Skip to content

docs(cc-249): spike result — assert_* consolidation decisions + file cc-252#146

Merged
screenleon merged 2 commits into
mainfrom
cc-249-spike
May 23, 2026
Merged

docs(cc-249): spike result — assert_* consolidation decisions + file cc-252#146
screenleon merged 2 commits into
mainfrom
cc-249-spike

Conversation

@screenleon
Copy link
Copy Markdown
Owner

Summary

PR-Spike of the CC-249 sequence (impl PR-B follows as a separate dispatch). New file docs/spikes/CC-249.md transcribes all PM decisions resolving the divergent assert_* helpers Explore surveyed across 14 test-*.sh files. Plus tail commit filing CC-252 — a CC-250 follow-up discovered while running /pr-gate on this branch.

Spike decisions (in docs/spikes/CC-249.md)

Q Decision
Q1 assert_exit signature (name, actual, expected) — majority (4 of 5 files); 1 outlier (test-check-docs-freshness) rewrites in PR-B
Q2 assert_contains Split into 3 separate named helpers: assert_file_contains (literal), assert_file_matches (regex), assert_string_contains (string-form). Self-documenting > flag-based per [[breaking-change-for-maintainability]]
Q3 Migration strategy Break-and-rewrite. No shim, no deprecation period. Internal test infra, bounded blast radius
Q4 assert_output_contains Merged into assert_string_contains with explicit-arg form (no hidden $LAST_OUTPUT global)
Q5 5 Uncertainties U1→PR-B audit, U2/U3/U5 scope-out, U4 resolved by Q4

Plus per-consumer migration matrix (14 rows) + Cost Estimate (harness +60–90 LoC / consumers –50 to –150 net / ~16 files touched / PR-B plan = 2 codex dispatches per CC-251 brief-splitting trigger).

BACKLOG row CC-249 flipped ⏸ deferred🟢 someday (per pm-schema: scoped + ready + no urgent driver, distinct from ⏸ "blocked / awaiting external input").

Process notes

  • Survey done by main-thread Explore (per [[feedback_design_survey_offload]] evidence framing); evidence passed to PM with Uncertainties section
  • Codex brief applied CC-251 patterns: expected_head_sha verified before first edit; apply_patch retry-cap constraint included; verbatim-as-attached-file N/A (brief touched only 2 files)
  • Brief was small (151 lines, 2 files in files: block) — no dispatch hang; codex completed in 34 sec
  • /pr-gate verdict: GO (critic approve + qa-tester pass, no findings). pr-gate.sh exit code came back 1 due to a CC-250 brief-template bug → codex wrote **Final: GO** (bold) instead of Final: GO (plain), failing the back-compat ^Final: (GO|NO-GO)$ grep. Verdict is correct; the parser fails on format drift. Filed as CC-252.

CC-252 follow-up

Tail commit (94e0de6) files CC-252 — /pr-gate brief template must specify Final: line is exact-format (no bold, at start of line). The CC-250 brief template inside scripts/pr-gate.sh (2 brief blocks: sequential + parallel synthesis) needs hardening + a regression test in test-pr-gate.sh. Will be implemented as a separate small PR.

PR-B roadmap (next, after this merges)

Per PM's plan in the spike Cost Estimate:

  • PR-B.1: harness additions + test-test-harness.sh self-test (~2 files, 60–90 LoC harness + 80–120 LoC tests). Single dispatch.
  • PR-B.2: consumer migration lockstep (~13–14 files, 5–15 LoC each, net –50 to –150 LoC). Single dispatch with verbatim-as-attached-file pattern for migration matrix per file (/tmp/cc-249-migration/<file>.md).

Test plan

  • bash pm/scripts/validate.sh BACKLOG.md 2>&1 | wc -l — parity 30 (CC-228 baseline)
  • spike doc has all 6 required sections + Cost Estimate per docs/spikes/README.md skeleton
  • BACKLOG CC-249 row: 🟢 someday + Result log pointer; pr cell stays pr:TBD
  • /pr-gate express — Final verdict: GO (critic approve + qa-tester pass, no findings) — gate script exit 1 is the CC-252 parser bug, not a real failure
  • git diff --stat: 3 files (docs/spikes/CC-249.md new, BACKLOG.md modified twice — CC-249 row + CC-252 add)

🤖 Generated with Claude Code

screenleon and others added 2 commits May 23, 2026 23:50
CC-249 spike completes investigation: decides API shape + migration
strategy for the divergent assert_* helpers Explore surveyed across
14 test-*.sh files. Impl follows in PR-B (2-dispatch plan documented
in spike Cost Estimate).

Decisions (transcribed verbatim into docs/spikes/CC-249.md):

- **Q1** assert_exit signature = `(name, actual, expected)` — majority
  (4 of 5 files); 1 outlier (test-check-docs-freshness) rewrites in PR-B
- **Q2** assert_contains splits into 3 separate named helpers:
  `assert_file_contains` (literal), `assert_file_matches` (regex),
  `assert_string_contains` (string-form). Per breaking-change-for-
  maintainability: separate names self-document intent
- **Q3** migration = break-and-rewrite. No multi-arity shim, no
  deprecation period. Internal test infra, bounded blast radius
- **Q4** assert_output_contains merged into assert_string_contains
  with explicit-arg form (no hidden $LAST_OUTPUT global)
- **Q5** 5 Uncertainties resolved (U1→PR-B audit, U2/U3/U5 scope-out,
  U4 resolved by Q4)

Includes per-consumer migration matrix + Cost Estimate
(~+80 to +200 LoC across ~16 files; net repo line count likely
negative due to local-helper deletions).

BACKLOG row flipped ⏸ deferred → 🟢 someday: impl is now fully
scoped, only sequencing gates PR-B. Per pm-schema, 🟢 someday is
the bare-token enum for "scoped, ready, no urgent driver".

Validator parity preserved at 30 (CC-228 baseline). No code change;
docs-only PR.

Brief applied CC-251 patterns: expected_head_sha verified before
first edit; apply_patch retry-cap constraint included; verbatim-as-
attached-file pattern N/A (brief touched only 2 files).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dening

Discovered while running /pr-gate on this branch (CC-249 spike):
codex applied prose markdown emphasis to the Final line as
`**Final: GO**`, but pr-gate.sh's back-compat parity check uses
`^Final: (GO|NO-GO)$` (no leading `**`), so the gate script exits 1
even though the verdict is GO.

CC-252 captures the brief-template hardening needed in the CC-250
(#144) brief inside scripts/pr-gate.sh. Out of scope for this PR
(CC-249 spike doc); filed for separate impl.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@screenleon screenleon merged commit 5b0437e into main May 23, 2026
16 checks passed
screenleon added a commit that referenced this pull request May 23, 2026
* fix(cc-252): harden /pr-gate brief Final: line emission

Both brief templates in scripts/pr-gate.sh (sequential L443 + parallel
synthesis L822) now spell out the Final: line format invariants
explicitly:

- plain text, no markdown emphasis (NO `**`, NO backticks, NO italic)
- at start of line (no leading whitespace)
- literal token GO or NO-GO (uppercase, hyphen for NO-GO)
- matched by ^Final: (GO|NO-GO)$
- value MUST equal frontmatter `final:` (case-sensitive)

Lists examples that BREAK the parser (`**Final: GO**`, `Final: **GO**`,
` Final: GO`, `Final: Go`). Self_verify in both templates now uses the
anchored regex `^Final: (GO|NO-GO)$` instead of bare `Final` grep, and
adds frontmatter-vs-Final parity assertion.

CC-252 origin: CC-249 spike PR-gate run (PR #146) hit codex emitting
`**Final: GO**` (bold), which the pr-gate.sh back-compat parser
correctly rejected — false-negative gate exit 1 even though verdict
was GO. Parser is correct; the brief template was under-specified.

Test: new test_bold_final_line_rejected in test-pr-gate.sh exercises
the rejection path via CODEX_GATE_STUB_BOLD_FINAL=1 env (test stub now
emits **Final: GO** when set). Asserts non-zero exit + "exactly one
Final" in stderr. Regression-locks the parser: any future loosening
that accepts bold-Final would silently hide this brief-template drift.

Result: 47/47 pr-gate tests pass (+1 new). Integration 13/13.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(cc-252): backlog status flip ✅ + pr:#147 + body Outcome / See

Tail commit per the CC-250/CC-251 closure pattern: flip CC-252 row
from `🔵 active pr:TBD` to `✅ closed 2026-05-24 pr:#147`, add body
✅ date in title + Outcome block + See line.

Validator parity preserved at 30 (CC-228 baseline).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
screenleon added a commit that referenced this pull request May 23, 2026
…#148)

* feat(cc-249): PR-B.1 — add 4 unified assert_* helpers to test-harness

CC-249 spike (docs/spikes/CC-249.md, PR #146) decided the unified
assert_* API. PR-B.1 adds the 4 helpers + shared fail-message
formatter to scripts/lib/test-harness.sh, PURE ADDITIVE — zero
consumer changes; PR-B.2 (consumer migration) follows separately.

Helpers (per spike Q1/Q2):
- `assert_exit <name> <actual> <expected>` — exit-code check; majority
  arg order (value-under-test first)
- `assert_file_contains <name> <file> <literal>` — grep -Fq for literal
  string in file (current variant A; 6+ consumers will adopt in PR-B.2)
- `assert_file_matches <name> <file> <regex>` — grep -qE for regex
  pattern in file (current variant B; 2 consumers)
- `assert_string_contains <name> <haystack> <needle>` — bash string
  containment via [[ != *needle* ]] (current variant C; 2 consumers).
  Also absorbs assert_output_contains in PR-B.2

Plus shared `_th_assert_fail_msg` formatter — each helper calls it on
the fail path; message contains helper-name + relevant args + failed
condition (debuggable from output alone).

All 4 helpers call existing harness `pass` / `fail` fns on
success/failure → FORMAT-aware output preserved + counter increments
go through the same path as every other case.

Test coverage: 8 new self-test cases in test-test-harness.sh (1 pass +
1 fail per helper) using the file's existing local pass_case/fail_case
+ run_harness_probe pattern (probe subshell, not harness's own
counters — these are tests OF the harness):
- assert-exit-{pass,fail}
- assert-file-contains-{pass,fail}
- assert-file-matches-{pass,fail}
- assert-string-contains-{pass,fail}

Verification:
- bash scripts/test-test-harness.sh — 30/30 (was 22; +8 new)
- bash scripts/test-run-all-tests.sh — 13/13 integration
- bash pm/scripts/validate.sh BACKLOG.md — parity 30 (CC-228 baseline)
- git diff scripts/lib/test-harness.sh — only additions after line 124
  (th_summary close); no deletions; existing fns byte-identical
- expected_head_sha 03555fe verified by codex before first edit

BACKLOG CC-249 row: stays `🟢 someday` (PR-B.2 still pending); pr-ref
`pr:TBD-PRB1` placeholder (tail commit flips to actual PR# after
`gh pr create`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(cc-249): backlog pr-ref TBD-PRB1 → pr:#148 (PR-B.1 tail commit)

CC-249 row stays 🟢 someday (PR-B.2 consumer migration still pending).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <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