Commit Graph

21 Commits

Author SHA1 Message Date
boshu 568bbcef2d fix(ci): green 5 pre-existing main-wide gate failures
The same gate set failed on every open PR and drove all 16 nightly-failure
issues. Each root-caused via isolated-worktree reproduction of the live CI
jobs, then fixed minimally:

- correctness: check + propagate the discarded json.Marshal error in
  plan-pawl --json and yield tokens --json (planning-rule f-2026-04-29-002).
- lint: 3 markdownlint violations in pre-existing audit docs (MD004 leading
  "+" continuations, MD037 skills/* glob emphasis).
- security: dual #nosec + nosemgrep on 4 gosec/semgrep false positives in
  local-CLI code (G404 e-exploration RNG, G101 message-type sentinel, G122
  corpus-walk I/O) -- not a dependency CVE; per .claude/rules/go.md.
- skills-integrity: scope the broken-symlink scan to the shipped dirs
  (skills hooks lib scripts), matching the pre-push gate, so the intentional
  root CLAUDE.md -> AGENTS.md symlink is not falsely flagged.
- go-gate-shadow: add the 4 post-parity job-scoped blocking scripts to the
  deferredWorkflowScripts allowlist (--require-workflow-parity missing_blocking
  4 -> 0); strengthen the plan-pawl JSON test (command/test pair).

contracts-sync + skill-gates were already green on main (no change).
2026-06-25 08:59:50 -04:00
boshu 61b3f5286a fix(membrane): ao yield tokens parses Codex transcripts too (cross-family REFUTE)
Round-2 cross-family review (Codex) caught that the command advertised
"Claude Code or Codex" transcripts but deriveTranscriptTokens only summed
message.usage (the Claude shape). A real Codex transcript returned 0 0 —
and Codex is the default runtime on this machine, so reconcile would have
silently recorded zero spend for Codex-produced work.

Codex reports a CUMULATIVE total_token_usage on each token_count event
(input_tokens already includes cache; total = input + output), so the LAST
one is the session total — NOT a per-message sum.

- parser: capture token_count's total_token_usage into the last-wins
  ParseResult.FinalUsage (folded in processLine, never added to the summed
  message list).
- ParseResult.TokenTotals() picks the right aggregation per runtime: Codex
  cumulative FinalUsage, else Claude per-message SumUsage (dedup-by-id).
- deriveTranscriptTokens + forge_tier1 use TokenTotals(); the malformed
  guard now treats a Codex transcript with FinalUsage (few messages) as parseable.

Verified on a real Codex session (32397/40 == ground-truth last total) and
the real Claude fixture (10946330/228 unchanged). Tests use real Codex +
Claude persisted shapes. Full build/vet/test green.

Refs: age-membrane-memory-arch-tz2s.3.2
2026-06-20 14:42:13 -04:00
boshu df37c81b49 fix(membrane): dedup usage by response id + fail-open hardening (cross-family REFUTE)
A fresh-context cross-family review (Codex) REFUTED the E4 producer-truth
diff and caught three real defects self-review missed — the membrane
working as designed:

1. OVERCOUNT (severe): real Claude Code transcripts write one model
   response as several rows (thinking/text/tool_use) that ALL repeat the
   same usage block under one message.id. Summing every row inflated
   tokens 2-3x (real fixture: 26781956 vs correct 10946330). Fix: capture
   message.id (fallback requestId) in the parser; new types.SumUsage dedups
   by response id; forge_tier1 + deriveTranscriptTokens both use it.
2. reconcile HOLD/REFUTED path ignored AO_YIELD_TRANSCRIPT -> rejected
   spend silently recorded 0 (broke L/R loss accounting). Fix: shared
   derive_yield_tokens() helper used by BOTH the accepted and rejected
   emit paths.
3. malformed transcript returned success 0 0 (SkipMalformed) instead of a
   visible fail-open. Fix: deriveTranscriptTokens errors when content
   yields zero messages, so reconcile keeps the honest default.

Plus: dropped misleading omitempty on value-type StreamEvent.Usage;
real-fixture regression test locking the deduped total (10946330/228);
dedup + malformed + message.id capture tests using real persisted shapes
(the synthetic one-row fixtures hid the overcount — go.md fixture-fidelity).

Full build/vet/test green; reconcile bash + shellcheck clean.

Refs: age-membrane-memory-arch-tz2s.3.1, age-membrane-memory-arch-tz2s.3.2
2026-06-20 14:31:54 -04:00
boshu 4dc8f5ad0f feat(membrane): real per-bead token capture — kill the hardcoded 0 (age-membrane-memory-arch-tz2s.3.1)
Producer truth, E4.1. Tokens were silently dropped to 0 at every
observation point, making the medallion's bronze tier lossy.

- stream_events.go: parse the result event's usage block (StreamUsage:
  input/output + cache-creation/cache-read) with TotalInputTokens/
  TotalTokens helpers.
- stream_parser.go: wire usage into PhaseProgress.Tokens (live status
  now shows real tokens, not 0).
- types.TranscriptMessage: carry a per-message *TokenUsage.
- parser: capture the assistant message usage block from transcripts.
- forge_tier1.deriveSessionMeta: sum real TokensIn/TokensOut across
  messages (killed the 'not tracked in v1' hardcoded 0) — the bronze
  capture E4.2 (bronze->silver) will emit.

TDD: token tests added at stream, parser, and bronze-ingest layers; all
red before, green after. Full cmd/ao + parser + types + llm green.

Refs: age-membrane-memory-arch-tz2s.3.1
2026-06-20 14:01:44 -04:00
Claude cbeb606831 perf(cli): finish ASCII fast-path sweep across remaining truncate sites
Completes the sweep started in cycles 1-4. Applies the same byte-length
upper-bound fast-path to the four remaining rune-safe truncation sites:

- internal/search/search_cass.go TruncateContext
- internal/parser/parser.go Parser.truncate
- cmd/ao/contradict.go truncateSnippet
- cmd/ao/extract.go truncateForPrompt

All call sites now follow the same pattern: if len(s) <= max, return s
without allocating a []rune slice. Behavior is unchanged for inputs
whose byte length exceeds max (the rune-count branch still fires).
2026-04-17 02:58:14 +00:00
Claude 8dca64ffb1 perf(parser): ASCII fast-path for truncateForError
When the input byte length already fits within maxLen, the rune count
cannot exceed it either (bytes >= runes). Short-circuit before the
[]rune allocation. Adds multibyte test cases proving both the fast-path
(bytes==runes), the rune-count fit case (bytes>maxLen, runes<=maxLen),
and the truncation case.

Closes finding: ag-yht / Add ASCII fast-path comment to truncate()
2026-04-17 02:45:14 +00:00
Boshu2 5cf8f7b22f test: restore parser coverage ratchet 2026-03-22 10:06:37 -04:00
Boshu2 e5b4936724 fix: align ao search with forged session history 2026-03-22 09:56:37 -04:00
Boshu2 e442a414a8 fix(tests): push internal packages to 100% coverage with error-path tests
Add comprehensive error-path tests across all internal packages and cmd/ao.
14 packages now at 100% statement coverage; 4 remaining packages at
98-99% ceiling (provably unreachable defensive code).

Key changes:
- Add injectable test hooks (getwdFunc, marshalJSON, openFileFunc, etc.)
  to cover OS-level error branches unreachable on macOS
- Cover deferred f.Close() errors, json.Marshal failures on typed structs,
  filepath.Walk errors, and crypto/rand.Read fallbacks
- Add Linux-only build-constrained tests for filepath.Abs double-failure
- Fix flaky TestMergeWorktree_UntrackedFileDirtyRepo (100ms -> 5s timeout)
- Split ratchet_extra_test.go into per-source test files per convention
- Remove duplicate test declarations from prior agent merges
2026-03-11 12:33:52 -04:00
Boden Fuller 5c25849dc8 fix(goals/parser): harden edge cases — paired backtick strip + rune-aware truncation
- markdown.go: replace strings.Trim(s, "`") with paired-backtick check in
  parseGateRow; asymmetric/lone backticks are now preserved instead of
  being silently corrupted or data-lost
- parser.go: truncate() now slices at rune boundaries ([]rune) to avoid
  splitting multi-byte UTF-8 chars (CJK, emoji) and producing \uFFFD
- Tests: +3 adversarial cases (asymmetric, single-backtick, matched-pair)
         +1 Unicode truncation case (CJK at rune boundary)

Closes: ag-yht.1, ag-yht.2
2026-02-27 23:22:19 -05:00
Boden Fuller ec550df2fa fix(truncation): convert 6 functions to rune-safe slicing
Implements: ag-3f6.2
2026-02-27 07:28:27 -05:00
Boden Fuller 7bf761d367 fix: resolve golangci-lint debt — dead code, errcheck, gosimple, test factory
- Remove orphaned markItemConsumed doc comment (ag-jst.1)
- Fix 13 errcheck findings in test files: _ = Close(), t.Setenv (ag-jst.2)
- Fix 3 unparam findings: remove unused returns, use t param (ag-jst.2)
- Fix 5 production errcheck: extract appendNewlineIfMissing, annotate
  hash.Write returns in parser.go (ag-jst.3)
- Add phasedState test factory with 24 builder methods, migrate 19
  construction sites across 3 test files (ag-jst.4)
2026-02-22 09:58:56 -05:00
Boden Fuller 12bdfbbf54 evolve: cycle 117 -- split rpi_phased by concern, reduce CC in 5 cmd/ao functions
Split rpi_phased.go (2036 lines) into 4 concern-based files:
- rpi_phased_context.go: phase context setup, config resolution
- rpi_phased_processing.go: post-phase processing helpers
- rpi_phased_stream.go: streaming/watchdog logic

Reduce cyclomatic complexity via helper extraction:
- batch_forge.go: runForgeBatch 24→14
- context.go: readSessionTail 22→14
- index.go: checkIndex 20→14
- maturity.go: runMaturityExpire 21→14
- rpi_cleanup.go: findStaleRunsWithMinAge 21→14
- parser.go: remaining CC=7 helpers
- gate.go: remaining CC=7 helpers

All tests pass. Internal CC>=7=0, cmd/ao CC>=20=0.
2026-02-22 09:48:32 -05:00
Boden Fuller bf5e9e9121 evolve: extract helpers from metrics, parser, ratchet, and worktree
- Extract cite report formatting helpers (metrics_cite_report)
- Extract parser validation helpers (parser)
- Extract maturity transition helpers (ratchet/maturity)
- Extract validation rule helpers (ratchet/validate)
- Extract worktree cleanup helpers (rpi/worktree)
- Add research skill validation docs
2026-02-22 09:14:38 -05:00
Boden Fuller 456dbb17dc modernize Go to idiomatic 1.23: slices, cmp.Or, range, CutPrefix
Apply version-aware modern Go patterns across cli/cmd/ao/ and cli/internal/:

- sort.Slice → slices.SortFunc with .Compare() (19 in cmd/ao, 15 in internal)
- C-style for loops → for i := range n / for range n (18 conversions)
- default-value chains → cmp.Or (19 conversions across 11 files)
- HasPrefix+TrimPrefix → strings.CutPrefix (2 in internal)
- strings.Index+slice → strings.Cut (1 in internal)
- sort.Strings → slices.Sort (3 in internal)

All 18 packages pass with -race. Sourced from JetBrains go-modern-guidelines RPI.
2026-02-22 07:57:49 -05:00
Boden Fuller 3a5bc6f875 evolve: cycle 111 -- extract magic strings to named constants across 8 packages
Replace repeated string literals with named constants:
- context: item type constants (ItemTypeFailingTest, etc.)
- parser: message type and error classification constants
- goals: drift delta and measurement result constants
- vibecheck: severity and health classification constants
- storage: default slug constant
- ratchet: unknown value constant

Addresses goconst lint warnings for production code.
2026-02-22 05:42:46 -05:00
Boden Fuller 427ec40d6d evolve: cycle 87 -- extract extractToolResultContent from parseToolResult (8->3)
Split content extraction logic into a dedicated helper that handles
both string and array-of-text-blocks formats. parseToolResult drops
from complexity 8 to 3; new helper is 6.
2026-02-22 04:21:08 -05:00
Boden Fuller 8bddb92333 evolve: cycle 83 -- modernize interface{} to any across 16 files
Replace all 135 occurrences of interface{} with the any alias
introduced in Go 1.18. The module uses Go 1.23 so this is safe.
Zero behavior change -- any is a built-in alias for interface{}.
2026-02-22 04:07:27 -05:00
Boden Fuller a240d3acce evolve: cycle 79 -- extract classifyBlock from parseContentBlocks (9->4)
Move per-block type dispatch into classifyBlock. parseContentBlocks
now iterates and accumulates, dropping from complexity 9 to 4.
2026-02-22 03:59:57 -05:00
Boden Fuller 5cefa7cc1b evolve: cycle 78 -- extract processLine from Parse (9->6)
Move line parsing, error recording, and message accumulation into
processLine. Parse now focuses on scanning and checksum, dropping
from complexity 9 to 6.
2026-02-22 03:59:15 -05:00
Boden Fuller 37d4b5b2ae Merge branch 'codex/rpi-supervisor-cli' into main 2026-02-21 19:41:50 -05:00