mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-08 01:38:10 +01:00
test: harness targets skip retired skills; record the standalone /plan-eng-review paid cases' fates (GST-1698) (#4111)
* test: harness targets skip retired skills; record each standalone /plan-eng-review paid case's fate (GST-1698) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: mark retired /plan-eng-review cases in the detector inventory and TODOS (GST-1698) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
3cf4bc9181
commit
94392a61ec
39 files changed
+121
-629
No files matched your search
@@ -4,7 +4,7 @@
|
||||
|
||||
### P2: `/plan-eng-review` retirement follow-ups (filed 2026-11-06, GST-1698 /ship review of #4108)
|
||||
|
||||
- **Stop the dots and generic harness targets from registering the retired skill.** `sourceSkills()` in `lib/harness-register.ts` lists every committed Claude-render skill and filters out only `gstack`, so `gstack-harness register --target dots|generic` still lists `plan-eng-review` in its router and gives it a folder in `all` mode. Filter `RETIRED_SKILLS` there (the Claude-render /autoplan reads Phase 3 from `~/.claude/skills/gstack/plan-eng-review/SKILL.md`, not from the harness payload) and add a case to `test/retired-skills.test.ts`. Raised by the outside voice (labelled blocking) and the native adversarial pass (non-blocking); below the blocking floor because nothing fails and the skill still works. **Effort:** S. **Priority:** P2.
|
||||
- **Delete the retired `plan-eng-multi-finding-batching` case and its counter subsystem.** The case checks one interactive question per eng finding; /autoplan Phase 3 auto-decides findings, so no shipped entry reaches it. The follow-up to #4108 took it out of the weekly lane through `PERIODIC_CI_EXCLUDE` instead of deleting it, because about 20 free tests and fixtures depend on its counter (`createEngBatchingIssueCounter` in `test/helpers/eng-seeded-coverage.ts`, `test/eng-batching-saved-ledger.test.ts`, `test/detector-corpus-plan-eng-multi-finding-batching.test.ts`, the `eng-batching-*` fixtures). Retirement card: detects=an eng review that batches findings into one plan write; non_test_callers=0; stronger_proof=the ceo/design/devex finding floors keep the shared one-question-per-finding contract; unlocks=the counter helpers, their free tests and fixtures. Delete each helper only after checking it has no other caller (plan-eng-review-artifact shares `engFirstReviewAUQ`). **Effort:** M. **Priority:** P3.
|
||||
- **Point the external-host methodology file's preamble Read at `gstack-autoplan`.** Every external host's `gstack-autoplan/plan-eng-review.md` says to Read `sections/preamble.md` relative to the installed `gstack-plan-eng-review` directory, which no longer exists. Normally the matching preamble id skips the reread, but after compaction late in a run the agent follows a missing path. Fixing it changes Phase 3 bytes, so it needs its own byte-pin update. **Effort:** S. **Priority:** P3.
|
||||
- **Redirect `gstack-doctor --for plan-eng-review`.** It now exits 2 with "unknown skill"; map the retired name to `/autoplan`'s requirements and print a one-line redirect, so saved lane scripts keep working. **Effort:** S. **Priority:** P3.
|
||||
- **Decide whether the QM edition keeps `gstack-plan`.** `hosts/qm.ts` and `qm/edition.json` still build `gstack-plan` from the `plan-eng-review` sources under another name, so the retired-name guards don't see it. Product call for Garry. **Effort:** S. **Priority:** P3.
|
||||
@@ -545,8 +545,9 @@ Deferred from the approved severe fix wave (docs/designs/SEVERE_FIX_WAVE_2026_10
|
||||
a PTY. A fresh run needs more than its 600 s budget (498 s pass; 595 s
|
||||
timeouts in census 37174266054 and a local run), so the periodic case
|
||||
resumes at Test review from that census run's real Scope Challenge ledger
|
||||
(pass, 364 s) and the fresh run is the marathon case
|
||||
plan-eng-review-artifact-full.
|
||||
(pass, 364 s) and the fresh run was the marathon case
|
||||
plan-eng-review-artifact-full (retired with standalone /plan-eng-review,
|
||||
GST-1698).
|
||||
- **Gate-outcome telemetry** — count `not_run`/`unavailable` outcomes per
|
||||
reason code from `lib/gate-outcomes.ts` so the most common gaps get fixed
|
||||
first. **Effort:** S. **Priority:** P3.
|
||||
@@ -2104,7 +2105,8 @@ alone). Recommend (b) short-term + (a) properly sequenced with the codemod.
|
||||
**What:** `evals-periodic.yml` runs an explicit 9-file matrix; the four tests
|
||||
demoted to `periodic` in v1.62.0.0 (`skill-e2e-plan-eng-plan-mode`,
|
||||
`skill-e2e-plan-design-plan-mode`, `skill-e2e-plan-eng-finding-floor`,
|
||||
`skill-e2e-plan-design-finding-floor`) are not in it, so they currently run
|
||||
`skill-e2e-plan-design-finding-floor`; the two plan-eng files were deleted with
|
||||
standalone /plan-eng-review in GST-1698) are not in it, so they currently run
|
||||
only locally/manually (`bun run test:periodic` or `eval:bg:periodic`). Wiring
|
||||
them needs a PTY-capable periodic job: the container skill-registration setup
|
||||
from evals.yml's `e2e-pty-plan-smoke` job (real-file SKILL.md copies for the
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
- **The dots and generic harness targets no longer register the retired /plan-eng-review.** `gstack-harness register --target dots|generic` listed every committed skill except `gstack`, so after #4108 it still put `plan-eng-review` in its router and, in `all` mode, gave it a folder. It now skips every skill in `RETIRED_SKILLS`; `plan-eng-review/` stays in the source tree as /autoplan's Phase 3 methodology. The paid cases written for the standalone skill each have a recorded fate in `docs/TEST_PORTFOLIO.md`: four that check Phase 3 methodology or its required outputs stay (`plan-eng-review`, `plan-eng-coverage-audit`, `plan-eng-review-artifact`, `journey-plan-eng`), six that checked only the standalone interactive entry are deleted along with their rows in the AUQ matrix and the plan-mode no-op file, and `plan-eng-multi-finding-batching` leaves the weekly lane through `PERIODIC_CI_EXCLUDE` until its counter helpers are removed. (GST-1698)
|
||||
@@ -286,6 +286,29 @@ or out-of-tier placeholders. A retained passing judge is reusable only when its
|
||||
complete request, rubric, parameters and relevant dependencies match; native
|
||||
behavioral acceptance follows its separate freshness contract.
|
||||
|
||||
## Paid cases of the retired standalone /plan-eng-review (GST-1698)
|
||||
|
||||
The skill's methodology still ships: `plan-eng-review/` is /autoplan's Phase 3
|
||||
methodology source, bound into each run by the methodology snapshot. Cases that
|
||||
check that methodology or Phase 3's required outputs stay. Cases that checked
|
||||
the standalone interactive entry, which no longer ships, are retired. None was
|
||||
quarantined: `CASE_QUARANTINE` holds flaky cases that keep running, and these
|
||||
cases are not flaky, their entry point is gone.
|
||||
|
||||
| Case | Fate | Why, and what still proves the contract |
|
||||
| --- | --- | --- |
|
||||
| `plan-eng-review` (SDK) | kept | Runs the methodology source over a plan, the bytes Phase 3 loads. |
|
||||
| `plan-eng-coverage-audit` (gate) | kept | Phase 3 must produce the codepath-to-test diagram; the case reads the same methodology and sections. |
|
||||
| `plan-eng-review-artifact` (PTY checkpoint) | kept | Phase 3 must leave a test plan on disk; the case's Test review writes it from the same section. |
|
||||
| `journey-plan-eng` | kept, retargeted | Architecture-review requests now route to /autoplan (#4108). |
|
||||
| `plan-eng-multi-finding-batching` | retired, excluded | Checks one interactive question per finding; Phase 3 auto-decides findings. `PERIODIC_CI_EXCLUDE` stops its weekly run; deleting it with its counter helpers is a TODOS.md item. |
|
||||
| `plan-eng-review-plan-mode` | retired, deleted | Standalone plan-mode handshake; the ceo, design and devex plan-mode cases and `plan-mode-no-op` keep the shared contract. |
|
||||
| `plan-eng-finding-floor` | retired, deleted | Interactive first-finding question; the ceo, design and devex floors keep the shared floor. |
|
||||
| `plan-eng-review-artifact-full` | retired, deleted | Fresh standalone marathon run; the checkpoint case keeps the artifact requirement. |
|
||||
| `plan-eng-review-format-coverage`, `plan-eng-review-format-kind` | retired, deleted | Format of standalone questions; the ceo format cases keep the shared question format. |
|
||||
| `carve-section-loading-plan-eng-review` | retired, deleted | Model-driven section loading on standalone entry; Phase 3 gets the methodology through the snapshot instead. |
|
||||
| `auq-matrix-plan-eng-review`, the eng rows of `plan-mode-no-op` | retired rows | Standalone entry; the other skills' rows keep both files' contracts. |
|
||||
|
||||
## Remaining work, not claimed savings
|
||||
|
||||
Report final acceptance with the delivery revision and its actual case inventory.
|
||||
|
||||
@@ -31,7 +31,7 @@ Dispositions:
|
||||
| F3 | test/helpers/pty/runners/floor.ts:497 | screen Write render / plan-ready text → fail | Write/ExitPlanMode tool_use in run.transcript | no | (b) |
|
||||
| A1 | test/helpers/auq-sdk-capture.ts:30-43 `scoreAuqFormat` | question has ELI10:, Recommendation:, Pros / cons, ✅, ❌, Net:, (recommended) | AUQ tool input (its prose is the contract) | yes | (c) |
|
||||
|
||||
Cases that use S1-S8: plan-ceo-review-plan-mode, plan-devex-review-plan-mode, plan-mode-no-op, office-hours-auto-mode (gate); auto-decide-preserved, plan-eng-review-plan-mode, plan-design-review-plan-mode-smoke (periodic). S9-S10: plan-mode-no-op, plan-eng-review-plan-mode, plan-design-review-plan-mode-smoke. F1-F3: plan-ceo-finding-floor, plan-devex-finding-floor (gate); plan-design-finding-floor, plan-eng-finding-floor (periodic). A1: auq-format-gate (gate); the three standalone AUQ files (periodic).
|
||||
Cases that use S1-S8: plan-ceo-review-plan-mode, plan-devex-review-plan-mode, plan-mode-no-op, office-hours-auto-mode (gate); auto-decide-preserved, plan-design-review-plan-mode-smoke (periodic). S9-S10: plan-mode-no-op, plan-design-review-plan-mode-smoke. F1-F3: plan-ceo-finding-floor, plan-devex-finding-floor (gate); plan-design-finding-floor (periodic). A1: auq-format-gate (gate); the three standalone AUQ files (periodic). plan-eng-review-plan-mode and plan-eng-finding-floor were deleted with standalone /plan-eng-review (GST-1698).
|
||||
|
||||
## Gate tier
|
||||
|
||||
@@ -205,18 +205,18 @@ Gate cases with no phrase-only checks: the shared-libs review-lifecycle, revalid
|
||||
| plan-eng-multi-finding-batching | test/helpers/eng-seeded-coverage.ts:33-104 | distinct-issue identity per answered AUQ ("Issue N:", D/R-ID, ELI10 gates) | ledger R records, used only as fallback behind the prose gates | no | (b) |
|
||||
| plan-eng-multi-finding-batching | test/helpers/pty/classify.ts:555 via counting.ts:554 | screen completion text ends counting | review-log row / ExitPlanMode tool_use | no | (b) |
|
||||
| plan-eng-review-artifact | test/skill-e2e-plan-eng-artifact.test.ts:78 | test-plan artifact ~ dashboard/fetchStats/`/api/stats` | artifact schema has no field naming the change (scripts/resolvers/testing.ts:501-528) | no | (d) |
|
||||
| carve-section-loading [plan-eng-review] | test/helpers/carve-section-case.ts:120 → test/helpers/auq-sdk-capture.ts:381 | report or output ~ report/review/summary/design doc/handoff | review-log row in the capture state root, deleted before the verdict (auq-sdk-capture.ts:368-370) | no | (b) |
|
||||
| carve-section-loading [plan-eng-review] (deleted, GST-1698) | test/helpers/carve-section-case.ts:120 → test/helpers/auq-sdk-capture.ts:381 | report or output ~ report/review/summary/design doc/handoff | review-log row in the capture state root, deleted before the verdict (auq-sdk-capture.ts:368-370) | no | (b) |
|
||||
| carve-section-loading [12 other skills] | same | same loose regex | none (Bash not allowed, auq-sdk-capture.ts:358-359) | no | (d) |
|
||||
|
||||
The plan-eng-review-plan-mode and plan-design-review-plan-mode-smoke verdicts are S1-S10. plan-eng-finding-floor and plan-design-finding-floor verdicts are F1-F3.
|
||||
The plan-design-review-plan-mode-smoke verdicts are S1-S10, and the plan-design-finding-floor verdicts are F1-F3. Their plan-eng twins were deleted with standalone /plan-eng-review (GST-1698).
|
||||
|
||||
### Question format: test/skill-e2e-plan-format.test.ts, test/skill-e2e-plan-prosons.test.ts, standalone AUQ files
|
||||
|
||||
| Case | Check (file:line) | Matches | Structured source | User-visible | Disposition |
|
||||
|---|---|---|---|---|---|
|
||||
| plan-ceo-review-format-mode, plan-eng-review-format-kind | test/skill-e2e-plan-format.test.ts:174-175, :377-378 | no `Completeness: N/10`; kind note present | captured question | yes | (c) |
|
||||
| plan-ceo-review-format-approach, plan-eng-review-format-coverage | test/skill-e2e-plan-format.test.ts:241, :310 | `Completeness: N/10` present | captured question | yes | (c) |
|
||||
| all four format cases | test/skill-e2e-plan-format.test.ts:177, :243, :312, :380 | recommendation quality | — | — | judge |
|
||||
| plan-ceo-review-format-mode | test/skill-e2e-plan-format.test.ts:173-174 | no `Completeness: N/10`; kind note present | captured question | yes | (c) |
|
||||
| plan-ceo-review-format-approach | test/skill-e2e-plan-format.test.ts:240 | `Completeness: N/10` present | captured question | yes | (c) |
|
||||
| both format cases | test/skill-e2e-plan-format.test.ts:176, :242 | recommendation quality | — | — | judge |
|
||||
| plan-review-prosons-format | test/skill-e2e-plan-prosons.test.ts:184-196 | `D\d+ —`, ELI10:, Stakes…:, Recommendation:, Pros / cons:, ^Net:, ✅≥4, ❌≥2, (recommended) | captured question | yes | (c) |
|
||||
| plan-review-prosons-hardstop-neg | test/skill-e2e-plan-prosons.test.ts:246-249 | no hard-stop escape line; ✅/❌ counts | captured question | yes | (c) |
|
||||
| plan-review-prosons-neutral-neg | test/skill-e2e-plan-prosons.test.ts:299-303 | no `taste call`; (recommended); `Recommendation:.*because` | captured question | yes | (c) |
|
||||
@@ -315,6 +315,6 @@ Red cases that are not convert candidates: shared-libs-plan-callers (3 reds, act
|
||||
- Census commits `a8ace39` through `fd6854b` are not in this checkout, so the wave-reds line numbers could not be mapped to assertions; reds are attributed from the trial error text.
|
||||
- The skill-llm-eval.test.ts judge cases are outside `E2E_TIERS` and are not covered.
|
||||
- codex-ci-access.test.ts, codex-hardening.test.ts, codex-under-codex-detection.test.ts, e2e-shard-reuse.test.ts and skill-routing-e2e.test.ts name the umbrella keys but are free tests or route to the files audited above.
|
||||
- plan-eng-review-artifact-full is `marathon` and out of scope.
|
||||
- plan-eng-review-artifact-full was `marathon` and was deleted with standalone /plan-eng-review (GST-1698).
|
||||
- The aside-* cases need a live Aside on macOS and never run in CI.
|
||||
- "Not verified" in the structured-source column means the template writes the record, but the audit did not confirm that the fixture installs the helper.
|
||||
@@ -19,6 +19,7 @@ import * as fs from 'node:fs';
|
||||
import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { RETIRED_SKILLS } from '../scripts/discover-skills';
|
||||
import { bunIsolationArgs } from './bun-isolation';
|
||||
import { runBashSync } from './script-invocation';
|
||||
import { frontmatterList, routerLine } from './skill-triggers';
|
||||
@@ -233,7 +234,7 @@ function skillDirs(root: string, triggersByName = new Map<string, string[]>()):
|
||||
|
||||
/** The skills a target's payload carries: the host render (made for this checkout as the install root) or the checkout's committed Claude render. */
|
||||
export function sourceSkills(target: Target, checkout: string, scratch: string): SkillEntry[] {
|
||||
if (target.render === 'claude') return skillDirs(checkout).filter(s => s.name !== 'gstack');
|
||||
if (target.render === 'claude') return skillDirs(checkout).filter(s => s.name !== 'gstack' && !RETIRED_SKILLS.includes(s.name));
|
||||
const out = path.join(scratch, 'render');
|
||||
fs.rmSync(out, { recursive: true, force: true });
|
||||
const r = spawnSync(process.execPath, [...bunIsolationArgs(), 'scripts/gen-skill-docs.ts', '--host', target.name, '--install-root', checkout, '--out-dir', out],
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"blob":"f862cf5241580c7593b9ee62eacf5ef046248d26","since":6,"nonBehavioral":"Claude-host verdicts are unchanged: the Codex host (EVALS_HOST=codex, codex-host-runner) runs only when selected and records its own per-model series; the Codex runner refactor (execCodex extraction, onSpawn hook) keeps its events and verdicts and adds token cost accounting; host fields on the plan/report are absent for claude"}
|
||||
{"blob":"c984ba618be367f2201362a9592da7a8631accb5","since":6,"nonBehavioral":"Retired standalone /plan-eng-review cases (GST-1698): removed their budgets and paid-case rows; remaining files' walls shrink with their case counts, and no remaining case's budget or verdict changes"}
|
||||
@@ -1 +1 @@
|
||||
{"blob":"8cb433b0618cc218dacf21cc644de7947442d045","since":6,"nonBehavioral":"GST-1403 removes the last three standalone LLM judges (qa anti-refusal, voice directive tone, cross-skill greptile consistency): llm-judge.ts drops their three schemas and three prompt builders, which no remaining case calls, and eval-budgets.ts drops the deleted test/skill-llm-eval.test.ts file wall; no kept case's prompt, threshold, samples, budget or verdict can change"}
|
||||
{"blob":"5a16324a47b7c3c770e64322ae357f90c405a249","since":6,"nonBehavioral":"Retired standalone /plan-eng-review cases (GST-1698): removed their budgets and paid-case rows; remaining files' walls shrink with their case counts, and no remaining case's budget or verdict changes"}
|
||||
@@ -76,7 +76,6 @@ export const CASE_TEST_NAMES: Record<string, string> = {
|
||||
'cso-infra-scope': '/cso --infra finds an attacker-to-credential execution path',
|
||||
'plan-ceo-review-plan-mode': 'first terminal outcome is asked (Step 0 fires before any plan write)',
|
||||
'plan-eng-review-artifact': 'an interactive review writes one QA test plan about the reviewed change',
|
||||
'plan-eng-review-artifact-full': 'a fresh interactive review reaches Test review and writes one QA test plan',
|
||||
};
|
||||
|
||||
export const CASE_KEY_SEPARATOR = '#';
|
||||
|
||||
@@ -116,7 +116,6 @@
|
||||
"test/carve-section-loading.test.ts#carve-section-loading-land-and-deploy": 156293,
|
||||
"test/carve-section-loading.test.ts#carve-section-loading-plan-design-review": 223606,
|
||||
"test/carve-section-loading.test.ts#carve-section-loading-plan-devex-review": 384295,
|
||||
"test/carve-section-loading.test.ts#carve-section-loading-plan-eng-review": 297627,
|
||||
"test/carve-section-loading.test.ts#carve-section-loading-qa": 149637,
|
||||
"test/carve-section-loading.test.ts#carve-section-loading-retro": 199931,
|
||||
"test/carve-section-loading.test.ts#carve-section-loading-review": 247902,
|
||||
@@ -173,11 +172,8 @@
|
||||
"test/skill-e2e-plan-design-finding-floor.test.ts": 131042,
|
||||
"test/skill-e2e-plan-design-plan-mode.test.ts": 111838,
|
||||
"test/skill-e2e-plan-devex-peer-comparison-classification.test.ts": 77201,
|
||||
"test/skill-e2e-plan-eng-artifact-full.test.ts": 595009,
|
||||
"test/skill-e2e-plan-eng-artifact.test.ts": 406795,
|
||||
"test/skill-e2e-plan-eng-finding-floor.test.ts": 234397,
|
||||
"test/skill-e2e-plan-eng-multi-finding-batching.test.ts": 409161,
|
||||
"test/skill-e2e-plan-eng-plan-mode.test.ts": 170914,
|
||||
"test/skill-e2e-plan-format.test.ts": 219670,
|
||||
"test/skill-e2e-plan-prosons.test.ts": 163659,
|
||||
"test/skill-e2e-plan-tune.test.ts": 1000,
|
||||
|
||||
@@ -24,7 +24,6 @@ describeE2ETier('periodic')('carve section-loading', () => {
|
||||
test('carve-section-loading-land-and-deploy', () => runCarveSectionCase('land-and-deploy'), CAPTURE_LONG_MS);
|
||||
test('carve-section-loading-plan-design-review', () => runCarveSectionCase('plan-design-review'), CAPTURE_LONG_MS);
|
||||
test('carve-section-loading-plan-devex-review', () => runCarveSectionCase('plan-devex-review'), CAPTURE_LONG_MS);
|
||||
test('carve-section-loading-plan-eng-review', () => runCarveSectionCase('plan-eng-review'), CAPTURE_LONG_MS);
|
||||
test('carve-section-loading-qa', () => runCarveSectionCase('qa'), CAPTURE_LONG_MS);
|
||||
test('carve-section-loading-retro', () => runCarveSectionCase('retro'), CAPTURE_LONG_MS);
|
||||
test('carve-section-loading-review', () => runCarveSectionCase('review'), CAPTURE_LONG_MS);
|
||||
|
||||
@@ -9,6 +9,7 @@ import { CASE_SHARDED_FILES, DEFAULT_SHARD_TIMEOUT_MS, caseFile, expandCaseShard
|
||||
import { carveSectionCaseId } from './helpers/carve-section-case';
|
||||
import { E2E_TIERS, E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
|
||||
import { E2E_KINDS } from './helpers/touchfiles-data';
|
||||
import { RETIRED_SKILLS } from '../scripts/discover-skills';
|
||||
|
||||
describe('carved-skill cases each get a complete paid process budget', () => {
|
||||
const FILE = 'test/carve-section-loading.test.ts';
|
||||
@@ -16,7 +17,8 @@ describe('carved-skill cases each get a complete paid process budget', () => {
|
||||
const source = fs.readFileSync(path.join(ROOT, FILE), 'utf8');
|
||||
const cases = [...source.matchAll(/test\('carve-section-loading-([a-z-]+)', \(\) => runCarveSectionCase\('([a-z-]+)'\), CAPTURE_LONG_MS\)/g)]
|
||||
.map(match => ({ id: `carve-section-loading-${match[1]}`, skill: match[2]! }));
|
||||
const generic = Object.values(CARVE_GUARDS).filter(guard => guard.behavioral === 'plan' || guard.behavioral === 'prompt').map(guard => guard.skill).sort();
|
||||
// A retired skill keeps its carve guard (its methodology still renders) but no section-loading case.
|
||||
const generic = Object.values(CARVE_GUARDS).filter(guard => (guard.behavioral === 'plan' || guard.behavioral === 'prompt') && !RETIRED_SKILLS.includes(guard.skill)).map(guard => guard.skill).sort();
|
||||
|
||||
test('every generic registry entry has exactly one periodic case, under its own case id, and no external entry does', () => {
|
||||
expect(source).toContain("describeE2ETier('periodic')");
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
import { describe, test, expect } from 'bun:test';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { RETIRED_SKILLS } from '../scripts/discover-skills';
|
||||
|
||||
const ROOT = path.resolve(import.meta.dir, '..');
|
||||
|
||||
@@ -47,7 +48,8 @@ function skillTemplateDirs(): string[] {
|
||||
*/
|
||||
function findInteractiveSkills(): string[] {
|
||||
const interactive: string[] = [];
|
||||
for (const skill of skillTemplateDirs()) {
|
||||
// A retired skill keeps its template as methodology for another skill but has no interactive entry.
|
||||
for (const skill of skillTemplateDirs().filter(name => !RETIRED_SKILLS.includes(name))) {
|
||||
const tmplPath = path.join(ROOT, skill, 'SKILL.md.tmpl');
|
||||
if (!fs.existsSync(tmplPath)) continue;
|
||||
const content = fs.readFileSync(tmplPath, 'utf-8');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { expect, test } from 'bun:test';
|
||||
import { resolvePaidShardBudget, retriesForFiles, planPaidShards, parseRunManifest, verifySliceResults, runPaidShard, buildRunManifest, paidShardWallUpperBoundMs, collectPaidTestFiles, selectPaidTestFiles, isOverlayTestFile, DEFAULT_SHARD_TIMEOUT_MS, DEFAULT_JOBS, parseCliOptions, expandCaseShards, expandTrialShards, shardFile, sliceExecutionOrder, sliceSupervisedWallMs, resolvePaidShardTimeoutMs } from '../scripts/test-paid-shards';
|
||||
import { FINDING_RETRY_BUDGETS, ALL_TIERS, SHARD_RESERVE_MS } from './helpers/eval-budgets';
|
||||
import { PERIODIC_CI_EXCLUDE } from './helpers/periodic-exclude-data';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
@@ -141,7 +142,7 @@ test('live periodic census fits the declared CI wall including setup', () => {
|
||||
|
||||
test('registered allocation is deterministic and preserves every discovered file', () => {
|
||||
const files = collectPaidTestFiles();
|
||||
expect(files).toHaveLength(114); // - skill-llm-eval (last standalone judges removed, GST-1403); + skill-e2e-autoplan-ceo-only (GST-537); + skill-e2e-planning-wave (GSTA-228); + skill-e2e-model-panel (GSTA-173); + skill-e2e-write-skill (GSTA-133); + skill-e2e-ship-frozen-scope (frozen review scope, GSTA-113 PR 2); + skill-e2e-failure-routing (#3157/#3158); + skill-e2e-dx-error-contract (#3226); + skill-e2e-gate-integrity (HONEST_WORK_GATE_INTEGRITY W8); + skill-e2e-autoplan-schema-canary, -guard-pty and -long-session (Oct 7 wave, CEO-13, ENG-18, CEO-15); + skill-e2e-ship-measure-seeded-flake (v1.91.32.0); W5a: 15 carve wrappers became one case-sharded file; + codex-e2e-multiblock-live and skill-e2e-design-model-smoke (v1.91.30.0);
|
||||
expect(files).toHaveLength(111); // - skill-e2e-plan-eng-plan-mode, -plan-eng-finding-floor and -plan-eng-artifact-full (standalone /plan-eng-review retired, GST-1698); - skill-llm-eval (last standalone judges removed, GST-1403); + skill-e2e-autoplan-ceo-only (GST-537); + skill-e2e-planning-wave (GSTA-228); + skill-e2e-model-panel (GSTA-173); + skill-e2e-write-skill (GSTA-133); + skill-e2e-ship-frozen-scope (frozen review scope, GSTA-113 PR 2); + skill-e2e-failure-routing (#3157/#3158); + skill-e2e-dx-error-contract (#3226); + skill-e2e-gate-integrity (HONEST_WORK_GATE_INTEGRITY W8); + skill-e2e-autoplan-schema-canary, -guard-pty and -long-session (Oct 7 wave, CEO-13, ENG-18, CEO-15); + skill-e2e-ship-measure-seeded-flake (v1.91.32.0); W5a: 15 carve wrappers became one case-sharded file; + codex-e2e-multiblock-live and skill-e2e-design-model-smoke (v1.91.30.0);
|
||||
expect(files).toContain('test/skill-e2e-ship-skip.test.ts');
|
||||
const m = livePlan(files);
|
||||
expect(livePlan([...files].reverse())).toEqual(m);
|
||||
@@ -175,6 +176,7 @@ test('single-slice manifest retains all registered files with one allocation', (
|
||||
for (const m of manifests) expect(m.entries.filter(e => e.status === 'planned').every(e => e.slice === 1)).toBe(true);
|
||||
for (const budget of FINDING_RETRY_BUDGETS) {
|
||||
const entries = manifests.flatMap(m => m.entries.filter(e => e.file === budget.file && e.status === 'planned'));
|
||||
if (PERIODIC_CI_EXCLUDE[budget.file]) { expect(entries, budget.file).toHaveLength(0); continue; }
|
||||
expect(entries, budget.file).toHaveLength(1);
|
||||
expect(entries[0]!.budget).toEqual(resolvePaidShardBudget([budget.file]));
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ describe('E2E_KINDS registry', () => {
|
||||
// Contract-shaped cases stay rule: ask-before-decide, plan-mode no-writes,
|
||||
// mandated steps, secrets, and the batching floor never ride a majority.
|
||||
for (const id of ['plan-ceo-mode-routing', 'plan-eng-multi-finding-batching', 'plan-design-review-plan-mode',
|
||||
'plan-eng-review-plan-mode', 'plan-ceo-section-loading', 'setup-gbrain-bad-token', 'qa-only-no-fix', 'review-sql-injection']) {
|
||||
'plan-ceo-section-loading', 'setup-gbrain-bad-token', 'qa-only-no-fix', 'review-sql-injection']) {
|
||||
expect(E2E_KINDS[id], id).toBe('rule');
|
||||
}
|
||||
});
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
"status": "planned",
|
||||
"estimatedMs": 217184,
|
||||
"budget": {
|
||||
"timeoutMs": 3720000,
|
||||
"timeoutMs": 2520000,
|
||||
"source": "registered",
|
||||
"policyId": "skill-e2e-plan-mode-no-op-existing-retry-v1"
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"executedTests": 5,
|
||||
"skippedTests": 0,
|
||||
"budget": {
|
||||
"timeoutMs": 3720000,
|
||||
"timeoutMs": 2520000,
|
||||
"source": "registered",
|
||||
"policyId": "skill-e2e-plan-mode-no-op-existing-retry-v1"
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
"carve-section-loading-land-and-deploy",
|
||||
"carve-section-loading-plan-design-review",
|
||||
"carve-section-loading-plan-devex-review",
|
||||
"carve-section-loading-plan-eng-review",
|
||||
"carve-section-loading-qa",
|
||||
"carve-section-loading-retro",
|
||||
"carve-section-loading-review",
|
||||
@@ -33,9 +32,7 @@
|
||||
"plan-design-with-ui-scope",
|
||||
"plan-devex-finding-floor",
|
||||
"plan-devex-review-plan-mode",
|
||||
"plan-eng-finding-floor",
|
||||
"plan-eng-multi-finding-batching",
|
||||
"plan-eng-review-plan-mode",
|
||||
"plan-mode-no-op",
|
||||
"ship-section-loading"
|
||||
],
|
||||
@@ -54,7 +51,6 @@
|
||||
"carve-section-loading-land-and-deploy",
|
||||
"carve-section-loading-plan-design-review",
|
||||
"carve-section-loading-plan-devex-review",
|
||||
"carve-section-loading-plan-eng-review",
|
||||
"carve-section-loading-qa",
|
||||
"carve-section-loading-retro",
|
||||
"carve-section-loading-review",
|
||||
@@ -72,9 +68,7 @@
|
||||
"plan-design-with-ui-scope",
|
||||
"plan-devex-finding-floor",
|
||||
"plan-devex-review-plan-mode",
|
||||
"plan-eng-finding-floor",
|
||||
"plan-eng-multi-finding-batching",
|
||||
"plan-eng-review-plan-mode",
|
||||
"plan-mode-no-op",
|
||||
"ship-section-loading"
|
||||
],
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"carve-section-loading-land-and-deploy",
|
||||
"carve-section-loading-plan-design-review",
|
||||
"carve-section-loading-plan-devex-review",
|
||||
"carve-section-loading-plan-eng-review",
|
||||
"carve-section-loading-qa",
|
||||
"carve-section-loading-retro",
|
||||
"carve-section-loading-review",
|
||||
@@ -35,13 +34,9 @@
|
||||
"plan-devex-finding-floor",
|
||||
"plan-devex-review-plan-mode",
|
||||
"plan-eng-coverage-audit",
|
||||
"plan-eng-finding-floor",
|
||||
"plan-eng-multi-finding-batching",
|
||||
"plan-eng-review",
|
||||
"plan-eng-review-artifact",
|
||||
"plan-eng-review-format-coverage",
|
||||
"plan-eng-review-format-kind",
|
||||
"plan-eng-review-plan-mode",
|
||||
"plan-mode-no-op",
|
||||
"plan-review-prosons-format",
|
||||
"plan-review-report",
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
BLOCK_BEGIN, BLOCK_END, CONTEXT_BLOCK_MAX, DOT_SKILLS_DIR, HARNESS_CODES, HYBRID_SKILLS, HarnessError, OPENCLAW_ALL_TEXTS, OPENCLAW_INSTRUCTION_MAX, ROUTER_DESCRIPTION, ROUTER_DESCRIPTION_MAX, TARGETS,
|
||||
contextBlock, contextScope, detect, listLedgers, readLedger, refresh, register, sourceSkills, unregister, type RegisterOptions,
|
||||
} from '../lib/harness-register';
|
||||
import { RETIRED_SKILLS } from '../scripts/discover-skills';
|
||||
import { QM_PACK_LIMITS, qmRequest, registerQm, removeQmPack } from '../lib/harness-qm';
|
||||
import { cleanupFixtures, cleanupSeed, makeFixture, makeSource, registryRows, runSetup, tree } from './helpers/install-fixture';
|
||||
|
||||
@@ -139,6 +140,17 @@ describe('gstack-harness register and unregister (skill folders)', () => {
|
||||
}
|
||||
}, 60_000);
|
||||
|
||||
test('Claude-render targets (dots, generic) never register a retired skill; /autoplan still carries its methodology', () => {
|
||||
const d = tmp();
|
||||
const names = sourceSkills(TARGETS.dots, ROOT, d).map(s => s.name);
|
||||
expect(names).toContain('autoplan');
|
||||
for (const retired of RETIRED_SKILLS) expect(names).not.toContain(retired);
|
||||
expect(sourceSkills(TARGETS.generic, ROOT, d).map(s => s.name)).toEqual(names);
|
||||
const r = register(opts(d, 'dots', { mode: 'all', skillsDir: path.join(d, 'all') }));
|
||||
for (const retired of RETIRED_SKILLS) expect(fs.existsSync(path.join(r.dest, retired))).toBe(false);
|
||||
expect(fs.existsSync(path.join(ROOT, 'plan-eng-review', 'SKILL.md'))).toBe(true);
|
||||
}, 60_000);
|
||||
|
||||
test('generic: the context block is replaced in place, then cut out; the user\'s lines and edits survive', () => {
|
||||
const d = tmp();
|
||||
const ctx = path.join(d, 'agent', 'AGENTS.md');
|
||||
|
||||
@@ -99,16 +99,14 @@ export const FILE_RETRY_BUDGETS = [
|
||||
{ file: 'test/skill-e2e-qa-callers.test.ts', attemptMs: 5 * (CAPTURE_MS + 15_000), caseMs: CAPTURE_MS + 15_000 },
|
||||
{ file: 'test/skill-e2e-shared-libs-paths.test.ts', attemptMs: 3 * CAPTURE_LONG_MS, caseMs: CAPTURE_LONG_MS },
|
||||
{ file: 'test/skill-e2e-ship-docsync.test.ts', attemptMs: 4 * CAPTURE_LONG_MS + 8 * CAPTURE_MS, caseMs: CAPTURE_LONG_MS },
|
||||
{ file: 'test/skill-e2e-auq-matrix.test.ts', attemptMs: 6 * CAPTURE_MS, caseMs: CAPTURE_MS },
|
||||
{ file: 'test/skill-e2e-plan-format.test.ts', attemptMs: 4 * (CAPTURE_MS + 10_000), caseMs: CAPTURE_MS + 10_000 },
|
||||
{ file: 'test/skill-e2e-auq-matrix.test.ts', attemptMs: 5 * CAPTURE_MS, caseMs: CAPTURE_MS },
|
||||
{ file: 'test/skill-e2e-plan-format.test.ts', attemptMs: 2 * (CAPTURE_MS + 10_000), caseMs: CAPTURE_MS + 10_000 },
|
||||
{ file: 'test/skill-e2e-auto-decide-preserved.test.ts', attemptMs: PTY_MS, caseMs: PTY_MS },
|
||||
{ file: 'test/skill-e2e-plan-ceo-finding-floor.test.ts', attemptMs: PTY_MS, caseMs: PTY_MS },
|
||||
{ file: 'test/skill-e2e-plan-eng-finding-floor.test.ts', attemptMs: PTY_MS, caseMs: PTY_MS },
|
||||
{ file: 'test/skill-e2e-plan-design-finding-floor.test.ts', attemptMs: PTY_MS, caseMs: PTY_MS },
|
||||
{ file: 'test/skill-e2e-plan-devex-finding-floor.test.ts', attemptMs: PTY_MS, caseMs: PTY_MS },
|
||||
{ file: 'test/skill-e2e-plan-mode-no-op.test.ts', attemptMs: 6 * CAPTURE_LONG_MS, caseMs: CAPTURE_LONG_MS },
|
||||
{ file: 'test/skill-e2e-plan-mode-no-op.test.ts', attemptMs: 4 * CAPTURE_LONG_MS, caseMs: CAPTURE_LONG_MS },
|
||||
{ file: 'test/skill-e2e-plan-ceo-mode-routing.test.ts', attemptMs: 2 * CAPTURE_LONG_MS, caseMs: CAPTURE_LONG_MS },
|
||||
{ file: 'test/skill-e2e-plan-eng-plan-mode.test.ts', attemptMs: 2 * CAPTURE_LONG_MS, caseMs: CAPTURE_LONG_MS },
|
||||
{ file: 'test/skill-e2e-plan-prosons.test.ts', attemptMs: 4 * (CAPTURE_MS + 10_000), caseMs: CAPTURE_MS + 10_000 },
|
||||
// Gate: six 300s cases + one 610s case; periodic: two 900s + two 600s
|
||||
// (plan-eng-review-artifact runs from its own PTY file).
|
||||
|
||||
@@ -23,6 +23,10 @@ export const PERIODIC_CI_EXCLUDE: Record<string, { reason: string; tracking: str
|
||||
reason: 'needs OPENROUTER_API_KEY, which no CI workflow carries; a preregistered research instrument run on demand, not weekly coverage',
|
||||
tracking: 'TODOS.md "CI-unrunnable paid evals" (re-entry: OPENROUTER_API_KEY in the periodic slice env and a new preregistration; review by 2026-12-28)',
|
||||
},
|
||||
'test/skill-e2e-plan-eng-multi-finding-batching.test.ts': {
|
||||
reason: 'retired with standalone /plan-eng-review (GST-1698): it checks one interactive question per eng finding, and /autoplan Phase 3 auto-decides findings, so no shipped entry reaches the behavior; running it weekly is known waste',
|
||||
tracking: 'TODOS.md "/plan-eng-review retirement follow-ups" (re-entry: none; delete the file with its batching counter helpers and fixtures)',
|
||||
},
|
||||
'test/skill-e2e-ios-device.test.ts': {
|
||||
reason: 'needs a physical iPhone over USB/devicectl — manual hardware, not a CI runner capability',
|
||||
tracking: 'TODOS.md "CI-unrunnable paid evals" (re-entry: the CLI/device is available in the CI image; review by 2026-12-28)',
|
||||
|
||||
@@ -191,13 +191,6 @@ export const E2E_TOUCHFILES: Record<string, string[]> = {
|
||||
"test/fixtures/plan-scope-recovery-av.json", 'plan-eng-review/**', 'test/skill-e2e-plan-eng-artifact.test.ts', 'test/helpers/plan-eng-artifact-fixture.ts', 'test/helpers/plan-eng-resume.ts', 'test/fixtures/plan-eng-artifact-resume-37174266054.json', 'test/helpers/workflow-excerpt.ts',
|
||||
"scripts/resolvers/preamble/generate-preamble-bash.ts", "scripts/resolvers/preamble/generate-completion-status.ts",
|
||||
'scripts/resolvers/testing.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'test/helpers/llm-judge.ts', 'test/helpers/office-hours-attempt.ts', 'test/helpers/office-hours-completion.ts', 'test/helpers/workflow-judge-input.ts'],
|
||||
'plan-eng-review-artifact-full': [ 'test/helpers/auto-decision-state.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/claude-pty-runner.ts', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/native-auto-decide.ts', 'test/helpers/owned-claude-transcript.ts', 'test/helpers/plan-count-artifacts.ts', 'test/helpers/plan-count-file-permission.ts', 'test/helpers/plan-count-fixture.ts', 'test/helpers/plan-count-pending-exit.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-count-transcript.ts', 'test/helpers/plan-floor-review.ts', 'test/helpers/plan-floor-target.ts', 'test/helpers/plan-scope-selection.ts', 'test/helpers/plan-seed-submission.ts', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/plan-skill-questions.ts', 'test/helpers/pty-screen.ts', 'test/helpers/pty-trust-dialog.ts', 'test/helpers/pty/**', 'test/helpers/pty/auq.ts', 'test/helpers/pty/binary.ts', 'test/helpers/pty/boundaries.ts', 'test/helpers/pty/classify.ts', 'test/helpers/pty/fake-session.ts', 'test/helpers/pty/judge.ts', 'test/helpers/pty/launch.ts', 'test/helpers/pty/plan-native.ts', 'test/helpers/pty/runners/counting.ts', 'test/helpers/pty/runners/floor.ts', 'test/helpers/pty/runners/observation.ts', 'test/helpers/pty/screen.ts', 'test/helpers/pty/session.ts', 'test/helpers/skill-census.ts',
|
||||
|
||||
'scripts/resolvers/learnings.ts',
|
||||
|
||||
"test/fixtures/plan-scope-recovery-av.json", 'plan-eng-review/**', 'test/skill-e2e-plan-eng-artifact-full.test.ts', 'test/helpers/plan-eng-artifact-fixture.ts', 'test/helpers/workflow-excerpt.ts',
|
||||
"scripts/resolvers/preamble/generate-preamble-bash.ts", "scripts/resolvers/preamble/generate-completion-status.ts",
|
||||
'scripts/resolvers/testing.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'test/helpers/llm-judge.ts', 'test/helpers/office-hours-attempt.ts', 'test/helpers/office-hours-completion.ts', 'test/helpers/workflow-judge-input.ts'],
|
||||
'plan-review-report': [
|
||||
|
||||
'test/helpers/office-hours-attempt.ts',
|
||||
@@ -231,28 +224,6 @@ export const E2E_TOUCHFILES: Record<string, string[]> = {
|
||||
|
||||
"test/fixtures/eng-option-b-scope-al.json",
|
||||
'test/fixtures/pty-companion-cli.ts', 'lib/fs-atomic.ts', 'test/helpers/plan-skill-questions.ts', 'test/fixtures/eng-auq-validation-error.json', 'test/fixtures/bash-directory-permission.json', 'test/fixtures/design-tasks-bash-permission.json', 'test/fixtures/read-permission.json', 'test/fixtures/ceo-split-e5-numbered-description-491.json', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/skill-census.ts', 'scripts/resolvers/tasks-section.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/owned-claude-transcript.ts', 'test/helpers/plan-count-artifacts.ts', 'test/helpers/plan-count-file-permission.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-count-transcript.ts', 'test/helpers/plan-floor-review.ts', 'test/helpers/plan-floor-target.ts', 'bin/gstack-context-recovery'],
|
||||
'plan-eng-review-plan-mode': ['bin/gstack-state-root.sh', 'lib/state-root.ts', 'lib/claude-public-transcript.ts', 'lib/claude-journal-records.ts', 'lib/claude-owned-journal.ts',
|
||||
|
||||
'test/fixtures/auto-decide-recommendation-361c.json',
|
||||
|
||||
'test/fixtures/auto-decide-target-361c.json',
|
||||
|
||||
'test/fixtures/autoplan-public-narration-ad.json',
|
||||
'test/helpers/plan-count-transcript.ts', 'test/fixtures/plan-count-cross-cwd-ancestry-0bcd.json',
|
||||
'scripts/resolvers/learnings.ts',
|
||||
"test/fixtures/plan-scope-target-aw.json",
|
||||
|
||||
|
||||
"test/fixtures/plan-scope-recovery-av.json",
|
||||
'test/fixtures/auto-decide-saved-ai.json', 'test/fixtures/auto-decide-retry-ai.json','bin/gstack-skill-start', 'bin/gstack-skill-end', 'plan-eng-review/**', 'scripts/resolvers/preamble/generate-completion-status.ts', 'scripts/resolvers/question-tuning.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/preamble.ts', 'scripts/resolvers/preamble-hoist.ts', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/fixtures/design-ui-boxed-question.json', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/pty-trust-dialog.ts', 'test/skill-e2e-plan-eng-plan-mode.test.ts', 'test/fixtures/eng-d2-truncated-border-0bcd.json', 'test/fixtures/eng-d1-clipped-elision-1579.json', 'test/fixtures/eng-d2-planning-prelude-4d.json', 'test/fixtures/ceo-approach-z-call.json', 'test/fixtures/ceo-approach-z-screen.txt', 'test/helpers/plan-scope-selection.ts', 'test/fixtures/design-plan-scope-ag.json', 'test/fixtures/design-scope-selection-aj.json', 'test/helpers/native-auto-decide.ts', 'test/fixtures/auto-decide-current-declaration-6aef.json', 'test/fixtures/auto-decide-explanatory-mode-043a.json', 'test/fixtures/auto-decide-explanatory-mode-749df.json', 'test/fixtures/auto-decide-structured-77.json', 'test/helpers/auto-decision-state.ts', 'test/fixtures/auto-decide-state-cab3.json', 'bin/gstack-question-log', 'bin/gstack-question-preference', 'test/helpers/fake-plan-seed.ts', 'test/fixtures/native-auto-decide-ag.json', 'test/fixtures/eng-seeded-completion-ai.json', 'test/helpers/plan-count-pending-exit.ts', 'test/helpers/pty-screen.ts', 'test/fixtures/pty-screen/**',
|
||||
|
||||
'test/fixtures/design-scope-announcement-ao.json',
|
||||
'test/fixtures/design-scope-declaration-ak.json',
|
||||
|
||||
"test/fixtures/eng-option-b-scope-al.json",
|
||||
|
||||
"scripts/resolvers/preamble/generate-preamble-bash.ts",
|
||||
'test/fixtures/pty-companion-cli.ts', 'test/helpers/plan-seed-submission.ts', 'test/fixtures/plan-seed-cli.ts', 'test/helpers/owned-claude-transcript.ts', 'lib/fs-atomic.ts', 'test/helpers/plan-skill-questions.ts', 'test/fixtures/eng-auq-validation-error.json', 'test/fixtures/bash-directory-permission.json', 'test/fixtures/design-tasks-bash-permission.json', 'test/fixtures/read-permission.json', 'test/fixtures/ceo-split-e5-numbered-description-491.json', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/skill-census.ts', 'scripts/resolvers/testing.ts', 'test/helpers/plan-mode-evidence.ts', 'lib/redact-engine.ts', 'lib/redact-patterns.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/plan-count-artifacts.ts', 'test/helpers/plan-count-file-permission.ts', 'test/helpers/plan-count-fixture.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-floor-review.ts', 'test/helpers/plan-floor-target.ts', 'bin/gstack-context-recovery'],
|
||||
// PTY plan-mode smoke (whole file); the SDK plan-edit case below owns plan-design-review-plan-mode.
|
||||
'plan-design-review-plan-mode-smoke': [
|
||||
'lib/claude-public-transcript.ts', 'lib/claude-journal-records.ts', 'lib/claude-owned-journal.ts',
|
||||
@@ -440,7 +411,6 @@ export const E2E_TOUCHFILES: Record<string, string[]> = {
|
||||
'carve-section-loading-land-and-deploy': ['land-and-deploy/**', 'setup', 'bin/gstack-bun-version.sh', 'bin/gstack-state-root.sh', 'lib/state-root.ts', 'bin/gstack-review-log', 'bin/gstack-review-read', 'lib/review-evidence.ts', 'bin/gstack-slug', 'bin/gstack-remote-identity.sh', 'bin/gstack-wtree', 'bin/gstack-config', 'bin/gstack-brain-enqueue', 'test/fixtures/autoplan-amend-input-77.json', 'test/fixtures/autoplan-phase-handoff-6714.json', 'test/fixtures/plan-scope-recovery-av.json', 'test/fixtures/design-scope-checkpoint-at.json', 'scripts/resolvers/composition.ts', 'autoplan/**', 'test/helpers/carve-guards.ts', 'scripts/resolvers/sections.ts', 'scripts/resolvers/redact-doc.ts', 'scripts/gen-skill-docs.ts', 'test/helpers/auq-sdk-capture.ts', 'test/helpers/session-runner.ts', 'bin/gstack-autoplan-snapshot.ts', 'test/fixtures/autoplan/t-ceo-omitted-obligations.json', 'test/fixtures/autoplan/u-ceo-original-loss.json', 'test/fixtures/autoplan/v-ceo-dangling-references.json', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts', 'test/carve-section-loading.test.ts', 'test/helpers/carve-section-case.ts', 'test/fixtures/design-html-section-complete.md', 'test/helpers/carve-plan-fixture.ts', 'test/fixtures/carve-existing-repository/**', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'test/helpers/agent-sdk-runner.ts', 'test/helpers/sdk-system-prompt.ts', 'test/helpers/auq-native-capture.ts', 'test/helpers/auto-decision-state.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/capture-parity-baseline.ts', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/llm-judge.ts', 'test/helpers/native-auto-decide.ts', 'test/helpers/owned-claude-transcript.ts', 'test/helpers/parity-harness.ts', 'test/helpers/size-ledger.ts', 'test/size-ledger/**', 'test/helpers/plan-count-artifacts.ts', 'test/helpers/plan-count-file-permission.ts', 'test/helpers/plan-count-fixture.ts', 'test/helpers/plan-count-pending-exit.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-count-transcript.ts', 'test/helpers/plan-floor-review.ts', 'test/helpers/plan-floor-target.ts', 'test/helpers/plan-scope-selection.ts', 'test/helpers/plan-seed-submission.ts', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/plan-skill-questions.ts', 'test/helpers/pty-screen.ts', 'test/helpers/pty-trust-dialog.ts', 'test/helpers/skill-census.ts'],
|
||||
'carve-section-loading-plan-design-review': ['plan-design-review/**', 'setup', 'bin/gstack-bun-version.sh', 'bin/gstack-state-root.sh', 'lib/state-root.ts', 'bin/gstack-review-log', 'bin/gstack-review-read', 'lib/review-evidence.ts', 'bin/gstack-slug', 'bin/gstack-remote-identity.sh', 'bin/gstack-wtree', 'bin/gstack-config', 'bin/gstack-brain-enqueue', 'test/fixtures/autoplan-amend-input-77.json', 'test/fixtures/autoplan-phase-handoff-6714.json', 'test/fixtures/plan-scope-recovery-av.json', 'test/fixtures/design-scope-checkpoint-at.json', 'scripts/resolvers/composition.ts', 'autoplan/**', 'test/helpers/carve-guards.ts', 'scripts/resolvers/sections.ts', 'scripts/resolvers/redact-doc.ts', 'scripts/gen-skill-docs.ts', 'test/helpers/auq-sdk-capture.ts', 'test/helpers/session-runner.ts', 'bin/gstack-autoplan-snapshot.ts', 'test/fixtures/autoplan/t-ceo-omitted-obligations.json', 'test/fixtures/autoplan/u-ceo-original-loss.json', 'test/fixtures/autoplan/v-ceo-dangling-references.json', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts', 'test/carve-section-loading.test.ts', 'test/helpers/carve-section-case.ts', 'test/fixtures/design-html-section-complete.md', 'test/helpers/carve-plan-fixture.ts', 'test/fixtures/carve-existing-repository/**', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'test/helpers/agent-sdk-runner.ts', 'test/helpers/sdk-system-prompt.ts', 'test/helpers/auq-native-capture.ts', 'test/helpers/auto-decision-state.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/capture-parity-baseline.ts', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/llm-judge.ts', 'test/helpers/native-auto-decide.ts', 'test/helpers/owned-claude-transcript.ts', 'test/helpers/parity-harness.ts', 'test/helpers/size-ledger.ts', 'test/size-ledger/**', 'test/helpers/plan-count-artifacts.ts', 'test/helpers/plan-count-file-permission.ts', 'test/helpers/plan-count-fixture.ts', 'test/helpers/plan-count-pending-exit.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-count-transcript.ts', 'test/helpers/plan-floor-review.ts', 'test/helpers/plan-floor-target.ts', 'test/helpers/plan-scope-selection.ts', 'test/helpers/plan-seed-submission.ts', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/plan-skill-questions.ts', 'test/helpers/pty-screen.ts', 'test/helpers/pty-trust-dialog.ts', 'test/helpers/skill-census.ts'],
|
||||
'carve-section-loading-plan-devex-review': ['plan-devex-review/**', 'setup', 'bin/gstack-bun-version.sh', 'bin/gstack-state-root.sh', 'lib/state-root.ts', 'bin/gstack-review-log', 'bin/gstack-review-read', 'lib/review-evidence.ts', 'bin/gstack-slug', 'bin/gstack-remote-identity.sh', 'bin/gstack-wtree', 'bin/gstack-config', 'bin/gstack-brain-enqueue', 'test/fixtures/autoplan-amend-input-77.json', 'test/fixtures/autoplan-phase-handoff-6714.json', 'test/fixtures/plan-scope-recovery-av.json', 'test/fixtures/design-scope-checkpoint-at.json', 'scripts/resolvers/composition.ts', 'autoplan/**', 'test/helpers/carve-guards.ts', 'scripts/resolvers/sections.ts', 'scripts/resolvers/redact-doc.ts', 'scripts/gen-skill-docs.ts', 'test/helpers/auq-sdk-capture.ts', 'test/helpers/session-runner.ts', 'bin/gstack-autoplan-snapshot.ts', 'test/fixtures/autoplan/t-ceo-omitted-obligations.json', 'test/fixtures/autoplan/u-ceo-original-loss.json', 'test/fixtures/autoplan/v-ceo-dangling-references.json', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts', 'test/carve-section-loading.test.ts', 'test/helpers/carve-section-case.ts', 'test/fixtures/design-html-section-complete.md', 'test/helpers/carve-plan-fixture.ts', 'test/fixtures/carve-existing-repository/**', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'test/helpers/agent-sdk-runner.ts', 'test/helpers/sdk-system-prompt.ts', 'test/helpers/auq-native-capture.ts', 'test/helpers/auto-decision-state.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/capture-parity-baseline.ts', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/llm-judge.ts', 'test/helpers/native-auto-decide.ts', 'test/helpers/owned-claude-transcript.ts', 'test/helpers/parity-harness.ts', 'test/helpers/size-ledger.ts', 'test/size-ledger/**', 'test/helpers/plan-count-artifacts.ts', 'test/helpers/plan-count-file-permission.ts', 'test/helpers/plan-count-fixture.ts', 'test/helpers/plan-count-pending-exit.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-count-transcript.ts', 'test/helpers/plan-floor-review.ts', 'test/helpers/plan-floor-target.ts', 'test/helpers/plan-scope-selection.ts', 'test/helpers/plan-seed-submission.ts', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/plan-skill-questions.ts', 'test/helpers/pty-screen.ts', 'test/helpers/pty-trust-dialog.ts', 'test/helpers/skill-census.ts'],
|
||||
'carve-section-loading-plan-eng-review': ['plan-eng-review/**', 'setup', 'bin/gstack-bun-version.sh', 'bin/gstack-state-root.sh', 'lib/state-root.ts', 'bin/gstack-review-log', 'bin/gstack-review-read', 'lib/review-evidence.ts', 'bin/gstack-slug', 'bin/gstack-remote-identity.sh', 'bin/gstack-wtree', 'bin/gstack-config', 'bin/gstack-brain-enqueue', 'test/fixtures/autoplan-amend-input-77.json', 'test/fixtures/autoplan-phase-handoff-6714.json', 'scripts/resolvers/learnings.ts', 'test/fixtures/plan-scope-recovery-av.json', 'test/fixtures/design-scope-checkpoint-at.json', 'scripts/resolvers/composition.ts', 'autoplan/**', 'test/helpers/carve-guards.ts', 'scripts/resolvers/sections.ts', 'scripts/resolvers/redact-doc.ts', 'scripts/gen-skill-docs.ts', 'test/helpers/auq-sdk-capture.ts', 'test/helpers/session-runner.ts', 'bin/gstack-autoplan-snapshot.ts', 'test/fixtures/autoplan/t-ceo-omitted-obligations.json', 'test/fixtures/autoplan/u-ceo-original-loss.json', 'test/fixtures/autoplan/v-ceo-dangling-references.json', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts', 'test/carve-section-loading.test.ts', 'test/helpers/carve-section-case.ts', 'test/fixtures/design-html-section-complete.md', 'scripts/resolvers/testing.ts', 'test/helpers/carve-plan-fixture.ts', 'test/fixtures/carve-existing-repository/**', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'test/helpers/agent-sdk-runner.ts', 'test/helpers/sdk-system-prompt.ts', 'test/helpers/auq-native-capture.ts', 'test/helpers/auto-decision-state.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/capture-parity-baseline.ts', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/llm-judge.ts', 'test/helpers/native-auto-decide.ts', 'test/helpers/owned-claude-transcript.ts', 'test/helpers/parity-harness.ts', 'test/helpers/size-ledger.ts', 'test/size-ledger/**', 'test/helpers/plan-count-artifacts.ts', 'test/helpers/plan-count-file-permission.ts', 'test/helpers/plan-count-fixture.ts', 'test/helpers/plan-count-pending-exit.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-count-transcript.ts', 'test/helpers/plan-floor-review.ts', 'test/helpers/plan-floor-target.ts', 'test/helpers/plan-scope-selection.ts', 'test/helpers/plan-seed-submission.ts', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/plan-skill-questions.ts', 'test/helpers/pty-screen.ts', 'test/helpers/pty-trust-dialog.ts', 'test/helpers/skill-census.ts'],
|
||||
'carve-section-loading-qa': ['qa/**', 'setup', 'bin/gstack-bun-version.sh', 'bin/gstack-state-root.sh', 'lib/state-root.ts', 'bin/gstack-review-log', 'bin/gstack-review-read', 'lib/review-evidence.ts', 'bin/gstack-slug', 'bin/gstack-remote-identity.sh', 'bin/gstack-wtree', 'bin/gstack-config', 'bin/gstack-brain-enqueue', 'test/fixtures/autoplan-amend-input-77.json', 'test/fixtures/autoplan-phase-handoff-6714.json', 'test/fixtures/plan-scope-recovery-av.json', 'test/fixtures/design-scope-checkpoint-at.json', 'scripts/resolvers/composition.ts', 'autoplan/**', 'test/helpers/carve-guards.ts', 'scripts/resolvers/sections.ts', 'scripts/resolvers/redact-doc.ts', 'scripts/gen-skill-docs.ts', 'test/helpers/auq-sdk-capture.ts', 'test/helpers/session-runner.ts', 'bin/gstack-autoplan-snapshot.ts', 'test/fixtures/autoplan/t-ceo-omitted-obligations.json', 'test/fixtures/autoplan/u-ceo-original-loss.json', 'test/fixtures/autoplan/v-ceo-dangling-references.json', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts', 'test/carve-section-loading.test.ts', 'test/helpers/carve-section-case.ts', 'test/fixtures/design-html-section-complete.md', 'test/helpers/carve-plan-fixture.ts', 'test/fixtures/carve-existing-repository/**', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'test/helpers/agent-sdk-runner.ts', 'test/helpers/sdk-system-prompt.ts', 'test/helpers/auq-native-capture.ts', 'test/helpers/auto-decision-state.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/capture-parity-baseline.ts', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/llm-judge.ts', 'test/helpers/native-auto-decide.ts', 'test/helpers/owned-claude-transcript.ts', 'test/helpers/parity-harness.ts', 'test/helpers/size-ledger.ts', 'test/size-ledger/**', 'test/helpers/plan-count-artifacts.ts', 'test/helpers/plan-count-file-permission.ts', 'test/helpers/plan-count-fixture.ts', 'test/helpers/plan-count-pending-exit.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-count-transcript.ts', 'test/helpers/plan-floor-review.ts', 'test/helpers/plan-floor-target.ts', 'test/helpers/plan-scope-selection.ts', 'test/helpers/plan-seed-submission.ts', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/plan-skill-questions.ts', 'test/helpers/pty-screen.ts', 'test/helpers/pty-trust-dialog.ts', 'test/helpers/skill-census.ts'],
|
||||
'carve-section-loading-retro': ['retro/**', 'setup', 'bin/gstack-bun-version.sh', 'bin/gstack-state-root.sh', 'lib/state-root.ts', 'bin/gstack-review-log', 'bin/gstack-review-read', 'lib/review-evidence.ts', 'bin/gstack-slug', 'bin/gstack-remote-identity.sh', 'bin/gstack-wtree', 'bin/gstack-config', 'bin/gstack-brain-enqueue', 'test/fixtures/autoplan-amend-input-77.json', 'test/fixtures/autoplan-phase-handoff-6714.json', 'test/fixtures/plan-scope-recovery-av.json', 'test/fixtures/design-scope-checkpoint-at.json', 'scripts/resolvers/composition.ts', 'autoplan/**', 'test/helpers/carve-guards.ts', 'scripts/resolvers/sections.ts', 'scripts/resolvers/redact-doc.ts', 'scripts/gen-skill-docs.ts', 'test/helpers/auq-sdk-capture.ts', 'test/helpers/session-runner.ts', 'bin/gstack-autoplan-snapshot.ts', 'test/fixtures/autoplan/t-ceo-omitted-obligations.json', 'test/fixtures/autoplan/u-ceo-original-loss.json', 'test/fixtures/autoplan/v-ceo-dangling-references.json', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts', 'test/carve-section-loading.test.ts', 'test/helpers/carve-section-case.ts', 'test/fixtures/design-html-section-complete.md', 'test/helpers/carve-plan-fixture.ts', 'test/fixtures/carve-existing-repository/**', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'test/helpers/agent-sdk-runner.ts', 'test/helpers/sdk-system-prompt.ts', 'test/helpers/auq-native-capture.ts', 'test/helpers/auto-decision-state.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/capture-parity-baseline.ts', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/llm-judge.ts', 'test/helpers/native-auto-decide.ts', 'test/helpers/owned-claude-transcript.ts', 'test/helpers/parity-harness.ts', 'test/helpers/size-ledger.ts', 'test/size-ledger/**', 'test/helpers/plan-count-artifacts.ts', 'test/helpers/plan-count-file-permission.ts', 'test/helpers/plan-count-fixture.ts', 'test/helpers/plan-count-pending-exit.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-count-transcript.ts', 'test/helpers/plan-floor-review.ts', 'test/helpers/plan-floor-target.ts', 'test/helpers/plan-scope-selection.ts', 'test/helpers/plan-seed-submission.ts', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/plan-skill-questions.ts', 'test/helpers/pty-screen.ts', 'test/helpers/pty-trust-dialog.ts', 'test/helpers/skill-census.ts'],
|
||||
'carve-section-loading-review': ['review/**', 'setup', 'bin/gstack-bun-version.sh', 'bin/gstack-state-root.sh', 'lib/state-root.ts', 'bin/gstack-review-log', 'bin/gstack-review-read', 'lib/review-evidence.ts', 'bin/gstack-slug', 'bin/gstack-remote-identity.sh', 'bin/gstack-wtree', 'bin/gstack-config', 'bin/gstack-brain-enqueue', 'test/fixtures/autoplan-amend-input-77.json', 'test/fixtures/autoplan-phase-handoff-6714.json', 'test/fixtures/plan-scope-recovery-av.json', 'test/fixtures/design-scope-checkpoint-at.json', 'scripts/resolvers/composition.ts', 'autoplan/**', 'test/helpers/carve-guards.ts', 'scripts/resolvers/sections.ts', 'scripts/resolvers/redact-doc.ts', 'scripts/gen-skill-docs.ts', 'test/helpers/auq-sdk-capture.ts', 'test/helpers/session-runner.ts', 'bin/gstack-autoplan-snapshot.ts', 'test/fixtures/autoplan/t-ceo-omitted-obligations.json', 'test/fixtures/autoplan/u-ceo-original-loss.json', 'test/fixtures/autoplan/v-ceo-dangling-references.json', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts', 'test/carve-section-loading.test.ts', 'test/helpers/carve-section-case.ts', 'test/fixtures/design-html-section-complete.md', 'test/helpers/carve-plan-fixture.ts', 'test/fixtures/carve-existing-repository/**', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'test/helpers/agent-sdk-runner.ts', 'test/helpers/sdk-system-prompt.ts', 'test/helpers/auq-native-capture.ts', 'test/helpers/auto-decision-state.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/capture-parity-baseline.ts', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/llm-judge.ts', 'test/helpers/native-auto-decide.ts', 'test/helpers/owned-claude-transcript.ts', 'test/helpers/parity-harness.ts', 'test/helpers/size-ledger.ts', 'test/size-ledger/**', 'test/helpers/plan-count-artifacts.ts', 'test/helpers/plan-count-file-permission.ts', 'test/helpers/plan-count-fixture.ts', 'test/helpers/plan-count-pending-exit.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-count-transcript.ts', 'test/helpers/plan-floor-review.ts', 'test/helpers/plan-floor-target.ts', 'test/helpers/plan-scope-selection.ts', 'test/helpers/plan-seed-submission.ts', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/plan-skill-questions.ts', 'test/helpers/pty-screen.ts', 'test/helpers/pty-trust-dialog.ts', 'test/helpers/skill-census.ts'],
|
||||
@@ -457,22 +427,6 @@ export const E2E_TOUCHFILES: Record<string, string[]> = {
|
||||
// review-phase AskUserQuestion). Uses runPlanSkillFloorCheck — minimal
|
||||
// "did agent fire ANY AUQ?" observer that exits early on first non-permission
|
||||
// numbered-option render. ~1-3 min typical wall time per test, ~$2-6 total.
|
||||
'plan-eng-finding-floor': ['bin/gstack-state-root.sh', 'lib/state-root.ts', 'test/helpers/pty-screen.ts',
|
||||
'lib/claude-public-transcript.ts', 'lib/claude-journal-records.ts', 'lib/claude-owned-journal.ts', 'test/fixtures/plan-create-prepublication-491.json', 'test/fixtures/plan-create-combined-permission-70b.json', 'test/fixtures/plan-floor-quote-70b.json',
|
||||
|
||||
'test/fixtures/plan-create-permission-361c.json',
|
||||
'test/helpers/plan-floor-review.ts',
|
||||
|
||||
'test/fixtures/plan-floor-routing-361c.json',
|
||||
|
||||
'test/fixtures/ceo-report-permission-fb10.json', 'test/fixtures/plan-floor-permission-fb10.json', 'test/helpers/plan-count-file-permission.ts', 'test/fixtures/plan-edit-cropped-permission-1579.json', 'test/fixtures/plan-count-permission-target-ad-v2.json', 'test/fixtures/design-crop-gutter-ap.json', 'test/fixtures/plan-count-crop-ak.json', 'test/fixtures/plan-count-long-edit-0bcd.json', 'test/fixtures/plan-count-cropped-wrap-6714.json',
|
||||
'scripts/resolvers/learnings.ts',
|
||||
|
||||
"test/fixtures/plan-scope-recovery-av.json", 'bin/gstack-skill-start', 'bin/gstack-skill-end', 'plan-eng-review/**', 'scripts/resolvers/preamble.ts', 'scripts/resolvers/preamble-hoist.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/preamble/generate-completion-status.ts', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/fixtures/design-ui-boxed-question.json', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/pty-trust-dialog.ts', 'test/fixtures/forcing-finding-seeds.ts', 'test/skill-e2e-plan-eng-finding-floor.test.ts', 'test/fixtures/eng-batching-t-calls.json', 'test/fixtures/eng-scope-y-calls.json', 'test/fixtures/eng-d2-truncated-border-0bcd.json', 'test/fixtures/eng-d1-clipped-elision-1579.json', 'test/fixtures/eng-d2-planning-prelude-4d.json', 'test/fixtures/ceo-approach-z-call.json', 'test/fixtures/ceo-approach-z-screen.txt', 'test/fixtures/eng-binding-z-calls.json', 'test/fixtures/eng-binding-retry-z-calls.json', 'test/helpers/plan-floor-target.ts', 'test/helpers/plan-count-fixture.ts', 'test/helpers/plan-count-artifacts.ts',
|
||||
"test/fixtures/eng-injected-export-aq.json", "test/fixtures/eng-library-hooks-aq.json",
|
||||
|
||||
"scripts/resolvers/preamble/generate-preamble-bash.ts",
|
||||
'test/fixtures/pty-companion-cli.ts', 'lib/fs-atomic.ts', 'test/helpers/plan-skill-questions.ts', 'test/fixtures/eng-auq-validation-error.json', 'test/fixtures/bash-directory-permission.json', 'test/fixtures/design-tasks-bash-permission.json', 'test/fixtures/read-permission.json', 'test/fixtures/ceo-split-e5-numbered-description-491.json', 'test/helpers/plan-skill-question-events.ts', 'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/skill-census.ts', 'scripts/resolvers/testing.ts', 'test/helpers/auto-decision-state.ts', 'test/helpers/autoplan-artifact-digest.ts', 'test/helpers/autoplan-artifact-permission.ts', 'test/helpers/autoplan-artifact-recorder.ts', 'test/helpers/dx-selected-navigation.ts', 'test/helpers/e2e-gate.ts', 'test/helpers/eng-cache-writer-decision.ts', 'test/helpers/native-auto-decide.ts', 'test/helpers/owned-claude-transcript.ts', 'test/helpers/plan-count-pending-exit.ts', 'test/helpers/plan-count-pending-question.ts', 'test/helpers/plan-count-transcript.ts', 'test/helpers/plan-scope-selection.ts', 'test/helpers/plan-seed-submission.ts', 'bin/gstack-context-recovery'],
|
||||
'plan-ceo-finding-floor': [ 'ETHOS.md','bin/gstack-state-root.sh', 'lib/state-root.ts', 'test/helpers/pty-screen.ts',
|
||||
'lib/claude-public-transcript.ts', 'lib/claude-journal-records.ts', 'lib/claude-owned-journal.ts', 'test/fixtures/plan-create-prepublication-491.json', 'test/fixtures/plan-create-combined-permission-70b.json', 'test/fixtures/plan-floor-quote-70b.json',
|
||||
|
||||
@@ -601,20 +555,6 @@ export const E2E_TOUCHFILES: Record<string, string[]> = {
|
||||
'plan-ceo-review-format-approach': [ 'ETHOS.md', 'plan-ceo-review/**', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/preamble/generate-completeness-section.ts', 'scripts/resolvers/preamble.ts', 'scripts/resolvers/preamble-hoist.ts', 'model-overlays/opus-4-7.md', 'test/helpers/llm-judge.ts', 'test/skill-e2e-plan-format.test.ts', 'test/helpers/plan-format-kind-note.ts',
|
||||
'test/helpers/office-hours-attempt.ts', 'scripts/resolvers/tasks-section.ts'
|
||||
],
|
||||
'plan-eng-review-format-coverage': [
|
||||
'scripts/resolvers/learnings.ts',
|
||||
|
||||
"test/fixtures/plan-scope-recovery-av.json", 'plan-eng-review/**', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/preamble/generate-completeness-section.ts', 'scripts/resolvers/preamble.ts', 'scripts/resolvers/preamble-hoist.ts', 'model-overlays/opus-4-7.md', 'test/helpers/llm-judge.ts', 'test/skill-e2e-plan-format.test.ts', 'test/helpers/plan-format-kind-note.ts',
|
||||
"scripts/resolvers/preamble/generate-preamble-bash.ts", "scripts/resolvers/preamble/generate-completion-status.ts",
|
||||
'scripts/resolvers/testing.ts', 'test/helpers/office-hours-attempt.ts', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts'
|
||||
],
|
||||
'plan-eng-review-format-kind': [
|
||||
'scripts/resolvers/learnings.ts',
|
||||
|
||||
"test/fixtures/plan-scope-recovery-av.json", 'plan-eng-review/**', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/preamble/generate-completeness-section.ts', 'scripts/resolvers/preamble.ts', 'scripts/resolvers/preamble-hoist.ts', 'model-overlays/opus-4-7.md', 'test/helpers/llm-judge.ts', 'test/skill-e2e-plan-format.test.ts', 'test/helpers/plan-format-kind-note.ts',
|
||||
"scripts/resolvers/preamble/generate-preamble-bash.ts", "scripts/resolvers/preamble/generate-completion-status.ts",
|
||||
'scripts/resolvers/testing.ts', 'test/helpers/office-hours-attempt.ts', 'scripts/resolvers/review-dashboard.ts', 'scripts/resolvers/plan-gates.ts', 'scripts/resolvers/spec-review.ts', 'scripts/resolvers/outside-voice-steps.ts', 'scripts/resolvers/review-scope.ts', 'scripts/resolvers/outside-voice.ts'
|
||||
],
|
||||
|
||||
// v1.7.0.0 Pros/Cons format cadence + format + negative-escape evals.
|
||||
// Dependencies: same as format-mode + the 4 plan-review templates + overlay.
|
||||
@@ -1357,7 +1297,6 @@ export const E2E_TIERS: Record<string, 'gate' | 'periodic' | 'marathon'> = {
|
||||
'plan-ceo-review-expansion-energy': 'periodic', // Demoted from gate (2026-08 audit): Opus generator + subjective 2-axis >=4/5 LLM-judge threshold in the merge lane — the exact class siblings were demoted for (a +21-line preamble change once flipped the score). CLAUDE.md's own rule: Opus model test -> periodic.
|
||||
'plan-eng-review': 'periodic',
|
||||
'plan-eng-review-artifact': 'periodic', // Checkpoint: resumes at Test review from a real Scope Challenge ledger
|
||||
'plan-eng-review-artifact-full': 'marathon', // Full fresh /plan-eng-review through Test review (498 s pass; 595 s timeouts at 600 s before Test review)
|
||||
'plan-eng-coverage-audit': 'gate',
|
||||
'ship-coverage-value': 'gate',
|
||||
'review-test-value': 'gate',
|
||||
@@ -1372,7 +1311,6 @@ export const E2E_TIERS: Record<string, 'gate' | 'periodic' | 'marathon'> = {
|
||||
// the hardened ask-first gate + the collapsed-form detector lifted them from
|
||||
// always-failing to mostly-passing, but they are not deterministic gates.
|
||||
'plan-ceo-review-plan-mode': 'gate',
|
||||
'plan-eng-review-plan-mode': 'periodic',
|
||||
'plan-design-review-plan-mode': 'periodic',
|
||||
'plan-design-review-plan-mode-smoke': 'periodic',
|
||||
'plan-devex-review-plan-mode': 'gate',
|
||||
@@ -1409,7 +1347,6 @@ export const E2E_TIERS: Record<string, 'gate' | 'periodic' | 'marathon'> = {
|
||||
'carve-section-loading-land-and-deploy': 'periodic',
|
||||
'carve-section-loading-plan-design-review': 'periodic',
|
||||
'carve-section-loading-plan-devex-review': 'periodic',
|
||||
'carve-section-loading-plan-eng-review': 'periodic',
|
||||
'carve-section-loading-qa': 'periodic',
|
||||
'carve-section-loading-retro': 'periodic',
|
||||
'carve-section-loading-review': 'periodic',
|
||||
@@ -1421,7 +1358,6 @@ export const E2E_TIERS: Record<string, 'gate' | 'periodic' | 'marathon'> = {
|
||||
// run drives a full skill end-to-end (~25 min, ~$5/run). Sequential
|
||||
// execution during calibration; concurrent opt-in only after measured
|
||||
// comparison agrees (plan §D15).
|
||||
'plan-eng-finding-floor': 'periodic', // stochastic ask-first (see plan-mode-handshake note); periodic
|
||||
'plan-ceo-finding-floor': 'gate',
|
||||
'plan-design-finding-floor': 'periodic', // stochastic ask-first (see plan-mode-handshake note); periodic
|
||||
'plan-devex-finding-floor': 'gate',
|
||||
@@ -1445,8 +1381,6 @@ export const E2E_TIERS: Record<string, 'gate' | 'periodic' | 'marathon'> = {
|
||||
// AskUserQuestion format regression — periodic (Opus 4.7 non-deterministic benchmark)
|
||||
'plan-ceo-review-format-mode': 'periodic',
|
||||
'plan-ceo-review-format-approach': 'periodic',
|
||||
'plan-eng-review-format-coverage': 'periodic',
|
||||
'plan-eng-review-format-kind': 'periodic',
|
||||
|
||||
// Office-hours Phase 4 silent-auto-decide regression — periodic (Phase 4
|
||||
// requires the agent to invent 2-3 architectures, more open-ended than the
|
||||
@@ -1798,11 +1732,9 @@ export const E2E_KINDS: Record<string, 'rule' | 'behavior' | 'judge'> = {
|
||||
'plan-ceo-review-expansion-energy': 'behavior',
|
||||
'plan-eng-review': 'rule',
|
||||
'plan-eng-review-artifact': 'rule',
|
||||
'plan-eng-review-artifact-full': 'rule',
|
||||
'plan-eng-coverage-audit': 'rule',
|
||||
'plan-review-report': 'rule',
|
||||
'plan-ceo-review-plan-mode': 'rule',
|
||||
'plan-eng-review-plan-mode': 'rule',
|
||||
'plan-design-review-plan-mode': 'rule',
|
||||
'plan-design-review-plan-mode-smoke': 'rule',
|
||||
'ship-coverage-value': 'rule',
|
||||
@@ -1835,13 +1767,11 @@ export const E2E_KINDS: Record<string, 'rule' | 'behavior' | 'judge'> = {
|
||||
'carve-section-loading-land-and-deploy': 'rule',
|
||||
'carve-section-loading-plan-design-review': 'rule',
|
||||
'carve-section-loading-plan-devex-review': 'rule',
|
||||
'carve-section-loading-plan-eng-review': 'rule',
|
||||
'carve-section-loading-qa': 'rule',
|
||||
'carve-section-loading-retro': 'rule',
|
||||
'carve-section-loading-review': 'rule',
|
||||
'carve-section-loading-setup-gbrain': 'rule',
|
||||
'carve-section-loading-spec': 'rule',
|
||||
'plan-eng-finding-floor': 'rule',
|
||||
'plan-ceo-finding-floor': 'rule',
|
||||
'plan-design-finding-floor': 'rule',
|
||||
'plan-devex-finding-floor': 'rule',
|
||||
@@ -1852,8 +1782,6 @@ export const E2E_KINDS: Record<string, 'rule' | 'behavior' | 'judge'> = {
|
||||
'setup-gbrain-path4-local-pglite': 'rule',
|
||||
'plan-ceo-review-format-mode': 'behavior',
|
||||
'plan-ceo-review-format-approach': 'behavior',
|
||||
'plan-eng-review-format-coverage': 'behavior',
|
||||
'plan-eng-review-format-kind': 'behavior',
|
||||
'office-hours-phase4-fork': 'behavior',
|
||||
'llm-judge-recommendation': 'judge',
|
||||
'plan-ceo-review-prosons-cadence': 'behavior',
|
||||
@@ -2037,10 +1965,6 @@ export const BEHAVIOR_WHY: Record<string, string> = {
|
||||
"Mode-question wording (Completeness line vs kind note) is live formatting of one AskUserQuestion.",
|
||||
'plan-ceo-review-format-approach':
|
||||
"Approach-menu Completeness wording is live formatting of one AskUserQuestion.",
|
||||
'plan-eng-review-format-coverage':
|
||||
"Coverage-issue Completeness wording is live formatting of one AskUserQuestion.",
|
||||
'plan-eng-review-format-kind':
|
||||
"Kind-note wording is live formatting of one AskUserQuestion.",
|
||||
'plan-ceo-review-prosons-cadence':
|
||||
"Pros/Cons cadence on a hard-stop question is live formatting; either the escape or the full block is accepted.",
|
||||
'plan-review-prosons-format':
|
||||
|
||||
@@ -557,8 +557,6 @@ describe('session runner native CLI max-turns exit semantics', () => {
|
||||
const FORMAT_CASES = [
|
||||
['skill-e2e-plan-format.test.ts', 'plan-ceo-review-format-mode'],
|
||||
['skill-e2e-plan-format.test.ts', 'plan-ceo-review-format-approach'],
|
||||
['skill-e2e-plan-format.test.ts', 'plan-eng-review-format-coverage'],
|
||||
['skill-e2e-plan-format.test.ts', 'plan-eng-review-format-kind'],
|
||||
['skill-e2e-plan-prosons.test.ts', 'plan-review-prosons-format'],
|
||||
['skill-e2e-plan-prosons.test.ts', 'plan-review-prosons-hardstop-neg'],
|
||||
['skill-e2e-plan-prosons.test.ts', 'plan-review-prosons-neutral-neg'],
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 2026-10-03 periodic and gate census artifacts (run 37151477069, commit
|
||||
* ac20ef1), whose report counted deselections as SKIPPED 82/282 and left
|
||||
* 72/24 testcases unattributed. Budget records follow the current declared
|
||||
* policy (plan-mode-no-op: 3,720,000 ms since v1.91.18.0 added its devex member).
|
||||
* policy (plan-mode-no-op: 2,520,000 ms since its plan-eng-review member retired, GST-1698).
|
||||
* The periodic fixture is re-shaped to the current case shards: qa-workflow runs
|
||||
* as its qa-fix-loop case shard (its three gate-tier siblings become sibling
|
||||
* deselections) and the review carve runs as a case of the consolidated
|
||||
|
||||
@@ -22,16 +22,14 @@ const expectedWalls = {
|
||||
'test/skill-e2e-shared-libs-paths.test.ts': 1_920_000,
|
||||
'test/skill-e2e-ship-docsync.test.ts': 4_920_000,
|
||||
'test/skill-e2e-auq-consistency.test.ts': 1_080_000,
|
||||
'test/skill-e2e-auq-matrix.test.ts': 1_920_000,
|
||||
'test/skill-e2e-plan-format.test.ts': 1_360_000,
|
||||
'test/skill-e2e-auq-matrix.test.ts': 1_620_000,
|
||||
'test/skill-e2e-plan-format.test.ts': 740_000,
|
||||
'test/skill-e2e-auto-decide-preserved.test.ts': 1_020_000,
|
||||
'test/skill-e2e-plan-ceo-finding-floor.test.ts': 1_020_000,
|
||||
'test/skill-e2e-plan-eng-finding-floor.test.ts': 1_020_000,
|
||||
'test/skill-e2e-plan-design-finding-floor.test.ts': 1_020_000,
|
||||
'test/skill-e2e-plan-devex-finding-floor.test.ts': 1_020_000,
|
||||
'test/skill-e2e-plan-mode-no-op.test.ts': 3_720_000,
|
||||
'test/skill-e2e-plan-mode-no-op.test.ts': 2_520_000,
|
||||
'test/skill-e2e-plan-ceo-mode-routing.test.ts': 1_320_000,
|
||||
'test/skill-e2e-plan-eng-plan-mode.test.ts': 1_320_000,
|
||||
'test/skill-e2e-plan-prosons.test.ts': 1_360_000,
|
||||
'test/skill-e2e-plan.test.ts': 3_120_000,
|
||||
};
|
||||
@@ -50,9 +48,9 @@ test('paid evals never retry: every paid file and registered row runs once', ()
|
||||
}
|
||||
});
|
||||
|
||||
test('registration covers exactly the sixteen demonstrated full-file retry gaps', () => {
|
||||
test('registration covers exactly the fourteen demonstrated full-file retry gaps', () => {
|
||||
expect(Object.fromEntries(newBudgets.map(row => [row.file, row.shardMs]))).toEqual(expectedWalls);
|
||||
expect(new Set(FILE_RETRY_BUDGETS.map(row => row.file)).size).toBe(18);
|
||||
expect(new Set(FILE_RETRY_BUDGETS.map(row => row.file)).size).toBe(16);
|
||||
expect(STRICT_RETRY_CASE_BUDGETS.map(row => row.file)).toEqual([
|
||||
...FINDING_RETRY_BUDGETS.map(row => row.file), AUQ_CONSISTENCY_RETRY_BUDGET.file,
|
||||
]);
|
||||
@@ -82,20 +80,19 @@ test('source allowances retain all captures, cases, and finalization grace', ()
|
||||
expect(read('test/helpers/codex-eval.ts')).toContain('CODEX_EVAL_FINALIZE_MS = 2 * CODEX_DRAIN_GRACE_MS');
|
||||
expect(read('test/helpers/codex-session-runner.ts')).toMatch(/CODEX_DRAIN_GRACE_MS\s*=\s*5_000/);
|
||||
expect(read('test/helpers/office-hours-attempt.ts')).toContain('OFFICE_HOURS_BUN_GRACE_MS = 10_000');
|
||||
for (const file of ['auto-decide-preserved', 'plan-ceo-finding-floor', 'plan-eng-finding-floor', 'plan-design-finding-floor', 'plan-devex-finding-floor']) {
|
||||
for (const file of ['auto-decide-preserved', 'plan-ceo-finding-floor', 'plan-design-finding-floor', 'plan-devex-finding-floor']) {
|
||||
expect(timeoutExpressions(`test/skill-e2e-${file}.test.ts`)).toEqual(['PTY_MS']);
|
||||
if (file.endsWith('-finding-floor')) expect(read(`test/skill-e2e-${file}.test.ts`)).toContain('timeoutMs: CAPTURE_LONG_MS');
|
||||
}
|
||||
const noop = read('test/skill-e2e-plan-mode-no-op.test.ts');
|
||||
expect(noop).toContain("['plan-ceo-review', 'plan-eng-review', 'plan-design-review', 'plan-devex-review'] as const");
|
||||
expect(noop).toContain("['plan-eng-review', 'plan-design-review'] as const");
|
||||
expect(noop).toContain("['plan-ceo-review', 'plan-design-review', 'plan-devex-review'] as const");
|
||||
expect(noop).toContain("['plan-design-review'] as const");
|
||||
expect(timeoutExpressions('test/skill-e2e-plan-mode-no-op.test.ts')).toEqual(Array(2).fill('CAPTURE_LONG_MS'));
|
||||
expect(read('test/skill-e2e-plan-ceo-mode-routing.test.ts').match(/^\s*{ mode: '/gm)).toHaveLength(2);
|
||||
expect(timeoutExpressions('test/skill-e2e-plan-ceo-mode-routing.test.ts')).toEqual(['CAPTURE_LONG_MS']);
|
||||
expect(timeoutExpressions('test/skill-e2e-plan-eng-plan-mode.test.ts')).toEqual(Array(2).fill('CAPTURE_LONG_MS'));
|
||||
expect(timeoutExpressions('test/skill-e2e-plan-prosons.test.ts')).toEqual(Array(4).fill('CAPTURE_MS + OFFICE_HOURS_BUN_GRACE_MS'));
|
||||
expect(timeoutExpressions('test/skill-e2e-plan-format.test.ts')).toEqual(Array(4).fill('CAPTURE_MS + OFFICE_HOURS_BUN_GRACE_MS'));
|
||||
expect(read('test/skill-e2e-auq-matrix.test.ts').match(/^ skill: '/gm)).toHaveLength(6);
|
||||
expect(timeoutExpressions('test/skill-e2e-plan-format.test.ts')).toEqual(Array(2).fill('CAPTURE_MS + OFFICE_HOURS_BUN_GRACE_MS'));
|
||||
expect(read('test/skill-e2e-auq-matrix.test.ts').match(/^ skill: '/gm)).toHaveLength(5);
|
||||
expect(timeoutExpressions('test/skill-e2e-auq-matrix.test.ts')).toEqual(['CAPTURE_MS']);
|
||||
expect(timeoutExpressions('test/skill-e2e-plan.test.ts')).toEqual([
|
||||
'PTY_MS', 'PTY_MS', 'CAPTURE_LONG_MS', 'CAPTURE_LONG_MS',
|
||||
|
||||
@@ -521,10 +521,10 @@ test('duplicate declarations and existing fixture files cannot be rewritten into
|
||||
expect(() => createPlanCountFixture(FORCING_FLOOR_CEO,{requestedPlanPath,files:{'gstack-test-plan-ceo-floor.md':'different source'}})).toThrow();
|
||||
});
|
||||
|
||||
test.each(['auq_observed','timeout','throw'])('all four actual floor registrations keep the declared actor and %s outcome', outcome => {
|
||||
test.each(['auq_observed','timeout','throw'])('all three actual floor registrations keep the declared actor and %s outcome', outcome => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(),'floor-registration-free-'));
|
||||
const worker = path.join(dir,'registrations.test.ts'), facts = path.join(dir,'calls.jsonl');
|
||||
const files = ['ceo','eng','design','devex'].map(kind => path.join(ROOT,`test/skill-e2e-plan-${kind}-finding-floor.test.ts`));
|
||||
const files = ['ceo','design','devex'].map(kind => path.join(ROOT,`test/skill-e2e-plan-${kind}-finding-floor.test.ts`));
|
||||
try {
|
||||
for (const file of files) expect(fs.statSync(file).isFile()).toBe(true);
|
||||
fs.writeFileSync(worker, `
|
||||
@@ -557,7 +557,7 @@ ${files.map(file => `await import(${JSON.stringify(file)});`).join('\n')}
|
||||
const output = result.stdout.toString()+result.stderr.toString();
|
||||
expect(result.exitCode,output).toBe(outcome === 'auq_observed' ? 0 : 1);
|
||||
expect(fs.readFileSync(facts,'utf8').trim().split('\n').map(line=>JSON.parse(line).kind).sort())
|
||||
.toEqual(['ceo','design','devex','eng']);
|
||||
.toEqual(['ceo','design','devex']);
|
||||
if(outcome !== 'auq_observed') expect(output).toContain(outcome === 'throw' ? 'controlled runner failure' : 'floor test FAILED: outcome=timeout');
|
||||
} finally {fs.rmSync(dir,{recursive:true,force:true});}
|
||||
},25_000);
|
||||
|
||||
@@ -11,10 +11,10 @@ const SECRET = 'fixture-private-diagnostic-value';
|
||||
|
||||
// Import the actual paid registration in an isolated Bun process. Only model
|
||||
// execution is replaced; Bun assertions and the report-file validator are real.
|
||||
for (const skill of ['design', 'eng'] as const) {
|
||||
for (const skill of ['design'] as const) {
|
||||
const PAID_FILE = `test/skill-e2e-plan-${skill}-plan-mode.test.ts`;
|
||||
const skillName = `plan-${skill}-review`;
|
||||
for (const scenario of ['success', 'missing-auto-select', 'scope-question', 'bad-report', 'bad-outcome', 'retry', 'unwritable', ...(skill === 'eng' ? ['missing-decisions'] : [])]) {
|
||||
for (const scenario of ['success', 'missing-auto-select', 'scope-question', 'bad-report', 'bad-outcome', 'retry', 'unwritable']) {
|
||||
test(`${skill} plan-mode caller preserves its outcome and failure evidence: ${scenario}`, () => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'design-mode-evidence-'));
|
||||
const evalDir = path.join(dir, 'artifacts');
|
||||
@@ -29,7 +29,7 @@ const runnerPath = ${JSON.stringify(path.join(ROOT, 'test/helpers/claude-pty-run
|
||||
const { assertReportAtBottomIfPlanWritten, planFileHasDecisionsSection } = await import(runnerPath);
|
||||
const scenario = ${JSON.stringify(scenario)};
|
||||
const report = ${JSON.stringify(path.join(dir, 'plan.md'))};
|
||||
fs.writeFileSync(report, '# Plan\\n' + (scenario === 'missing-decisions' ? '' : '## Decisions to confirm\\nPending.\\n')
|
||||
fs.writeFileSync(report, '# Plan\\n## Decisions to confirm\\nPending.\\n'
|
||||
+ '## GSTACK REVIEW REPORT\\nDone.\\n' + (scenario === 'bad-report' ? '## Unexpected trailing section\\n' : ''));
|
||||
let calls = 0;
|
||||
mock.module(runnerPath, () => ({
|
||||
@@ -37,10 +37,10 @@ mock.module(runnerPath, () => ({
|
||||
runPlanSkillObservation: async opts => {
|
||||
const call = ++calls;
|
||||
fs.appendFileSync(${JSON.stringify(events)}, JSON.stringify({ call, opts }) + '\\n');
|
||||
return { outcome: ['bad-report', 'missing-decisions'].includes(scenario) ? 'plan_ready' : scenario === 'bad-outcome' ? 'auto_decided' : 'asked',
|
||||
return { outcome: scenario === 'bad-report' ? 'plan_ready' : scenario === 'bad-outcome' ? 'auto_decided' : 'asked',
|
||||
summary: 'Returned observation ' + call, elapsedMs: 42,
|
||||
evidence: 'Visible terminal tail ' + call + ': ' + process.env.DIAGNOSTIC_API_TOKEN,
|
||||
...(['bad-report', 'missing-decisions'].includes(scenario) ? { planFile: report } : {}),
|
||||
...(scenario === 'bad-report' ? { planFile: report } : {}),
|
||||
proseAUQEverObserved: true, waitingEverObserved: true, tokensObserved: { 'draft-plan': true, 'scope-announcement': false },
|
||||
scopeGateQuestionObserved: scenario === 'scope-question',
|
||||
scopeGateAutoSelectObserved: !['missing-auto-select', 'retry', 'unwritable'].includes(scenario) };
|
||||
@@ -68,14 +68,6 @@ await import(${JSON.stringify(path.join(ROOT, PAID_FILE))});
|
||||
keys.push('initialPlanContent', 'trackTokens');
|
||||
expect(opts.trackTokens.length).toBeGreaterThan(0);
|
||||
for (const token of opts.trackTokens) expect(opts.initialPlanContent).toContain(token);
|
||||
if (skill === 'eng') {
|
||||
keys.push('extraArgs', 'cwd', 'env');
|
||||
expect(opts.extraArgs).toEqual(['--disallowedTools', 'AskUserQuestion']);
|
||||
// The seeded runner plan reviews its own fixture project, never this checkout.
|
||||
expect(path.isAbsolute(opts.cwd)).toBe(true);
|
||||
expect(path.relative(ROOT, opts.cwd).startsWith('..')).toBe(true);
|
||||
expect(opts.env).toEqual({ DISABLE_AUTOUPDATER: '1', CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1' });
|
||||
}
|
||||
}
|
||||
expect(Object.keys(opts).sort()).toEqual(keys.sort());
|
||||
}
|
||||
@@ -113,7 +105,6 @@ await import(${JSON.stringify(path.join(ROOT, PAID_FILE))});
|
||||
if (scenario === 'bad-report') expect(output).toContain('GSTACK REVIEW REPORT contract violation');
|
||||
if (scenario === 'missing-auto-select') expect(output).toContain('scopeGateAutoSelectObserved');
|
||||
if (scenario === 'scope-question') expect(output).toContain('scopeGateQuestionObserved');
|
||||
if (scenario === 'missing-decisions') expect(output).toContain('without a question');
|
||||
} finally { fs.rmSync(dir, { recursive: true, force: true }); }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,15 +2,15 @@ import { expect, test } from 'bun:test';
|
||||
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
|
||||
|
||||
const ptyIds = [
|
||||
'plan-ceo-review-plan-mode', 'plan-eng-review-plan-mode', 'plan-design-review-plan-mode-smoke',
|
||||
'plan-ceo-review-plan-mode', 'plan-design-review-plan-mode-smoke',
|
||||
'plan-devex-review-plan-mode', 'plan-mode-no-op', 'office-hours-auto-mode',
|
||||
'auto-decide-preserved', 'plan-ceo-mode-routing', 'plan-design-with-ui-scope', 'plan-eng-finding-floor',
|
||||
'auto-decide-preserved', 'plan-ceo-mode-routing', 'plan-design-with-ui-scope',
|
||||
// The two formerly keyless AUQ probes (W1b) import the same SDK capture helper as auq-format-gate, which reaches the PTY runner.
|
||||
'auq-format-gate', 'auq-consistency', 'auq-verbose-vs-carved-ab', ...['benchmark', 'browse', 'codex', 'context-restore', 'design-consultation', 'design-html', 'design-shotgun', 'document-release', 'investigate', 'land-and-deploy',
|
||||
'plan-design-review', 'plan-devex-review', 'plan-eng-review', 'qa', 'retro', 'review', 'setup-gbrain', 'spec'].map(skill => `carve-section-loading-${skill}`),
|
||||
'plan-design-review', 'plan-devex-review', 'qa', 'retro', 'review', 'setup-gbrain', 'spec'].map(skill => `carve-section-loading-${skill}`),
|
||||
'office-hours-section-loading', 'office-hours-design-draft', 'plan-ceo-section-loading', 'ship-section-loading',
|
||||
'plan-ceo-finding-floor', 'plan-design-finding-floor', 'plan-devex-finding-floor',
|
||||
'plan-eng-multi-finding-batching', 'plan-ceo-split-overflow', 'plan-eng-review-artifact', 'plan-eng-review-artifact-full',
|
||||
'plan-eng-multi-finding-batching', 'plan-ceo-split-overflow', 'plan-eng-review-artifact',
|
||||
// The /autoplan guard's live cases drive the same PTY runner (Oct 7 wave).
|
||||
'autoplan-guard-pty', 'autoplan-long-session',
|
||||
].sort();
|
||||
|
||||
@@ -70,11 +70,6 @@ interface MatrixSkill {
|
||||
}
|
||||
|
||||
const MATRIX: MatrixSkill[] = [
|
||||
{
|
||||
skill: 'plan-eng-review',
|
||||
fixtures: { 'plan.md': FLAWED_PLAN },
|
||||
scenario: 'Read plan.md — that is the plan to review. It is a standalone plan document, not a codebase. Walk the review until the first AskUserQuestion (a per-issue finding or a scope decision).',
|
||||
},
|
||||
{
|
||||
skill: 'plan-design-review',
|
||||
fixtures: { 'plan.md': FLAWED_PLAN + '\n## UI\nA new pricing page with a comparison table, plan cards, and an upgrade modal.\n' },
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/**
|
||||
* /plan-ceo-review AskUserQuestion floor regression (gate, paid, real-PTY).
|
||||
*
|
||||
* See test/skill-e2e-plan-eng-finding-floor.test.ts for the contract.
|
||||
* Contract: a seeded forcing finding must fire at least one AskUserQuestion
|
||||
* before the review writes its plan or exits plan mode (the /plan-eng-review
|
||||
* floor that first pinned it retired with that skill, GST-1698).
|
||||
*/
|
||||
|
||||
import { test } from 'bun:test';
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/**
|
||||
* /plan-design-review AskUserQuestion floor regression (periodic, paid, real-PTY).
|
||||
*
|
||||
* See test/skill-e2e-plan-eng-finding-floor.test.ts for the contract.
|
||||
* Contract: a seeded forcing finding must fire at least one AskUserQuestion
|
||||
* before the review writes its plan or exits plan mode (the /plan-eng-review
|
||||
* floor that first pinned it retired with that skill, GST-1698).
|
||||
*/
|
||||
|
||||
import { test } from 'bun:test';
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/**
|
||||
* /plan-devex-review AskUserQuestion floor regression (gate, paid, real-PTY).
|
||||
*
|
||||
* See test/skill-e2e-plan-eng-finding-floor.test.ts for the contract.
|
||||
* Contract: a seeded forcing finding must fire at least one AskUserQuestion
|
||||
* before the review writes its plan or exits plan mode (the /plan-eng-review
|
||||
* floor that first pinned it retired with that skill, GST-1698).
|
||||
*/
|
||||
|
||||
import { test } from 'bun:test';
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/**
|
||||
* Marathon: a fresh /plan-eng-review, from startup through Test review, writes
|
||||
* its QA test-plan artifact (paid, real-PTY, non-blocking).
|
||||
*
|
||||
* The periodic checkpoint (skill-e2e-plan-eng-artifact.test.ts) resumes after
|
||||
* Scope Challenge and Sections 1-2; this case keeps the whole interactive path.
|
||||
* Budget: PTY_LONG_MS. Measured on Claude Code 2.1.284: one fresh run passed at
|
||||
* 498 s; census 37174266054 and a local run both spent 595 s on startup plus six
|
||||
* one-at-a-time Scope Challenge questions without reaching Test review.
|
||||
*
|
||||
* Replaces the composing `plan-eng-review-artifact` case in skill-e2e-plan.test.ts.
|
||||
* That case told a `claude -p` session to skip the preamble and questions and
|
||||
* "go straight to the review"; in runs 37151477069, 37158847998 and 37162480720
|
||||
* (and one local CI-image run) the model wrote the whole review into one file
|
||||
* without executing the workflow, so it measured composing, not the skill. A
|
||||
* full interactive run does write the artifact (37158847998's batching PTY run
|
||||
* wrote eng-review-test-plan-20261003-224617.md during Test review).
|
||||
*
|
||||
* This case drives the real interactive /plan-eng-review over the same
|
||||
* dashboard plan and sources, answers each question with its first option, and
|
||||
* stops once the artifact exists or the report completes. The requirement is
|
||||
* unchanged: exactly one new QA test plan under the run's own state root, about
|
||||
* the reviewed dashboard change.
|
||||
*/
|
||||
|
||||
import { expect, test } from 'bun:test';
|
||||
import * as fs from 'node:fs';
|
||||
import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
import { PTY_LONG_MS } from './helpers/eval-budgets';
|
||||
import { DASHBOARD_PLAN, FIXTURE_PLAN_PATH, SOURCES } from './helpers/plan-eng-artifact-fixture';
|
||||
import { describeE2ETier } from './helpers/e2e-gate';
|
||||
import { engFirstReviewAUQ, engSetupAUQ, engStep0Boundary, hasCompletePlanReport, runPlanSkillCounting } from './helpers/claude-pty-runner';
|
||||
|
||||
const describeE2E = describeE2ETier('marathon');
|
||||
|
||||
describeE2E('/plan-eng-review QA test-plan artifact, full workflow (marathon)', () => {
|
||||
test('a fresh interactive review reaches Test review and writes one QA test plan', async () => {
|
||||
const startedAt = Date.now();
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-e2e-plan-eng-artifact-full-'));
|
||||
const planPath = path.join(tmpDir, 'gstack-test-plan-eng-artifact.md');
|
||||
try {
|
||||
const obs = await runPlanSkillCounting({
|
||||
skillName: 'plan-eng-review',
|
||||
slashCommand: '/plan-eng-review',
|
||||
followUpPrompt: DASHBOARD_PLAN.replaceAll(FIXTURE_PLAN_PATH, planPath),
|
||||
fixtureFiles: SOURCES,
|
||||
permissionPlanPath: planPath,
|
||||
isLastStep0AUQ: engStep0Boundary,
|
||||
isSetupAUQ: engSetupAUQ,
|
||||
isFirstReviewAUQ: engFirstReviewAUQ,
|
||||
// The artifact is the only verdict; stop once it exists or the report is complete.
|
||||
isCollectionComplete: (_transcript, _fingerprints, testPlans) =>
|
||||
testPlans.length > 0 || hasCompletePlanReport(planPath, startedAt, Date.now()),
|
||||
reviewCountCeiling: Infinity,
|
||||
preconfiguredReviewActor: true,
|
||||
timeoutMs: PTY_LONG_MS,
|
||||
env: { QUESTION_TUNING: 'false', EXPLAIN_LEVEL: 'default' },
|
||||
});
|
||||
const plans = obs.engTestPlans;
|
||||
console.log(`plan-eng-review-artifact-full: outcome=${obs.outcome} elapsed=${obs.elapsedMs}ms review=${obs.reviewCount} test plans=${plans.map(plan => plan.file).join(', ') || 'none'}`);
|
||||
if (!['plan_ready', 'completion_summary', 'collection_complete'].includes(obs.outcome)) {
|
||||
throw new Error(`plan-eng-review-artifact-full: outcome=${obs.outcome} (${obs.summary})\n--- evidence ---\n${obs.evidence}`);
|
||||
}
|
||||
expect(plans, `expected one new eng-review test plan; outcome=${obs.outcome}`).toHaveLength(1);
|
||||
expect(/dashboard|fetchStats|\/api\/stats/i.test(plans[0]!.content), 'the test plan covers the reviewed dashboard change').toBe(true);
|
||||
} finally {
|
||||
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
}, PTY_LONG_MS + 30_000);
|
||||
});
|
||||
@@ -19,8 +19,8 @@
|
||||
* review, answering each question with its first option, and the case stops
|
||||
* once the artifact exists or the report completes. The requirement is
|
||||
* unchanged: exactly one new QA test plan under the run's own state root, about
|
||||
* the reviewed dashboard change. The fresh start-to-finish path is the marathon
|
||||
* case in skill-e2e-plan-eng-artifact-full.test.ts.
|
||||
* the reviewed dashboard change. (The fresh start-to-finish marathon case
|
||||
* retired with the standalone skill, GST-1698.)
|
||||
*/
|
||||
|
||||
import { expect, test } from 'bun:test';
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* /plan-eng-review AskUserQuestion floor regression (periodic, paid, real-PTY).
|
||||
*
|
||||
* Catches the May 2026 transcript bug where /plan-eng-review wrote a
|
||||
* multi-section review plan to ~/.claude/plans/ and called ExitPlanMode
|
||||
* without firing any AskUserQuestion. See
|
||||
* `.context/attachments/pasted_text_2026-05-06_10-25-23.txt`.
|
||||
*
|
||||
* Uses runPlanSkillFloorCheck — a minimal "did the agent fire ANY AUQ?"
|
||||
* observer that exits early on the first non-permission numbered-option
|
||||
* render. See claude-pty-runner.ts for why this is separate from the
|
||||
* runPlanSkillCounting harness used by periodic finding-count tests.
|
||||
*
|
||||
* Tier: periodic. Budget: 10 min (early exit on success ~30-90s typical).
|
||||
* Cost: ~$0.50-$1.50 per run depending on early-exit timing.
|
||||
*/
|
||||
|
||||
import { test } from 'bun:test';
|
||||
import { CAPTURE_LONG_MS, PTY_MS } from './helpers/eval-budgets';
|
||||
import { describeE2ETier } from './helpers/e2e-gate';
|
||||
import { runPlanSkillFloorCheck } from './helpers/claude-pty-runner';
|
||||
import { FORCING_FLOOR_ENG } from './fixtures/forcing-finding-seeds';
|
||||
|
||||
const describeE2E = describeE2ETier('periodic');
|
||||
|
||||
describeE2E('/plan-eng-review AskUserQuestion floor (periodic)', () => {
|
||||
test(
|
||||
'seeded forcing finding causes the agent to fire at least one AskUserQuestion',
|
||||
async () => {
|
||||
const obs = await runPlanSkillFloorCheck({
|
||||
skillName: 'plan-eng-review',
|
||||
slashCommand: '/plan-eng-review',
|
||||
followUpPrompt: FORCING_FLOOR_ENG,
|
||||
requestedPlanPath: '/tmp/gstack-test-plan-eng-floor.md',
|
||||
// LIVE-REPO CWD: PTY session needs the repo cwd — gstack skill
|
||||
// registry + hermetic pre-trusted dir (hermetic-env trustedDirs).
|
||||
cwd: process.cwd(),
|
||||
timeoutMs: CAPTURE_LONG_MS,
|
||||
env: { QUESTION_TUNING: 'false', EXPLAIN_LEVEL: 'default' },
|
||||
});
|
||||
|
||||
if (obs.outcome !== 'auq_observed') {
|
||||
throw new Error(
|
||||
`floor test FAILED: outcome=${obs.outcome} elapsed=${obs.elapsedMs}ms\n` +
|
||||
`summary: ${obs.summary}\n` +
|
||||
`If outcome is plan_ready or completion_summary, this is the transcript-bug ` +
|
||||
`regression — agent reached terminal without firing AskUserQuestion. See ` +
|
||||
`.context/attachments/pasted_text_2026-05-06_10-25-23.txt.\n` +
|
||||
`If outcome is timeout, agent may just be slow — re-run or increase budget.\n` +
|
||||
`--- evidence (last 3KB) ---\n${obs.evidence}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
PTY_MS,
|
||||
);
|
||||
});
|
||||
@@ -1,183 +0,0 @@
|
||||
/**
|
||||
* plan-eng-review plan-mode smoke (periodic, paid, real-PTY).
|
||||
*
|
||||
* See test/skill-e2e-plan-ceo-plan-mode.test.ts for the shared assertion
|
||||
* contract. This file exercises the same contract against /plan-eng-review.
|
||||
*/
|
||||
|
||||
import { test, expect } from 'bun:test';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import * as fs from 'node:fs';
|
||||
import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
import { CAPTURE_MS, CAPTURE_LONG_MS } from './helpers/eval-budgets';
|
||||
import { describeE2ETier } from './helpers/e2e-gate';
|
||||
import { assertNoPlanFileDecisions, assertPlanModeWithEvidence, seededPlanTargeted } from './helpers/plan-mode-evidence';
|
||||
import {
|
||||
runPlanSkillObservation,
|
||||
planFileHasDecisionsSection,
|
||||
assertReportAtBottomIfPlanWritten,
|
||||
} from './helpers/claude-pty-runner';
|
||||
|
||||
const describeE2E = describeE2ETier('periodic');
|
||||
|
||||
// SEED_PLAN_FORCING_FINDINGS: 8+ files + custom-vs-builtin smell forces the
|
||||
// Step 0 complexity check to trigger. Passed via runPlanSkillObservation's
|
||||
// initialPlanContent (D3-B) so the spawned `claude` actually sees it.
|
||||
const SEED_PLAN_FORCING_FINDINGS = `
|
||||
# Parallelize unit tests
|
||||
|
||||
## Plan
|
||||
Build a custom test runner: scripts/test-parallel.ts, scripts/test-shard-impl.ts,
|
||||
scripts/test-merge-results.ts, scripts/test-progress.ts, scripts/test-watch.ts,
|
||||
scripts/test-coverage.ts, scripts/test-cli.ts, scripts/test-config.ts.
|
||||
|
||||
Add new TestRunner class, new ShardManager class, new ResultMerger class.
|
||||
|
||||
Ignore Bun's native --shard flag because we want full control.
|
||||
|
||||
## Files
|
||||
- scripts/test-parallel.ts (new)
|
||||
- scripts/test-shard-impl.ts (new)
|
||||
- scripts/test-merge-results.ts (new)
|
||||
- scripts/test-progress.ts (new)
|
||||
- scripts/test-watch.ts (new)
|
||||
- scripts/test-coverage.ts (new)
|
||||
- scripts/test-cli.ts (new)
|
||||
- scripts/test-config.ts (new)
|
||||
- package.json (add scripts)
|
||||
|
||||
## Tests
|
||||
None planned — will add later.
|
||||
`;
|
||||
|
||||
/**
|
||||
* The seeded plan proposes a custom test runner, so its Step 0 "what already
|
||||
* exists" pass reads the working tree's test setup. Run it in a small project
|
||||
* of its own, never the gstack checkout: there the agent explored gstack's own
|
||||
* sharded runner, and the review's length tracked unrelated runner edits
|
||||
* (a 300 s timeout in census 37228573062 after a runner refactor).
|
||||
*/
|
||||
function createRunnerPlanFixture(): { cwd: string; cleanup(): void } {
|
||||
const cwd = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-plan-eng-smoke-')));
|
||||
const cleanup = () => fs.rmSync(cwd, { recursive: true, force: true });
|
||||
const files: Record<string, string> = {
|
||||
'package.json': JSON.stringify({ name: 'tiny-math', private: true, type: 'module', scripts: { test: 'bun test' } }, null, 2) + '\n',
|
||||
'README.md': '# tiny-math\n\nA small Bun library. `bun test` runs the unit tests in test/.\n',
|
||||
'src/sum.ts': 'export function sum(values: number[]): number {\n return values.reduce((total, value) => total + value, 0);\n}\n',
|
||||
'test/sum.test.ts': "import { expect, test } from 'bun:test';\nimport { sum } from '../src/sum';\n\ntest('sums values', () => {\n expect(sum([1, 2, 3])).toBe(6);\n});\n",
|
||||
};
|
||||
try {
|
||||
for (const [name, content] of Object.entries(files)) {
|
||||
fs.mkdirSync(path.dirname(path.join(cwd, name)), { recursive: true });
|
||||
fs.writeFileSync(path.join(cwd, name), content);
|
||||
}
|
||||
for (const args of [
|
||||
['init', '-b', 'main'],
|
||||
['add', '--', ...Object.keys(files)],
|
||||
['-c', 'user.name=Plan Eng Fixture', '-c', 'user.email=plan-eng@example.test', '-c', 'commit.gpgsign=false',
|
||||
'commit', '--no-verify', '-m', 'Seed tiny-math'],
|
||||
['update-ref', 'refs/remotes/origin/main', 'HEAD'],
|
||||
]) {
|
||||
const result = spawnSync('git', args, { cwd, encoding: 'utf8', timeout: 10_000 });
|
||||
if (result.error || result.status !== 0) throw new Error(`Could not initialize the plan-eng fixture: ${result.error?.message ?? result.stderr}`);
|
||||
}
|
||||
return { cwd, cleanup };
|
||||
} catch (error) {
|
||||
cleanup();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Seed-only names; seeing one after the slash command shows the review read the seeded plan.
|
||||
const SEED_PLAN_TOKENS = ['ShardManager', 'ResultMerger', 'test-shard-impl'];
|
||||
|
||||
describeE2E('plan-eng-review plan-mode smoke (periodic)', () => {
|
||||
test('reaches a terminal outcome (asked or plan_ready) without silent writes', async () => {
|
||||
const obs = await runPlanSkillObservation({
|
||||
skillName: 'plan-eng-review',
|
||||
inPlanMode: true,
|
||||
timeoutMs: CAPTURE_MS,
|
||||
});
|
||||
|
||||
assertPlanModeWithEvidence('plan-eng-review', 'reaches a terminal outcome (asked or plan_ready) without silent writes', obs, () => {
|
||||
if (obs.outcome === 'silent_write' || obs.outcome === 'exited' || obs.outcome === 'timeout') {
|
||||
throw new Error(
|
||||
`plan-eng-review plan-mode smoke FAILED: outcome=${obs.outcome}\n` +
|
||||
`summary: ${obs.summary}\n` +
|
||||
`elapsed: ${obs.elapsedMs}ms\n` +
|
||||
`--- evidence (last 2KB visible) ---\n${obs.evidence}`,
|
||||
);
|
||||
}
|
||||
expect(['asked', 'plan_ready']).toContain(obs.outcome);
|
||||
assertReportAtBottomIfPlanWritten(obs);
|
||||
assertNoPlanFileDecisions(obs, planFileHasDecisionsSection);
|
||||
});
|
||||
}, CAPTURE_LONG_MS);
|
||||
|
||||
// D3-B / D4-B: when a plan with guaranteed-finding-triggering complexity
|
||||
// is seeded, the skill must ask (mcp AskUserQuestion or the prose fallback)
|
||||
// before writing findings to the plan. The wrote_findings_before_asking
|
||||
// outcome catches the transcript bug where the model writes findings to the
|
||||
// plan before any question renders. A plan-file ## Decisions section is not
|
||||
// a substitute for asking.
|
||||
test('STOP gate fires when seeded plan forces Step 0 findings', async () => {
|
||||
const fixture = createRunnerPlanFixture();
|
||||
let obs: Awaited<ReturnType<typeof runPlanSkillObservation>>;
|
||||
try {
|
||||
obs = await runPlanSkillObservation({
|
||||
skillName: 'plan-eng-review',
|
||||
inPlanMode: true,
|
||||
cwd: fixture.cwd,
|
||||
// As in auto-decide-preserved's standalone fixture: a first launch in a
|
||||
// fresh folder can paint a product notice under the composer, which
|
||||
// the plan-seed composer check (one footer row) never accepts.
|
||||
env: { DISABLE_AUTOUPDATER: '1', CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1' },
|
||||
initialPlanContent: SEED_PLAN_FORCING_FINDINGS,
|
||||
// Force the Conductor-style path: native AUQ disallowed → the model
|
||||
// must use mcp__*__AskUserQuestion or render the prose fallback
|
||||
// (both observed as outcome='asked').
|
||||
extraArgs: ['--disallowedTools', 'AskUserQuestion'],
|
||||
trackTokens: SEED_PLAN_TOKENS,
|
||||
timeoutMs: CAPTURE_MS,
|
||||
});
|
||||
} finally {
|
||||
fixture.cleanup();
|
||||
}
|
||||
|
||||
assertPlanModeWithEvidence('plan-eng-review', 'STOP gate fires when seeded plan forces Step 0 findings', obs, () => {
|
||||
if (
|
||||
obs.outcome === 'wrote_findings_before_asking' ||
|
||||
obs.outcome === 'auto_decided' ||
|
||||
obs.outcome === 'silent_write' ||
|
||||
obs.outcome === 'exited' ||
|
||||
obs.outcome === 'timeout'
|
||||
) {
|
||||
throw new Error(
|
||||
`STOP-gate regression: outcome=${obs.outcome}\nsummary: ${obs.summary}\n` +
|
||||
`elapsed: ${obs.elapsedMs}ms\n` +
|
||||
`--- evidence (last 2KB) ---\n${obs.evidence}`,
|
||||
);
|
||||
}
|
||||
|
||||
assertReportAtBottomIfPlanWritten(obs);
|
||||
assertNoPlanFileDecisions(obs, planFileHasDecisionsSection);
|
||||
if (obs.outcome !== 'asked') {
|
||||
throw new Error(
|
||||
`STOP-gate regression: outcome=${obs.outcome} — the seeded findings reached ` +
|
||||
`${obs.planFile ?? 'plan_ready'} without a question.\n` +
|
||||
`--- evidence (last 2KB) ---\n${obs.evidence}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Plan-mode scope-gate bypass: with a seeded plan in plan mode, the gate
|
||||
// must NOT render its "What should I review?" menu, and the review must
|
||||
// target the seeded plan. The announcement's exact wording is not graded.
|
||||
// Unseeded test 1 keeps its lenient contract: with no plan drafted, the
|
||||
// "ask as normal" fallback legitimately renders the question.
|
||||
expect(obs.scopeGateQuestionObserved ?? false).toBe(false);
|
||||
console.log(`[plan-eng plan-mode] scope announcement observed: ${obs.scopeGateAutoSelectObserved ?? false}; seed tokens: ${JSON.stringify(obs.tokensObserved ?? {})}`);
|
||||
expect(seededPlanTargeted(obs, SEED_PLAN_TOKENS), 'seeded plan was not targeted (scopeGateAutoSelectObserved or seed-only plan tokens)').toBe(true);
|
||||
});
|
||||
}, CAPTURE_LONG_MS);
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
/**
|
||||
* AskUserQuestion format regression test for /plan-ceo-review and /plan-eng-review.
|
||||
* AskUserQuestion format regression test for /plan-ceo-review (the /plan-eng-review
|
||||
* cases retired with that skill, GST-1698).
|
||||
*
|
||||
* Context: a user on Opus 4.7 reported the RECOMMENDATION line and the
|
||||
* `Completeness: N/10` per-option score stopped appearing on AskUserQuestion
|
||||
@@ -82,7 +83,7 @@ We're building a new user dashboard that shows recent activity, notifications, a
|
||||
- Cache: Redis for dashboard aggregates
|
||||
`;
|
||||
|
||||
function setupPlanDir(tmpPrefix: string, skillName: 'plan-ceo-review' | 'plan-eng-review'): string {
|
||||
function setupPlanDir(tmpPrefix: string, skillName: 'plan-ceo-review'): string {
|
||||
const planDir = fs.mkdtempSync(path.join(os.tmpdir(), tmpPrefix));
|
||||
const run = (cmd: string, args: string[]) =>
|
||||
spawnSync(cmd, args, { cwd: planDir, stdio: 'pipe', timeout: 5000 });
|
||||
@@ -107,12 +108,6 @@ function setupPlanDir(tmpPrefix: string, skillName: 'plan-ceo-review' | 'plan-en
|
||||
return planDir;
|
||||
}
|
||||
|
||||
// The capture instruction passed to every case except the mode and approach menus (D2).
|
||||
// Tells the agent to dump AskUserQuestion content to a file instead of calling a tool.
|
||||
function captureInstruction(outFile: string): string {
|
||||
return `Write the verbatim text of every AskUserQuestion you would have made to ${outFile} (one question per session, full text including options and recommendation line). Do NOT call any tool to ask the user. Do NOT paraphrase — include the exact prose you would have shown. This is a format-capture test, not an interactive session.`;
|
||||
}
|
||||
|
||||
/**
|
||||
* D2: both approach-menu refusals in census 37195203538 (Fable 5.1,
|
||||
* `reasoning_extraction`, "duplicating model outputs") were anchored on the
|
||||
@@ -259,143 +254,6 @@ After writing the file, stop. Do not continue the review.`,
|
||||
}, CAPTURE_MS + OFFICE_HOURS_BUN_GRACE_MS);
|
||||
});
|
||||
|
||||
// --- Case 3: plan-eng-review coverage-differentiated per-issue AskUserQuestion ---
|
||||
|
||||
describeIfSelected('Plan Format — Eng Coverage Issue', ['plan-eng-review-format-coverage'], () => {
|
||||
let planDir: string;
|
||||
let outFile: string;
|
||||
|
||||
beforeAll(() => {
|
||||
planDir = setupPlanDir('skill-e2e-plan-format-eng-cov-', 'plan-eng-review');
|
||||
outFile = path.join(planDir, 'ask-capture.md');
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
try { fs.rmSync(planDir, { recursive: true, force: true }); } catch {}
|
||||
});
|
||||
|
||||
testConcurrentIfSelected('plan-eng-review-format-coverage', async () => {
|
||||
const judgeMetadata: Pick<EvalTestEntry, 'judge_scores' | 'judge_reasoning'> = {};
|
||||
await runRecordedOfficeHoursAttempt({
|
||||
collector: evalCollector, name: '/plan-eng-review-format-coverage', suite: 'Plan Format — Eng Coverage Issue',
|
||||
model: resolveEvalModel('capture'), budgetMs: CAPTURE_MS,
|
||||
judgeMetadata,
|
||||
run: signal => runSkillTest({
|
||||
signal,
|
||||
prompt: `Read plan-eng-review/SKILL.md for the review workflow.
|
||||
|
||||
Read plan.md — that's the plan to review. This is a standalone plan document, not a codebase — skip any codebase exploration steps.
|
||||
|
||||
During your review (Section 3 Test Review is the natural place), generate ONE AskUserQuestion about test coverage depth where the options are clearly coverage-differentiated. For example:
|
||||
A) Full coverage: happy path + edge cases + error paths (Completeness 10/10)
|
||||
B) Happy path only (Completeness 7/10)
|
||||
C) Smoke test (Completeness 3/10)
|
||||
|
||||
${captureInstruction(outFile)}
|
||||
|
||||
After writing the file with that ONE question, stop. Do not continue the review.`,
|
||||
workingDirectory: planDir,
|
||||
maxTurns: 10,
|
||||
timeout: CAPTURE_MS,
|
||||
testName: 'plan-eng-review-format-coverage',
|
||||
runId,
|
||||
model: resolveEvalModel('capture'),
|
||||
}),
|
||||
validate: async (result, signal) => {
|
||||
logCost('/plan-eng-review format (coverage)', result);
|
||||
expect(['success', 'error_max_turns']).toContain(result.exitReason);
|
||||
|
||||
expect(fs.existsSync(outFile)).toBe(true);
|
||||
const captured = fs.readFileSync(outFile, 'utf-8');
|
||||
expect(captured.length).toBeGreaterThan(100);
|
||||
|
||||
// Coverage-differentiated: Completeness: N/10 required. Recommendation
|
||||
// presence checked by the judge.
|
||||
expect(captured).toMatch(COMPLETENESS_RE);
|
||||
|
||||
await assertRecommendationQuality({
|
||||
captured,
|
||||
signal,
|
||||
record: metadata => Object.assign(judgeMetadata, metadata),
|
||||
evalCollector,
|
||||
evalId: '/plan-eng-review-format-coverage',
|
||||
evalTitle: 'Plan Format — Eng Coverage Issue',
|
||||
result,
|
||||
passed: ['success', 'error_max_turns'].includes(result.exitReason),
|
||||
});
|
||||
},
|
||||
});
|
||||
}, CAPTURE_MS + OFFICE_HOURS_BUN_GRACE_MS);
|
||||
});
|
||||
|
||||
// --- Case 4: plan-eng-review kind-differentiated per-issue AskUserQuestion ---
|
||||
|
||||
describeIfSelected('Plan Format — Eng Kind Issue', ['plan-eng-review-format-kind'], () => {
|
||||
let planDir: string;
|
||||
let outFile: string;
|
||||
|
||||
beforeAll(() => {
|
||||
planDir = setupPlanDir('skill-e2e-plan-format-eng-kind-', 'plan-eng-review');
|
||||
outFile = path.join(planDir, 'ask-capture.md');
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
try { fs.rmSync(planDir, { recursive: true, force: true }); } catch {}
|
||||
});
|
||||
|
||||
testConcurrentIfSelected('plan-eng-review-format-kind', async () => {
|
||||
const judgeMetadata: Pick<EvalTestEntry, 'judge_scores' | 'judge_reasoning'> = {};
|
||||
await runRecordedOfficeHoursAttempt({
|
||||
collector: evalCollector, name: '/plan-eng-review-format-kind', suite: 'Plan Format — Eng Kind Issue',
|
||||
model: resolveEvalModel('capture'), budgetMs: CAPTURE_MS,
|
||||
judgeMetadata,
|
||||
run: signal => runSkillTest({
|
||||
signal,
|
||||
prompt: `Read plan-eng-review/SKILL.md for the review workflow.
|
||||
|
||||
Read plan.md — that's the plan to review. This is a standalone plan document, not a codebase — skip any codebase exploration steps.
|
||||
|
||||
During your review (Section 1 Architecture), generate ONE AskUserQuestion about an architectural choice where the options differ in kind, not in coverage. For example, "should we use Redis or Postgres for the cache layer?" — the options are different kinds of systems with different tradeoffs, not more-or-less-complete versions of the same thing.
|
||||
|
||||
${captureInstruction(outFile)}
|
||||
|
||||
After writing the file with that ONE question, stop. Do not continue the review.`,
|
||||
workingDirectory: planDir,
|
||||
maxTurns: 10,
|
||||
timeout: CAPTURE_MS,
|
||||
testName: 'plan-eng-review-format-kind',
|
||||
runId,
|
||||
model: resolveEvalModel('capture'),
|
||||
}),
|
||||
validate: async (result, signal) => {
|
||||
logCost('/plan-eng-review format (kind)', result);
|
||||
expect(['success', 'error_max_turns']).toContain(result.exitReason);
|
||||
|
||||
expect(fs.existsSync(outFile)).toBe(true);
|
||||
const captured = fs.readFileSync(outFile, 'utf-8');
|
||||
expect(captured.length).toBeGreaterThan(100);
|
||||
|
||||
// Kind-differentiated: Completeness: N/10 must NOT appear, and the brief
|
||||
// says the options are not comparable on coverage (any wording).
|
||||
// Recommendation presence checked by the judge.
|
||||
expect(captured).not.toMatch(COMPLETENESS_RE);
|
||||
expect(captured).toMatch(KIND_NOTE_RE);
|
||||
|
||||
await assertRecommendationQuality({
|
||||
captured,
|
||||
signal,
|
||||
record: metadata => Object.assign(judgeMetadata, metadata),
|
||||
evalCollector,
|
||||
evalId: '/plan-eng-review-format-kind',
|
||||
evalTitle: 'Plan Format — Eng Kind Issue',
|
||||
result,
|
||||
passed: ['success', 'error_max_turns'].includes(result.exitReason),
|
||||
});
|
||||
},
|
||||
});
|
||||
}, CAPTURE_MS + OFFICE_HOURS_BUN_GRACE_MS);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await finalizeEvalCollector(evalCollector);
|
||||
});
|
||||
@@ -16,11 +16,12 @@
|
||||
*
|
||||
* Coverage grew with the scope-gate bypass (plan-mode auto-select B):
|
||||
* - plan-ceo-review: original preamble-misfire regression.
|
||||
* - plan-eng-review / plan-design-review: the bypass must NOT fire outside
|
||||
* - plan-design-review: the bypass must NOT fire outside
|
||||
* plan mode (scopeGateAutoSelectObserved stays false), and when the run
|
||||
* ends in 'asked', the question that fired must be the scope gate itself
|
||||
* (outside plan mode with no named target, the gate is the FIRST
|
||||
* question by contract).
|
||||
* question by contract). (plan-eng-review had the same two checks; they
|
||||
* retired with that skill, GST-1698.)
|
||||
* - plan-devex-review: no no-target scope gate, so only the terminal
|
||||
* outcome and the absent plan-mode reminder are asserted. It reviews a
|
||||
* pasted developer-facing plan: without one it reviews the checkout's
|
||||
@@ -90,14 +91,14 @@ script against the task tracker. Prints to stdout; --out writes a file.
|
||||
`;
|
||||
|
||||
describeE2E('plan-mode-info no-op outside plan mode (gate regression)', () => {
|
||||
for (const skillName of ['plan-ceo-review', 'plan-eng-review', 'plan-design-review', 'plan-devex-review'] as const) {
|
||||
const hasScopeGate = skillName === 'plan-eng-review' || skillName === 'plan-design-review';
|
||||
for (const skillName of ['plan-ceo-review', 'plan-design-review', 'plan-devex-review'] as const) {
|
||||
const hasScopeGate = skillName === 'plan-design-review';
|
||||
test(`${skillName} reaches a terminal outcome outside plan mode`, async () => {
|
||||
const obs = await runPlanSkillObservation({
|
||||
skillName,
|
||||
inPlanMode: false,
|
||||
timeoutMs: CAPTURE_MS,
|
||||
// eng/design: force the prose-fallback path. The unconditional
|
||||
// design: force the prose-fallback path. The unconditional
|
||||
// gate-must-ask assert below pins the render shape the detector
|
||||
// anchors on, and only the --disallowedTools prose fallback makes
|
||||
// that shape CONTRACTUAL ("use exactly this shape" in the template);
|
||||
@@ -164,7 +165,7 @@ describeE2E('plan-mode-info no-op outside plan mode (gate regression)', () => {
|
||||
// review output), proving the target was used rather than the question
|
||||
// merely skipped. Also the over-trigger guard for the tightened
|
||||
// "explicit-only" exception wording.
|
||||
for (const skillName of ['plan-eng-review', 'plan-design-review'] as const) {
|
||||
for (const skillName of ['plan-design-review'] as const) {
|
||||
test(`${skillName} skips the scope gate for an explicitly-pasted target`, async () => {
|
||||
const obs = await runPlanSkillObservation({
|
||||
skillName,
|
||||
|
||||
@@ -147,8 +147,7 @@ describe('selectTests', () => {
|
||||
const actual = selectTests(['scripts/resolvers/testing.ts'], E2E_TOUCHFILES);
|
||||
expect(actual.reason).toBe('diff');
|
||||
expect(actual.selected.sort()).toEqual(expected);
|
||||
for (const id of ['plan-eng-multi-finding-batching',
|
||||
'plan-eng-review-format-coverage', 'ship-section-loading']) {
|
||||
for (const id of ['plan-eng-multi-finding-batching', 'ship-section-loading']) {
|
||||
expect(actual.selected).toContain(id);
|
||||
expect(E2E_TIERS[id]).toBe('periodic');
|
||||
}
|
||||
@@ -633,7 +632,10 @@ describe('derived touchfile closure', () => {
|
||||
};
|
||||
const maps = [['E2E_TOUCHFILES', E2E_TOUCHFILES], ['LLM_JUDGE_TOUCHFILES', LLM_JUDGE_TOUCHFILES]] as const;
|
||||
/** Paid files no key selects; they run only by tier or census. */
|
||||
const KEYLESS_PAID: Record<string, string> = {};
|
||||
const KEYLESS_PAID: Record<string, string> = {
|
||||
// Template-literal ids (auq-matrix-${skill}) and no E2E map key; it runs on every periodic sweep. It only looked keyed while its plan-eng-review row quoted that SDK key (row retired with the skill, GST-1698).
|
||||
'test/skill-e2e-auq-matrix.test.ts': 'periodic self-gated matrix with template-literal ids',
|
||||
};
|
||||
|
||||
test('no free test file is a touchfile', () => {
|
||||
const listed = maps.flatMap(([name, map]) => Object.entries(map).flatMap(([key, deps]) =>
|
||||
|
||||
Reference in new issue
Block a user