Codex adversarial review found a HIGH the Claude pass missed plus 3 mediums:
- C1 (HIGH): gstack-decision-search --all returned every decide and IGNORED redact
events, so a redacted secret still resurfaced via --all until compact ran. --all
now excludes redacted (redact = expunge from every read path), still showing
superseded history.
- C-med: semantic (external gbrain) slug/snippet were printed raw — datamark them too
so a gbrain hit can't spoof role markers / fences into agent context.
- C4: semanticRecall fell back to an UNSCOPED gbrain search when no curated-memory
source resolved, pulling code/doc corpora mislabeled as 'related decisions'. Now
returns null (degrade) when there's no worktree-backed memory source.
- C5: validateDecide scanned only decision/rationale/alternatives; branch and issue
are stored + surfaced (raw via --json), so include them in the injection+secret scan.
C2 (snapshot staleness) / C3 (compact TOCTOU residual): accepted for a single-user
store — atomic appends never lose the event, rebuilds self-heal, and the compact
size-recheck leaves only a sub-ms window; full append-locking would break the
lock-free append design.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adversarial review (Claude subagent) found a CRITICAL the specialist pass missed:
- F1 (CRITICAL): 'Human:'/'Assistant:' turn-prefixes bypassed BOTH the write-time
denylist AND datamark(), landing verbatim in agent context inside the trusted
ACTIVE DECISIONS fence. Add 'human:' (+ 'disregard previous', 'from now on') to
the shared denylist, and have datamark() neutralize Human:/Assistant:/System:/User:
turn-prefixes (ZWSP) at the render boundary.
- F2: datamark() only stripped ASCII C0; extend to Unicode line terminators
(U+0085/2028/2029) and U+007F so 'strip newlines' actually holds.
- F3: validateDecide blocked only HIGH secrets; MEDIUM-tier PII (e.g. SSN) persisted
silently and synced cross-machine. The store is non-interactive (no confirm path),
so fail closed on MEDIUM too.
- F4: compact() was a lock-free read-modify-rewrite that could clobber a concurrent
append (lost decision). Add an O_EXCL compact lock + a pre-rename size recheck that
aborts untouched (skipped=true) if an append landed; caller re-runs.
- F7: filterByScope unknown/garbage scope fell through to 'return true' (leaked into
every context); fail conservative (false).
F5 (pid reuse) and F6 (pgrep over-match) are intentionally left as-is: both fail SAFE
(over-refuse sync); making them precise would introduce a fail-DANGEROUS path
(allowing sync during a real autopilot). True disambiguation needs gbrain to stamp the
lock with a start-time, which gstack doesn't own. F8 (compact moves history to archive)
is by design.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Addresses the pre-landing review findings (all INFORMATIONAL, no criticals):
- security: datamark resurfaced decision text at the render boundary
(lib/gstack-decision.ts datamark() — neutralizes code fences, --- banners,
<|role|>/</system> markers, control chars, newlines). Applied in
gstack-decision-search human output so stored text can't masquerade as
instructions in Context Recovery (codex hardening #3 / AC #7). --json stays raw.
- DRY: extract resolveSlug/gitBranch/flagValue to lib/bin-context.ts; both
decision bins use it instead of duplicating the helpers.
- compact(): batch the archive append (one write, not N) and shrink the
mid-compact crash window; simplify the opaque branch/issue ternary.
- coverage: learnings-log injection rejection (D2A wiring), search --recent/
--scope + NaN-safe --recent, datamark-applied, unparseable lock body,
compact-empty, corrupt-snapshot degrade.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
writeSnapshot/readSnapshot/rebuildSnapshot give an O(active) bounded read for the
session-start hot path (D1A). compact() rewrites the log to active, archives
superseded decisions for history, and EXPUNGES redacted ones (dropped, never
archived) so an accidentally-captured secret leaves the store for good.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
decide/supersede/redact events on lib/jsonl-store; active set is computed (no
mutable status), dangling refs tolerated. Free-text is injection-checked and
redact-scanned on write (HIGH secret -> reject). Scope filter (repo/branch/issue)
for relevant resurfacing. File-only + reliable; gbrain not required.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>