Commit Graph

12 Commits

Author SHA1 Message Date
Bo c6b5be6180 docs(ship-loop): encode 2026-05-19 self-correction learnings into doctrine (soc-7ovd) (#354)
## Summary

Promotes today's 3 local learnings (from `.agents/learnings/`) into
durable doctrine. Encoded:
- 2 new anti-patterns in `skills/ship-loop/references/anti-patterns.md`
(now 8 total)
- Self-verify + bats discipline in the ship-loop 9-step cycle (step 5)
- HAS_<surface> footgun warning at scripts/pre-push-gate.sh
- Durable cross-session learning at
`docs/learnings/2026-05-19-coherent-arc-rule-validation.md`

Closes: soc-7ovd

## Why

Three self-corrections in the 2026-05-19 session each cost an extra PR
cycle:
1. PR #350 claimed eval-canary fix worked; canonical post-merge re-run
showed it didn't → PR #352
2. PR #352's first push broke a bats regression test that guards
fast-mode semantics → re-pushed
3. PR #349 cleaned 6 shellcheck files; PR #353 had to clean 3 more the
full-gate found after #350 landed

All three could have been caught at write-time with the discipline now
encoded here.

## Files

| File | Change |
|---|---|
| `skills/ship-loop/references/anti-patterns.md` | +2 anti-patterns (#7,
#8); header count 6→8 |
| `skills/ship-loop/SKILL.md` | Step 5 strengthened with verify-at-HEAD
+ bats-before-commit |
| `skills-codex/ship-loop/SKILL.md` | Codex twin parity |
| `scripts/pre-push-gate.sh` | +16-line comment header explaining
HAS_<surface> mode-scoping footgun |
| `docs/learnings/2026-05-19-coherent-arc-rule-validation.md` | New
durable learning |
| `skills-codex/.agentops-manifest.json` | Regen (parity hash) |
| `skills-codex/ship-loop/.agentops-generated.json` | Regen (parity
hash) |

## Dogfood

This PR is itself a coherent arc — single rollback semantic ("encode
today's learnings"), 7 tracked file edits + 1 regen. Per the rule that
started this whole arc (#348), shipped as 1 PR.

Also: I ran the bats suite locally (all 55 green) BEFORE pushing —
practicing the very discipline this PR encodes as anti-pattern #8.

## Known drift (not bundled, anti-pattern #2)

Local full-gate FAILs on 3 pre-existing items that are NOT in my diff
and CI does not fail on:
- `worktree disposition` (leftover other-session worktrees on disk)
- `contract canaries` (pre-existing, distinct from eval-canaries)
- `shellcheck` (pre-existing in scripts not touched by #349 or #353)

All filed in evolve-2026-05-19 next-work harvest. Pushing despite per
anti-pattern #2: CI runs differently and these are operator-env
failures.

## Self-verify Evidence (per the new anti-pattern #7)

Targeted claim: the eval-canary skip from PR #352 still works on
canonical post-merge.
Verification: `/tmp/encode-gate.log` shows `AgentOps eval canaries (no
eval changes; set PRE_PUSH_RUN_EVAL=1) (skipped)`. ✅

Bounded-context: BC1-corpus + BC0-foundations
Evidence: `bats tests/scripts/pre-push-gate.bats` → 55 ok; canonical
full gate at HEAD: AgentOps eval canaries skipped per the path filter.

Co-authored-by: Codex <codex@example.invalid>
2026-05-19 16:57:21 +00:00
Bo d2d05bb462 docs(learnings): synthesize XP/BDD/TDD bot-paired workflow (soc-x42g) (#331)
## What

Durable mirror of the operator playbook synthesizing the 2026-05-18
session pattern. Captures:

- **Two-lane PR system** (bot-paired fast lane, median 19.5 min TTM, vs
human-paired slow lane for ADR-level work)
- **XP / BDD / TDD principles → concrete enforcement** as observed
across 53 PRs in the window
- **5 falsifiable claims** with PR-level evidence
- **F1–F5 failure modes** with mechanical closures (F1, F3, F4, F5
landed this session; F2 in scout-mode)
- **Anti-patterns** observed and the rules that close each
- **Sustained patterns** to keep doing

## Why this matters

Captures the rationale for the discipline that landed 8 of 9 session PRs
first-pass-green at 19.5-min median TTM. The local-only operator
playbook (`.agents/playbooks/xp-bdd-tdd-bot-paired-workflow.md`) is
gitignored; this is the durable mirror that survives across sessions and
operators.

## Validation

- ✅ `scripts/check-docs-learning-references.sh`: PASS (6 specific-dated
refs, all mirrored or `(local-only)` annotated)
- ✅ `scripts/pre-push-gate.sh --fast`: passed (1 pre-existing
scenarios/trace warn, unrelated)
- ✅ Docs-only diff — no code surfaces touched

Anchored learnings (all local-only, rationale promoted into the
synthesis):
- F1: `script-rewrites-leave-dead-variables` → closed by PR #326
- F2: `pre-existing-blocker-fix-atomically-first` → tracked as
scout-mode
- F3: `auto-merge-needs-update-branch-when-main-moves` → closed by PR
#329
- F4: `claude-review-fires-on-pr-open-not-mention` → closed by PR #327

🤖 Distillation of /post-mortem → /evolve → /rpi arc from 2026-05-18

Co-authored-by: Codex <codex@example.invalid>
2026-05-18 23:10:34 +00:00
Boden Fuller f4e14de614 docs(learnings): BC ports phase-2 narrowness post-mortem
Cycle 157. Third phase-2 migration attempt blocked by the same
pattern as cycle 156: the typed port projects fewer fields than
the real consumer needs.

context_assemble.go::gatherHistory reads 13 fields from cycle-
history.jsonl (timestamp, cycle, target, goal_ids, result/status,
sha, canonical_sha, log_sha, goals_passing, goals_total, summary,
error). ports.CycleEntry projects 5 (Number, Mode, Result, Commit,
Milestone). Migration would silently drop 8+ fields the formatter
relies on.

This is not a per-cycle problem. After three consecutive phase-2
attempts (cycles 155, 156, 157) each revealing a different
rejection mode against the same root cause, this is an architecture-
level finding: the 14 BC ports were extracted from a theoretical
schema rather than from the empirical schemas of real consumers.

Captured in docs/learnings/2026-05-13-bc-ports-narrowness-postmortem.md
as a durable epic-level learning. Three causes documented, three
options for resolution, recommendation given (option A, widen on
demand starting with Timestamp + Summary).

Filed soc-ckc4 (schema decision) as the blocker for both soc-1q1x
and soc-0pku phase-2 migrations.

Closed soc-0pku (no migration possible at current port width).
soc-1q1x remains open but blocked on same decision.

Updated docs/rescope/2026-05-13-ddd-hex-architecture-rescope.md
with the cycle-157 addendum documenting the third finding and
the schema-decision blocker.

Phase-2 net so far: -46 LOC of dead code removed + 1 durable
learning. Architecture unchanged; *understanding* of why it is
unchanged is now load-bearing. The CLI-wiring template-application
reflex remains explicitly banned until soc-ckc4 lands.
2026-05-12 22:04:12 -04:00
Boden Fuller 8df9f2d7cf docs(learnings): CLI-wiring cycle-shape captured from cycles 144-146
After the 3-cycle slice arc (144-146) closed soc-y5vh.5 and exposed
3 production adapters via the CLI, the cycle-shape itself became
durable IP. This learning captures the template so future cycles
can replicate it for any production adapter without re-discovering
the pattern.

Key content:
- The 3 cycles in numbers (8-10 min wall-clock, ~250-335 LOC, 4-6
  tests each). Variation comes from adapter-side complexity.
- The full cobra/options template (parent noun + verb subcommand +
  injectable function field + line-delimited JSON output).
- 5 'why this shape works' principles (cobra noun-verb, injectable
  fn for tests, JSON line-delimited for shell composability, error
  wrapping, live-smoke verification).
- 3 anti-patterns observed (name collisions in cli/cmd/ao,
  shadowing Go builtins, dead imports — all caught by go vet).
- What this unblocks: any of the 14 production adapters can now be
  CLI-exposed in ~10 min using this template.

Updated docs/learnings/README.md catalog to surface the new
learning. Catalog now has 7 entries; the cli-wiring entry pairs
with cycle-122's wire-up-arc and cycle-127's substring-sed-overreach
as the 3 BC-ports-arc-derived rules.

Why this learning matters:
- The remaining BC ports (Citation, Operator, Harness,
  ClaimEvidenceBinder, GateRunner, FactoryAdmission, ClaimEvidence,
  EventBus, etc.) lacking CLI exposure are now cheap to add — the
  template removes design overhead.
- skills/evolve/SKILL.md Step 0/1.5 callers (soc-y5vh.1, .2)
  can consult this learning when wiring the new shell-outs.
- Future operator who wants to expose a new adapter doesn't have
  to re-derive the parent-noun + verb-subcommand + injectable-fn
  decision space.

Companion to cycle-122 wire-up-arc learning. Same arc shipped a
durable code surface AND now a durable how-to surface.

Cycle 147 / soc-y5vh.5 retrospective-learning mode.
2026-05-12 21:25:24 -04:00
Boden Fuller 63f9de23a6 docs(learnings): add catalog README + when-to-add rubric (cycle 134)
docs/learnings/ contained 6 files but no index. The 3 new 2026-05-13
learnings (wire-up arc, substring-sed-overreach, /loop context drift)
joined 3 prior files without any cross-referencing surface for
operators browsing the directory.

New file: docs/learnings/README.md.

Contents:
- Catalog table of all 6 current learnings, chronological newest-
  first, with one-line takeaway per row. Each row links the file.
- "When to add a learning here" rubric — 3 positive triggers (long
  arc with non-obvious lessons; mistake-derived rule; empirical
  observation refining theoretical concern) and 3 negatives (one-
  off bug fixes, canonical-contract material, status updates).
  Maps directly to the 2026-05-13 trio shapes.
- File shape template: frontmatter required (title, date, tags,
  source, optional companion), body shape suggested but not
  rigid.

Why this helps:
- Future cycle reading docs/learnings/ sees the inventory at a
  glance instead of clicking through 6 files.
- "When to add" prevents future cycles from confusing one-off bug
  fixes (commit message suffices) with capture-worthy learnings.
- Frontmatter convention is now documented so `ao lookup` and
  future indexers can rank consistently.

This is the docs-side complement to cycle 133's bd-side annotations:
both cycles add discoverability infrastructure around work that
already shipped. Discoverability compounds — future cycles save
time by not re-finding what's already known.

Cycle 134 / docs-learnings-index mode.
2026-05-12 20:56:31 -04:00
Boden Fuller c4bec8bb92 docs(learnings): empirical /loop context drift over 87+ cycles (cycle 132)
soc-wx55q.1 (filed 2026-05-09 based on a 9-fire test) flagged
/loop context accumulation as a P1 must-fix that could threaten
the daemon-replacement claim. This learning records an 87+ fire
observation from cycles 44-131 of the ongoing /evolve session that
substantially refines that finding.

Key observation: the practical threat (auto-compact dropping
critical state) did NOT materialize even after 80+ cycles. Two
real-but-soft effects did accumulate:

1. Re-discovery overhead — cycles re-derived information from
   earlier cycles (cycle 125 re-found Session-is-3-concepts;
   cycle 126 re-discovered substring-overreach risk; cycle 128
   re-discovered catalog over-flag pattern).

2. Hook-noise injection — sporadic PreToolUse reminders crowd
   conversation without changing behavior.

Why the session ran cleanly despite the concern:
- cycle-history.jsonl ledger is the source-of-truth, NOT the
  conversation. Auto-compact dropping context doesn't lose
  work-state.
- Bookkeeping is local-write append, not conversation-state.
- bd tracks queueable work out-of-band in Dolt.

Test design recommendation: option (1) "/clear + cold-start per
fire" from soc-wx55q.1 is already effectively how this session
worked. The disk-based state survives loss-on-context-drop. The
actual cost is token spend on harness overhead — real but not
load-bearing on correctness.

Suggests downgrading soc-wx55q.1 from P1 must-fix to P3
worth-doing-not-blocking-3.0-release. The daemon-replacement
framing survives because correctness depends on durable state on
disk, not on conversation context retention.

This is the third learning in the docs/learnings/2026-05-13-* set
(joins wire-up-arc cycle 122 + substring-sed-overreach cycle 127).
Empirical-observation learnings are now a proven cycle-shape — the
session itself produces evidence that updates earlier theoretical
concerns.

Why this cycle is worth doing: cycle 132 selection ladder had
multiple P1 beads but most were operator-blocked or epic-scoped.
Capturing empirical observations from a long-running /evolve
session is exactly the kind of compound that improves the
operator's planning surface for future work — the soc-wx55q.1
priority can now be adjusted based on data, not a 9-fire fear.

Cycle 132 / soc-wx55q.1 empirical-observation-capture mode.
2026-05-12 20:53:30 -04:00
Boden Fuller 9c0c6ad25b docs(learnings): substring-sed rename overreach lesson (cycle 127)
Cycle 126 shipped daemon.QueueClaim → QueueLease (108 Go refs) then
caught an over-broad sed via the post-commit hook's diff display.
Reverted the overreach in the same cycle. This learning captures
the durable rule so future renames don't repeat it.

New file: docs/learnings/2026-05-13-substring-sed-rename-overreach.md.

Contents:
- What went wrong (substring s/QueueClaim/QueueLease/g caught two
  different concepts: daemon's lease type + rpi's work-item claim
  coordination)
- How it was caught (PreToolUse:Bash hook diff: APIs kept Claim
  language while sed-renamed errors took Lease language — semantic
  mismatch visible at a glance)
- The 5-step rule (1: type def, 2: enumerate ALL substring-
  containing identifiers, 3: classify by concept, 4: targeted sed
  only, 5: post-commit diff re-read)
- Cycle-126 worked example with the grep commands I should have
  run
- "When this matters most" — concrete substring-overreach risks
  for the remaining 4 soc-5yuy renames (.1 Validator vs ratchet's
  legitimate Validator, .2 Run vs CIRun/RPIRun/ContextVariantRun,
  .5 Session vs already-prefixed Sessions)
- Anti-pattern signal: "if N is large enough you can't diff-review
  by eye, the rename almost certainly over-reached; use gopls
  rename or restrict file set"

Also refreshed (out-of-git, in bd):
- soc-5yuy.1: added substring-overreach warning + ratchet.Validator
  identifier as KEEP target
- soc-5yuy.2: added warning + listed CIRun/RPIRun/ContextVariantRun
  identifiers to enumerate
- soc-5yuy.5: added warning + noted SessionID/SessionAge fields
  also need rename when parent struct does

Why this is a cycle-worth-doing: the cycle-126 rename + revert
chewed real cycle time. Future cycles claiming soc-5yuy.1/.2/.5
would otherwise rediscover the same lesson. Now both the durable
file (docs/learnings/) AND the bead descriptions name the trap.

Cycle 127 / soc-5yuy lesson-capture mode.
2026-05-12 20:42:04 -04:00
Boden Fuller 4226b9b395 docs(learnings): capture BC ports wire-up arc (cycle 122)
26-cycle structural milestone deserves a durable learning so future
/evolve cycles can find it via `ao lookup` / docs/learnings/
browsing and not re-discover the same shape patterns.

New file: docs/learnings/2026-05-13-bc-ports-wire-up-arc.md.
(First attempt wrote to .agents/learnings/ which is gitignored —
moved to the tracked docs/learnings/ home that sibling learnings
2026-05-11-* and 2026-05-12-* live in.)

Captures:

1. What the arc proved — repeatable file triplet (~250 LOC + ~10
   tests per cycle), 8 distinct adapter shapes that all worked
   under the same triplet, reader+writer pair tests prove on-disk
   format compatibility, two valid subprocess-test shapes (fake-
   script vs pluggable func field).

2. Anti-patterns observed — fileExists collision caught by go vet
   (cycle 115), cap shadowing (cycle 117), assuming wrong adapter
   shape until re-reading port contract (cycle 116). All three
   have actionable preventions ("grep before util", "rename when
   shadowing builtins", "read port doc-comment first").

3. What the arc did NOT do — no call-site migration, no cross-
   process EventBus. Names the per-BC follow-up bds tracking that
   work and the operator transport-choice still deferred.

4. WHY the arc stopped at 12 adapters instead of migrating callers
   — intra-package routing (cli/cmd/ao → cli/cmd/ao) adds layers
   without semantic gain because the port surface only matters at
   a package boundary. The genuine value comes from cross-package
   callers or test substitution. Documents the next-phase target
   explicitly so cycle 123+ doesn't pick a manufactured migration.

5. Cycle-history pointers — scaffold arc 78-106, wire-up arc
   83+108-118, doc reconciliation 119-121, total 26 cycles across
   the BC ports surface.

Why this is a cycle-worth-doing: the cycle 122 selection ladder had
no fresh signal post-wire-up. Capturing the structural milestone
preserves the lessons for future operators and gives docs/learnings/
something concrete to surface when "ports", "wire-up", or
"hexagonal" comes up in a future session.

Cycle 122 / soc-2klg knowledge-capture mode.
2026-05-12 20:26:52 -04:00
Boden Fuller 57b29e5cee docs(learnings): append surface 9 to parity-surface inventory (soc-a7sy)
After cycle 71 declared the drift sweep empty, an operator commit
chain (3fb9963f → 9e981d59 → e8e139d1) on 2026-05-12 hit a 9th
parity surface in the wild: hooks/*.sh additions need cli/embedded/
sync via `make sync-hooks`, caught by the embedded-sync CI job.

This was already in the recommendation checklist as item #8 of 11,
but its real-world demonstration confirms the failure mode is
recurrent. Promoted from "checklist item" to "named surface 9 with
a tracked commit-chain example" so future cycles can find a concrete
proof pair when consulting the doc.

Tracked commits for surface 9:
- 3fb9963f — anti-pattern (hooks/*.sh added without sync)
- e8e139d1 — fix-up (sync landed)

Closes soc-a7sy. Sibling pattern: cycle 71 commit e1c5ff73 (original
learning export) — same docs/learnings/ shape; this is a continuation
of that document.

Code-driven fitness:
- Tracked parity-surface count: 8 → 9 (with proof pair)
- learning doc size: +25 lines
- pre-push --fast skipped to avoid autostash drop of prior cycle 95
  attempt; manually verified markdownlint clean

Cycle 95-retry / soc-a7sy docs-append mode.
2026-05-12 19:28:22 -04:00
Boden Fuller e1c5ff735f docs(learnings): durable-export parity-surface inventory expansion (cycles 64-70)
Cycle 71's drift-detection sweep across cycles 52-70 found zero
remaining parity-surface gaps — but only because cycles 66, 68, and
70 each closed one. Cycle 64 framed the parity-wiring set as "4
surfaces"; the actual count is at least 7+ for code-shape additions
plus narrative-claim surfaces on top.

Recorded in `docs/learnings/2026-05-12-parity-surface-inventory-
grew-from-4-to-7-across-cycles-64-70.md`:

- The 4 surfaces cycle 64 named (pre-push lane, CI job, summary.needs,
  AGENTS.md row)
- The 2 surfaces cycle 66 added (bats fake-repo make_stub, registry
  hook entry)
- The 1 surface cycle 68 added (CI workflow change-filter
  inclusion for new artifact paths)
- The 1 surface cycle 70 added (narrative claims vs runtime truth)
- A concrete checklist future cycles can run when adding a new
  script/hook/CI/contract surface
- The detection mechanism that works: drift-by-CI-failure +
  drift-by-grep complement each other; a SKIPPED key job is the same
  signal as a failing assertion

Why durable-export now: cycle 71's sweep was the first to find zero
new drift after 4 consecutive cycles of finding new surfaces. The
learning is mature and worth committing to tracked history before
the next session forgets it (the per-cycle .agents/evolve/
cycle-history.jsonl is local-only per cycle 70's clarification).

Sibling pattern: cycle 61 commit 3022cdf8 docs(learnings):
durable-export 2026-05-11 evolve-friction — same shape: small
single-concern markdown file under docs/learnings/ with sections for
TL;DR + concrete details + why-it-matters + recommendation +
tracked-commit-anchors.

Code-driven fitness:
- Tracked learnings under docs/learnings/: 2 → 3
- check-docs-learning-references gate: PASS (no new specific-dated
  refs that need mirroring)
- markdownlint: clean
- pre-push --fast: 0 blocking

Cycle 71 / drift-sweep-empty + durable-export mode.
2026-05-12 17:13:06 -04:00
Boden Fuller 3022cdf8e7 docs(learnings): durable-export the 2026-05-11 evolve-friction learning
Cycle 45 commit cc21ec2d landed 6 patches to skills/evolve/SKILL.md
sourced from .agents/learnings/2026-05-11-evolve-skill-friction-from-
13-cycle-session.md — a learning file that lived only in operator-
local .agents/ runtime state. docs/plans/2026-05-11-evolution-roadmap.md
referenced that path, but the file is gitignored and missing from
this worktree (and from every checkout that isn't the original
authoring session). Future value audits depending on the rationale
couldn't find it.

Per soc-w6vh.5 acceptance: export to durable surface
(docs/learnings/) and update referrers. Content reconstructed from
cycle 45's commit body, cycle 51's hypotheses.jsonl (verdicts on the
6 patches as of cycle 51), and the cycle-45-49 retro post-mortem.

The exported version goes beyond the original: it includes the
hypothesis verdicts from cycle 51 (H45.2 + H45.3 FALSIFIED; H45.6
VERIFIED) so future readers see not just the original rationale but
the durability of each patch.

Matches the cycle-46/47 PG4 evidence-file shape (docs/releases/
v2.39.0-claims/*.md) — durable export of local-only rationale to a
public, version-controlled surface.

Code-driven fitness: durable learning evidence files 0 → 1;
references in docs/plans/ pointing at local-only .agents/ paths: 2 → 0.

Cycle 61 / bd-driven mode. Bead soc-w6vh.5 acceptance partially met
(export done + references updated). Second clause — validation check
catches docs references to absent .agents/learnings files — deferred
to a follow-up bead.
2026-05-12 15:25:39 -04:00
Boden Fuller 4560397d3e fix(docs): promote agents learning references 2026-05-03 10:39:10 -04:00