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.
Cycle 156, phase-2 of the DDD/hex rescope.
First phase-2 migration attempt (soc-8fjo: metrics_health.go →
LoopReaderPort) surfaced a bigger finding than the rescope predicted:
the function we planned to migrate has zero production callers.
quality.LoadCycleHistory in cli/internal/quality/metrics_health.go
and its one-line shim cli/cmd/ao/metrics_health.go::loadCycleHistory
are defined, tested directly, and called by nothing else. Two tests
in cli/cmd/ao/metrics_health_test.go probe the dead path.
The right phase-2 move was delete, not migrate.
Removed:
- cli/internal/quality/metrics_health.go: LoadCycleHistory (23 lines)
+ now-unused bufio/encoding-json imports
- cli/cmd/ao/metrics_health.go: loadCycleHistory shim (1 line)
- cli/cmd/ao/metrics_health_test.go: TestMetricsHealth_LoadCycleHistory
+ TestMetricsHealth_LoadCycleHistoryMissingFile (~22 lines)
Net: ~46 lines of dead code removed. Full test suite green.
Drive-by fix while running the regression bundle: cobra_commands_test
TestCobraExpectedCmdsMatchRegistration was failing because cycles
144-154 added 6 new top-level commands (ci, citation, claim, harness,
loop, operator) without updating the expectedCmds list. That drift
was pre-existing, surfaced by running the full bundle. Added the 6
to both expectedCmds lists in the test.
Also surfaced (deferred, not done): cli/internal/lifecycle/defrag.go
::SweepOscillatingGoals keys on a 'Target' field that ports.CycleEntry
does NOT project. Worse, zero entries in cycle-history.jsonl have a
'target' field — the production sweep is a permanent no-op. Migration
to LoopReaderPort requires a schema decision (extend CycleEntry vs
re-target defrag at a different artifact). Filed as deferred under
soc-1q1x. Closing soc-8fjo (no longer applicable: target deleted).
Updated docs/rescope/2026-05-13-ddd-hex-architecture-rescope.md
with an addendum capturing both findings.
Operator-triggered rescope of the BC ports + production adapters + CLI
wiring arc (cycles ~80-154).
Key finding: zero non-cli importers of cli/internal/ports. The hex
architecture's outer ring (ports + adapters + CLI) is complete, but no
inner-ring consumer code routes through it yet. defrag.go,
metrics_health.go, and context_assemble.go still read
cycle-history.jsonl directly, bypassing the LoopReaderPort we built.
Declares the arc phase-1 complete (hex shape) and phase-2 pending
(hex adoption). Filed soc-1q1x, soc-8fjo, soc-0pku as the three
concrete phase-2 picks that prove the ports are load-bearing.
The rescope explicitly stops the CLI-wiring template cycle and
redirects /evolve to consumer-migration work. The 4 remaining
unexposed adapters (FactoryAdmission, ClaimEvidence, EventBus,
FindingCompiler) stay unexposed until real consumers need them —
adapter exposure is no longer the work.
Filed: soc-1q1x (defrag → LoopReaderPort), soc-8fjo (metrics_health
→ LoopReaderPort), soc-0pku (context_assemble → LoopReaderPort +
CorpusReaderPort).