Skip to content

0.14.65 — war-memory CLI correctness & lint completeness - #1173

Merged
Ljferrer merged 10 commits into
masterfrom
dev/2026-07-26-war-memory-cli-correctness
Jul 28, 2026
Merged

0.14.65 — war-memory CLI correctness & lint completeness#1173
Ljferrer merged 10 commits into
masterfrom
dev/2026-07-26-war-memory-cli-correctness

Conversation

@Ljferrer

Copy link
Copy Markdown
Owner

Campaign 2026-07-26-doc-truth-and-engine-hardening, plan 2 of 4. Both phases landed via /war --afk --ace. Plan 1 (#1166) is already on master, so this cuts from and lands to master with no stacking constraint.

Plan: docs/plans/2026-07-26-war-memory-cli-correctness.md · Red-team: docs/red-team/2026-07-26-war-memory-cli-correctness.md (CLEARED, 12 blocking findings patched) · Epics #1168, #1169 · Source issues #1145, #1135, #1154, #1147.

What lands

  1. cmdQuery --top-k/--budget guards (war-memory: cmdQuery --top-k/--budget keep the truthy-ternary silent-degradation shape --target just retired #1145) — a supplied-but-invalid space-separated value now exits 1 with empty stdout, stderr naming the flag and the received token, and no query-log line (the guard sits before walkCorpus, so refusal writes nothing). 8/8 refusal regressions, red pre-fix. The =-attached form (--top-k=abc) remains a known, still-silent, deliberately frozen residualparseArgv is frozen by ratified spec decision D10, and the Intent names it rather than waiving it.
  2. cmdLint recursive walk (war-followup: redaction lint (CI + new gate wrapper) never walks docs/learnings/archive/ — ~104 committed lessons unlinted #1135)lint <dir> now descends archive/. CI (memory-audit.yml) and the gate wrapper (war-memory-lint.test.sh) inherit it with zero edits (both byte-unchanged, checked from the task diff). Consumer-visible: a previously-green learnings tree with a nested violation will start failing — that is the lint doing its job.
  3. cmdArchive hub WARN slug-deduped (war-memory: archive's concept-hub warning counts a cross-root-dupe citer twice, disagreeing with inbound's slug-deduped count #1154) — the >= 2 predicate and the printed count now both come from new Set(hotInbound.map(r => r.slug)).size, and the noun is inbound citers. On a deduped count refs was false: a cross-root twin is 2 refs but 1 citer and is not a hub. Independently observed live by the Lead during a memory sweep before this plan ran.
  4. Lesson prose trued up (war-followup: RESOLVED-stamped tighten lesson body still prescribes the defective guard and cites a retired SKILL.md escape #1147) + a dated append-only amendment to ADR 0028 (whose verbatim WARN quote would otherwise have gone stale).

Unexecuted backstops

  • Backstop 1 — live-tree recursive lint: DISCHARGED. Re-run at the final tip 3885e9e: lint: clean over the full recursive docs/learnings/ tree (145+ archived files). Red-team narrowed this at round 0 — the task gate already runs it pre-merge and blocking, so End state 6 was re-filed HARD; only the gate→merge window was ever deferred, and CI re-checks it on this PR.
  • Backstop 2 — real-size --args live transport: PARTIALLY DISCHARGED. Both phases dispatched through the newly landed stage-workflow.mjs --args <file> CLI path (50,330 B and 32,414 B) with no Workflow args; the phases running at all is the transport observation. The ~104.5 KB class remains unobserved, so this is partial, not closed. Its second half — carrying both lesson corrections into the local memory root — was discharged in-run by the Phase 1 servitor, per red-team adjudication 3.

Notable during execution

  • Phase 1 held escalation on a post-merge gate-audit Major: End state 8's OLD-absent clause was false at the tip — the retired inbound refs literal survived on three live skills/ surfaces, including the operator-facing hub thresholds in skills/lessons-learned/SKILL.md, which thereby contradicted the tool this task converged. Reproduced by the Lead, then fixed at 086db74 rather than deferred: a plan End state may not be waived in prose (ADR 0017), and a follow-up would have left it false.
  • A prior launch held workflow-error at the Provision barrier — a red-team probe escape had left a repo-global integration branch that the barrier correctly refused (ADR 0003). Cleaned and relaunched fresh. Both incidents are now recorded lessons in this PR's docs(learnings) commit.

Residual risk (accepted, all named in the plan)

The =-attached flag form stays silent (D10); recursive readdirSync does not descend directory symlinks; an unreadable subdirectory skips its whole target fail-open. Two Nits landed unfixed and recorded: the release blurb renders the recursive call with the CLI argument name rather than the source identifier, and the plan Notes' three one-line residuals are unclaimed by any task slice.

🤖 Generated with Claude Code

WAR Test and others added 10 commits July 27, 2026 16:17
…rchive/

The tighten lesson was archived on 2026-07-27 (PR #1167, operator-directed
RESOLVED sweep), so Task 1.2's declared path no longer resolves. Archiving is
a move, not a deletion — the lesson stays FTS-queryable, so its inaccurate
zsh-fuse mechanism prose still misleads and still needs correcting.

Re-anchored in place rather than restoring the lesson to the hot set:
restoring would add its row back and push the projection over the 17,000 B
advisory that the same sweep just cleared (16,797 B, verdict ok).

The sibling cmdquery lesson is unaffected — still hot at its declared path.

Lead adjudication at the campaign decompose gate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- End state 1 + Purpose narrowed to space-separated flag values; the
  =-attached residual (D10, frozen parseArgv) lifted into the Intent as a
  named still-silent out-of-scope path instead of a Notes-only mention.
- Task 1.2 sweep + End state 9 greps made case-insensitive (grep -in),
  token-anchored — a re-cased straggler could previously false-negate.
- ADR 0028 quotes the hub-WARN verbatim: added to Task 1.1 Files with a
  dated append-only amendment; per-medium gate (NEW-present on the ADR,
  OLD-absent on live skills/ surfaces) added to End state 8.
- The existing spawn-the-CLI hub-WARN test pins the message bytes and reds
  on the noun flip: named as a required in-task edit; End state 8's
  stay-green clause narrowed to the inboundCiters unit tests.
- cmdQuery guard triple gets coupling comments both ways (cmdTightenPlan's
  --target block named as reference implementation).
- End state 3's explicit-defaults invocation built from imported constants,
  not hand-typed 10/4096 literals.
- End state 6 re-filed HARD (task gate runs the recursive live-tree lint
  pre-merge); backstop 1 narrowed to the post-gate window.
- Backstop 2 rewritten: in-run runner = Phase 1 servitor (recorded
  resolved-lesson-stamp convention); Lead Gate-2 duty to exclude the
  archived tighten slug from promotion (flat-copy would duplicate it hot).
- Contention note corrected: three siblings, not one; plan 4's README +
  version-slots.test.mjs Phase-1 overlap recorded with mitigation.
- Doc-sweep note widened to the WARN message string.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ings patched, sandbox escape contained

Round 0: 14 probes on-target (6 executed / 8 analyzed), 20 agents, opus/high.
8 gate blockers + 4 needsDecision patched into the plan at 4453863; round-1
re-verify confirms all 12 RESOLVED. 5 Minors absorbed by the same patches.

Incident: the ff-topology probe built its synthetic fixture in the shared
sandbox worktree (5 rogue commits + working-tree edits). Contained to the
disposable sandbox — real repo clean, remote tips unchanged; taint audit
shows every load-bearing finding anchored on unmutated surfaces; sandbox
restored and escape guard re-run exit 0 before the verdict.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
)

Three CLI correctness fixes, each bound at its owning verb's boundary:

- cmdQuery (#1145): --top-k and --budget get the three-way argv-boundary
  resolution #1059 ratified for tighten-plan's --target — absent ⇒ default
  (byte-identical flagless path), a positive finite string binds, anything
  else refuses loud (exit 1, stderr naming the flag and the received token).
  The guards sit above walkCorpus, so a refusal writes nothing: no query-log
  line, no prompt block. No integer check (D3 — --top-k 3.5 binds, mirroring
  --target's predicate exactly). parseArgv is frozen, so the =-attached form
  (--top-k=abc) remains the named, deliberately silent residual (D10).
  Three comment-coupled sites, no shared helper.
- cmdLint (#1135): the directory branch walks recursively, so the committed
  archive/ subtree is linted on every surface sharing the one invocation —
  CI (memory-audit.yml) and the gate wrapper (war-memory-lint.test.sh) both
  stay byte-unchanged. The catch { continue } fail-open is preserved.
- cmdArchive (#1154): the advisory concept-hub WARN counts slug-deduped
  citers for both the >=2 predicate and the printed number, converging on the
  inbound verb and tightenPlan's Floor 2; the count noun becomes
  "inbound citers" (the old noun would be false on the deduped count).

ADR 0028 quotes the WARN verbatim: a dated append-only amendment records the
new counting and noun; the historical quote stands (superseded, not rewritten).

Regressions (all red pre-fix, verified by reverting the source alone): eight
spawn-the-CLI refusal cases with per-case token fidelity plus no-query-log-on-
refusal, unchanged-path cases built from the imported DEFAULT_TOP_K/
DEFAULT_BUDGET constants, archive/-nested lint fixtures at both the CLI and
wrapper surfaces, and three hub-WARN dedupe cases (twin ⇒ no WARN, two distinct
⇒ 2, twin + distinct ⇒ 2 not 3). The existing hub-WARN CLI test is updated in
place — it pins the message bytes, so the noun flip reds it by design.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…amp (#1171)

Two committed-lesson corrections, sourced from the red-team report
(docs/red-team/2026-07-24-memory-tooling-hardening.md, Minors, "Purpose, zsh
threading") and spec §4 of docs/specs/2026-07-26-war-memory-cli-correctness-design.md
— not re-derived:

- tighten-target-flag-...-degradation-paths.md (archive/, moved there by the
  2026-07-27 RESOLVED sweep): failure-mode-3 now states the true fuse
  mechanism — zsh, lacking SH_WORD_SPLIT, does not word-split the unquoted
  ${TIGHTEN_TARGET:+...} expansion, so the whole replacement fuses into one
  argv word (`--target 2000`), which parseArgv keys as
  `{"target 2000": true}`; argv.target itself stays undefined. The "same
  silent outcome as never setting $TIGHTEN_TARGET" clause is kept verbatim
  (it was the accurate part). A case-insensitive grep for dropped/collapses
  now finds zero hits. The closing "Not yet extended to siblings" paragraph
  is rewritten past-tense as "Extended to siblings
  (war-memory-cli-correctness/1.1, #1145)", citing Task 1.1's landed
  cmdQuery guard by construct name.
- cmdquery-topk-budget-share-tighten-targets-pre-fix-truthy-ternary-shape.md
  (D9): description RESOLVED-prefixed; appended `## RESOLVED` section names
  Task 1.1's guarded cmdQuery resolution and its `refusal (#1145): --<flag>
  ...` test banner in war-memory.test.mjs. Per the ratified stamp
  convention the "deliberately left open" H1 and pre-fix code snippet stay
  frozen — the appended section is what corrects the record.

Hand-scan survey (both files, full body): zero additional paraphrase
stragglers beyond failure-mode-3 — matches the spec's own spec-time survey
result (the sibling lesson carries no zsh claim).

Redaction lint clean on both edited files.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…1171)

Absorb-disposition Minor findings from the task 1.2 audit:

1. [Minor] New RESOLVED prose misattributes the NaN --budget failure mode
   to selectForBudget's slice (it uncapped, it never emptied).
   Rationale: selectForBudget slices only on topK; budget is used in
   'bytes + size > budget' — with NaN that comparison is always false, so
   the loop never breaks and the block runs UNCAPPED, the opposite of
   empty. Fix: split the clause by flag — a NaN --top-k empties via
   slice(0, topK); a NaN --budget silently uncaps (the break never fires).

2. [Minor] 'bare/NaN --top-k had silently emptied the prefetch' — the
   bare flag gave a ONE-lesson block, not an empty one.
   Rationale: pre-fix a bare --top-k mapped to boolean true and
   Number(true) === 1 selected one lesson; only NaN/zero/negative values
   emptied the block via slice. Fix: split bare (one lesson) from
   NaN/zero/negative (emptied) in the archive lesson's 'Extended to
   siblings' paragraph, and mirror the same split in the sibling lesson's
   RESOLVED-prefixed description (the stamp convention's correction
   channel).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#1170)

Lead manual completion of a held:escalation phase. The post-merge gate-audit
(execution-evidence seat) found End state 8's OLD-absent clause false at the
confirmed tip: the retired WARN literal survived on three live `skills/`
surfaces, none of them exempt.

Reproduced by the Lead at 36e04d0 before acting — three hits, all real:
  skills/lessons-learned/SKILL.md:256, :257 (the Phase-3 hub-check thresholds)
  skills/lessons-learned/lessons-learned-doc-contract.test.mjs:88 (comment)

Not cosmetic. Those SKILL.md lines document `war-memory inbound`'s thresholds,
and cmdInbound dedupes by slug — `[...new Set(inboundCiters(...).map(r => r.slug))]`
— so on a deduped count `refs` is false: a cross-root twin is 2 refs but 1
citer and is NOT a hub. That is precisely the falsehood this plan retired, so
the surviving prose contradicted the tool it documents (ADR 0025 cascade class).

Verified the doc-contract test asserts on the `inbound <slug>` invocation and
the absence of the retired prose grep, never on the retired literal — so the
flip reds nothing.

Scope widening adjudicated by the Lead rather than deferred: End state 8 is a
plan End state, and a validation in neither the gate, a floor, nor the backstops
section may not be waived in prose (ADR 0017). Fixing it makes the End state
true; a follow-up issue would have left it false.

End state 8 now holds both halves at this tip: OLD-absent = 0 hits across
skills/, hooks/, agents/, CONTEXT.md, README.md; NEW-present verified in
war-memory.mjs (4) and ADR 0028's dated amendment.

Gate green: 990 JS tests, all shell tests, war-memory lint docs/learnings/ clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
All four release slots bumped in lock-step to 0.14.65, the next free patch:
plugin.json#version, marketplace.json#metadata.version and
#plugins[0].version, and the README ## Status token. Resolved from the live
slots at the Phase-1 landed tip 086db74 and origin/master (both 0.14.64), not
from any plan literal; version-slots.test.mjs green on all four checks,
including the monotonic floor (window max 0.14.64).

The Status blurb names the one consumer-visible behavior change first-class:
the redaction-lint walk is RECURSIVE, so a plugin user's previously green
learnings tree holding a violation under archive/ exited 0 before this release
and exits 1 now. Phrased as the walk being recursive and as a real new failure
with a remedy — never as "lints all archives clean" (the recorded
overstating-guard-semantics trap). Also enumerated: cmdQuery's --top-k/--budget
refusal guards (a supplied-but-invalid space-separated value exits 1 instead of
binding a degraded one; the =-attached form named as the frozen D10 residual)
and cmdArchive's slug-deduped hub WARN with its `inbound citers` noun, plus the
ADR 0028 amendment, the /lessons-learned threshold noun retirement, and the two
lesson truth-ups.

Two traps checked against the drafted prose, not assumed:
- Count word: "Three correctness fixes" is followed by exactly three numbered
  items; the one other count ("three comment-coupled sites") names its own
  members inline (--target, --top-k, --budget).
- The retired WARN literal is NOT reintroduced — README.md is inside End state
  8's OLD-absent grep scope (skills/, hooks/, agents/, CONTEXT.md, README.md),
  so describing the noun flip in the blurb would have re-fired the rename's own
  absence guard. Re-verified zero hits over that scope after the edit.

Code facts in the blurb were traced at the tip rather than copied from the
Phase-1 commit message: selectForBudget's records.slice(0, topK) empties on a
non-numeric or zero --top-k while a NaN --budget leaves the block UNCAPPED (the
`bytes + size > budget` break never fires), and parseArgv keys `--top-k=abc`
whole, leaving argv['top-k'] undefined. "Negative empties" was deliberately not
claimed — slice(0, -n) truncates from the end, it does not empty.

Gate: 990 JS tests pass, 27 shell suites pass (exit 0), including
war-memory-lint.test.sh linting the live docs/learnings/ tree clean with the
recursive walk active.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e-2 into dev/2026-07-26-war-memory-cli-correctness
Gate-2 promotion, deferred until phase 2 landed so the commit could not
strand phase 2's land CAS as land_stale (its integration branch was cut
from the pre-commit working tip).

- redteam-sandbox-probe-branch-residue-blocks-next-provision: a git-mutating
  red-team probe that escapes into a shared sandbox worktree leaves REFS
  behind that a working-tree reset --hard/clean -fd does not undo; a residual
  branch then collided with the next run's Provision barrier (ADR 0003).
- old-absent-gate-half-relies-on-unrecorded-hand-grep-fails-silently: in a
  per-medium NEW-present/OLD-absent retirement gate, the OLD-absent half had
  no committed assertion and rested on an unrecorded hand grep — which is the
  half that silently returned the wrong answer (caught at post-merge
  gate-audit, 3 live stragglers).
- release-blurb-quoted-code-literal-can-diverge-from-actual-identifier: a
  blurb quoting a call with the CLI argument name instead of the source
  identifier defeats the grep-the-rendered-literal verification this repo
  relies on.

EXCLUDED from promotion (red-team adjudication 3, fail-closed):
tighten-target-flag-has-three-independent-silent-degradation-paths — its repo
copy lives under docs/learnings/archive/, and promotion copies FLAT into
docs/learnings/, which would land it hot and duplicate the archived copy.
NOT promoted: cmdquery-topk-budget-share-… — Task 1.2 already corrected the
repo copy in place; the servitor only mirrored that correction locally.

Release slots re-verified at 0.14.65 before staging (#1083 hazard).
Redaction lint clean over the full recursive docs/learnings/ tree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant