@webpresso/agent-kit 3.1.28 → 3.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/catalog/AGENTS.md.tpl +4 -4
- package/catalog/agent/rules/ci-cost-local-first.md +139 -0
- package/catalog/agent/rules/ci-test-perf.md +5 -1
- package/catalog/agent/rules/cmd-execution.md +9 -0
- package/catalog/agent/rules/pre-implementation.md +2 -1
- package/catalog/agent/rules/test-scan-perf.md +80 -0
- package/catalog/agent/rules/workflow-skills-routing.md +4 -2
- package/catalog/agent/skills/fix/SKILL.md +3 -0
- package/catalog/agent/skills/verify/SKILL.md +18 -0
- package/dist/esm/audit/blueprint-pr-coverage.js +68 -7
- package/dist/esm/audit/registry.d.ts +4 -4
- package/dist/esm/audit/registry.js +3 -0
- package/dist/esm/audit/roadmap-links.js +6 -0
- package/dist/esm/audit/test-scan-perf.d.ts +18 -0
- package/dist/esm/audit/test-scan-perf.js +275 -0
- package/dist/esm/blueprint/lifecycle/engine.d.ts +9 -0
- package/dist/esm/blueprint/lifecycle/engine.js +53 -6
- package/dist/esm/blueprint/lifecycle/review-provenance.d.ts +6 -0
- package/dist/esm/blueprint/lifecycle/review-provenance.js +93 -12
- package/dist/esm/blueprint/markdown/helpers.js +6 -2
- package/dist/esm/ci/act-replay.js +110 -7
- package/dist/esm/ci/act-runner.d.ts +4 -0
- package/dist/esm/ci/act-runner.js +85 -26
- package/dist/esm/ci/act-worktree-git.d.ts +11 -0
- package/dist/esm/ci/act-worktree-git.js +219 -0
- package/dist/esm/cli/commands/audit.js +3 -0
- package/dist/esm/cli/commands/blueprint/mutations.js +35 -18
- package/dist/esm/cli/commands/blueprint/router.js +27 -2
- package/dist/esm/cli/commands/ci.d.ts +8 -1
- package/dist/esm/cli/commands/ci.js +80 -21
- package/dist/esm/cli/commands/dash/keymap.js +1 -0
- package/dist/esm/cli/commands/dash/launch-preferences.d.ts +15 -0
- package/dist/esm/cli/commands/dash/launch-preferences.js +46 -17
- package/dist/esm/cli/commands/dash/plan-once-label.d.ts +7 -0
- package/dist/esm/cli/commands/dash/plan-once-label.js +5 -0
- package/dist/esm/cli/commands/dash/plan-once-membership.d.ts +67 -0
- package/dist/esm/cli/commands/dash/plan-once-membership.js +151 -0
- package/dist/esm/cli/commands/dash/plan-once-merge.d.ts +143 -0
- package/dist/esm/cli/commands/dash/plan-once-merge.js +238 -0
- package/dist/esm/cli/commands/dash/plan-once.d.ts +22 -2
- package/dist/esm/cli/commands/dash/plan-once.js +41 -4
- package/dist/esm/cli/commands/dash/tui/attention-hud.d.ts +9 -0
- package/dist/esm/cli/commands/dash/tui/attention-hud.js +9 -0
- package/dist/esm/cli/commands/dash/tui/chat-bridge.d.ts +41 -0
- package/dist/esm/cli/commands/dash/tui/chat-bridge.js +73 -0
- package/dist/esm/cli/commands/dash/tui/chat-mode.d.ts +47 -0
- package/dist/esm/cli/commands/dash/tui/chat-mode.js +98 -0
- package/dist/esm/cli/commands/dash/tui/frame.d.ts +3 -0
- package/dist/esm/cli/commands/dash/tui/frame.js +3 -1
- package/dist/esm/cli/commands/dash/tui/palette.d.ts +1 -1
- package/dist/esm/cli/commands/dash/tui/palette.js +14 -0
- package/dist/esm/cli/commands/dash/tui/runtime.js +239 -4
- package/dist/esm/cli/commands/dash/tui/state.d.ts +41 -0
- package/dist/esm/cli/commands/dash/tui/state.js +257 -4
- package/dist/esm/cli/commands/format.js +0 -2
- package/dist/esm/cli/commands/init/config.d.ts +0 -1
- package/dist/esm/cli/commands/init/config.js +1 -4
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.d.ts +5 -6
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.js +6 -13
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.d.ts +0 -2
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.js +0 -2
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.d.ts +6 -3
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.js +39 -26
- package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.js +61 -23
- package/dist/esm/cli/commands/logs.d.ts +15 -0
- package/dist/esm/cli/commands/logs.js +192 -3
- package/dist/esm/cli/commands/quality-log-store.d.ts +1 -0
- package/dist/esm/cli/commands/quality-log-store.js +187 -51
- package/dist/esm/cli/commands/review.js +5 -8
- package/dist/esm/cli/commands/secrets.d.ts +1 -0
- package/dist/esm/cli/commands/secrets.js +4 -1
- package/dist/esm/cli/direct-provider-launch.js +25 -1
- package/dist/esm/hooks/doctor.d.ts +15 -0
- package/dist/esm/hooks/doctor.js +56 -0
- package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +4 -4
- package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.d.ts +0 -1
- package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.js +8 -5
- package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.d.ts +9 -7
- package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.js +126 -14
- package/dist/esm/mcp/tools/_shared/audit-kinds.d.ts +1 -1
- package/dist/esm/mcp/tools/audit.d.ts +2 -1
- package/dist/esm/mcp/tools/audit.js +10 -0
- package/dist/esm/mcp/tools/audits.d.ts +1 -0
- package/dist/esm/mcp/tools/ci-act.js +9 -11
- package/dist/esm/paths/state-root.js +3 -0
- package/dist/esm/review/authority.js +17 -2
- package/dist/esm/review/availability.js +18 -5
- package/dist/esm/review/subject.d.ts +15 -0
- package/dist/esm/review/subject.js +105 -10
- package/dist/esm/runtime/executor.d.ts +1 -0
- package/dist/esm/runtime/executor.js +2 -1
- package/dist/esm/secret-gate/runner.d.ts +1 -0
- package/dist/esm/secret-gate/runner.js +4 -1
- package/dist/esm/worktrees/current.d.ts +1 -0
- package/dist/esm/worktrees/current.js +1 -0
- package/dist/esm/worktrees/project-agent-surfaces.d.ts +1 -0
- package/dist/esm/worktrees/project-agent-surfaces.js +2 -1
- package/package.json +14 -14
package/catalog/AGENTS.md.tpl
CHANGED
|
@@ -63,10 +63,10 @@ asynchronously.
|
|
|
63
63
|
|
|
64
64
|
## Verify
|
|
65
65
|
|
|
66
|
-
Before claiming completion, run the narrowest checks that prove the
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
Before claiming completion, run the narrowest MCP/`wp` checks that prove the
|
|
67
|
+
change: typecheck, lint/format, affected tests, policy, docs/blueprint, and
|
|
68
|
+
`wp sync --check` after template/catalog changes. Fix root cause or record the
|
|
69
|
+
blocker. Before pushing, run `wp ci-preflight` (see `ci-cost-local-first`).
|
|
70
70
|
|
|
71
71
|
## Communicate
|
|
72
72
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: rule
|
|
3
|
+
slug: ci-cost-local-first
|
|
4
|
+
title: CI cost and local-first gates
|
|
5
|
+
status: active
|
|
6
|
+
scope: repo
|
|
7
|
+
applies_to: [agents]
|
|
8
|
+
related:
|
|
9
|
+
- cmd-execution
|
|
10
|
+
- ci-test-perf
|
|
11
|
+
- pre-implementation
|
|
12
|
+
- hook-hot-path
|
|
13
|
+
- no-timeout-as-fix
|
|
14
|
+
created: "2026-07-21"
|
|
15
|
+
last_reviewed: "2026-07-21"
|
|
16
|
+
paths:
|
|
17
|
+
- ".github/workflows/**"
|
|
18
|
+
- "catalog/agent/**"
|
|
19
|
+
- "AGENTS.md"
|
|
20
|
+
- ".husky/**"
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# CI cost and local-first gates
|
|
24
|
+
|
|
25
|
+
Agents waste money when they treat remote CI as the primary debugger.
|
|
26
|
+
**Catch failures locally first.** Remote CI is confirmation, not exploration.
|
|
27
|
+
|
|
28
|
+
Monthly spend on private repos (Ubicloud + GitHub-hosted minutes + artifact
|
|
29
|
+
storage) is a product constraint. Prefer cheap local loops over burning full
|
|
30
|
+
PR matrices to discover format/lint/type/test/governance failures.
|
|
31
|
+
|
|
32
|
+
## Iron law
|
|
33
|
+
|
|
34
|
+
1. **Never open or update a PR you already know will fail** a locally-runnable
|
|
35
|
+
gate (format, guardrails, typecheck, lint, affected tests, PR body contract,
|
|
36
|
+
changeset/blueprint trailers when applicable).
|
|
37
|
+
2. **Never use `git push --no-verify` / `HUSKY=0` / skip hooks** to “save
|
|
38
|
+
time.” That only moves the failure to paid CI and trains a red-loop habit.
|
|
39
|
+
3. **Never re-run a failed CI job “to see if it flaked”** until you have a
|
|
40
|
+
local reproduction or a concrete flake hypothesis with evidence.
|
|
41
|
+
4. **Never add GitHub-hosted runners** (`ubuntu-latest`, `macos-*`,
|
|
42
|
+
`windows-*`) on private-repo workflows except the **Release / npm OIDC
|
|
43
|
+
publish** path (and release-native targets that truly need that OS). Default
|
|
44
|
+
is **Ubicloud** (`ubicloud-standard-2` / `-4` only when justified).
|
|
45
|
+
|
|
46
|
+
## Local gate stack (must pass before push)
|
|
47
|
+
|
|
48
|
+
| When | Command / check |
|
|
49
|
+
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| Every commit | Managed pre-commit (format + staged guardrails) |
|
|
51
|
+
| Every push | `wp ci-preflight` before pushing; in agent-kit itself this is also enforced by `.husky/pre-push` |
|
|
52
|
+
| Before PR open / body edit | PR template fields filled; trailers exact (`Blueprint-exempt`, `Changeset-exempt`, `Review-skip` as **start-of-line** when used) |
|
|
53
|
+
| Before claim merge-ready | `/verify <target>` then `/verify <target> --merge-ready` when landing |
|
|
54
|
+
|
|
55
|
+
`wp ci-preflight` is fail-fast and **branch-scoped**:
|
|
56
|
+
|
|
57
|
+
1. `wp format --affected --branch --check`
|
|
58
|
+
2. `wp audit guardrails --affected --branch`
|
|
59
|
+
3. `wp typecheck --affected --branch`
|
|
60
|
+
4. `wp lint --affected --branch`
|
|
61
|
+
5. `wp test --affected --branch`
|
|
62
|
+
|
|
63
|
+
If preflight fails: **fix locally**, do not push. Reproduce with the printed
|
|
64
|
+
`wp …` line.
|
|
65
|
+
|
|
66
|
+
### Bootstrap before preflight
|
|
67
|
+
|
|
68
|
+
Missing `node_modules` in a worktree → run `wp install` (or the repo’s setup),
|
|
69
|
+
then preflight. Use `vp install` only when `wp` has no equivalent. Do not push a
|
|
70
|
+
bare worktree “to let CI install.”
|
|
71
|
+
|
|
72
|
+
## Cost model (private repos)
|
|
73
|
+
|
|
74
|
+
| Resource | Cost driver | Agent duty |
|
|
75
|
+
| ------------------------------ | ------------------------------------------------- | ---------------------------------------------- |
|
|
76
|
+
| Ubicloud minutes | Every PR job matrix (lint, tests, smokes, shards) | Local preflight; avoid drive-by full re-runs |
|
|
77
|
+
| GitHub-hosted `ubuntu-latest` | Billable Actions minutes | Only release/OIDC publish unless proven needed |
|
|
78
|
+
| GitHub `macos-*` / `windows-*` | ~10× Linux minutes | Release natives only; never default PR CI |
|
|
79
|
+
| Actions artifacts / caches | Storage quota; can block Release uploads | Prefer short retention; do not spam artifacts |
|
|
80
|
+
| Failed CI loops | Full matrix × attempts | Fix from logs locally before `gh run rerun` |
|
|
81
|
+
|
|
82
|
+
Related: `ci-test-perf.md` (keep coverage; speed via workers/cache/shards — not
|
|
83
|
+
by skipping tests). Prefer **fewer/cheaper runners + sharding** over raising
|
|
84
|
+
timeouts (`no-timeout-as-fix.md`).
|
|
85
|
+
|
|
86
|
+
## Workflow authoring (when you touch CI)
|
|
87
|
+
|
|
88
|
+
- Private non-release jobs: `runs-on: ubicloud-standard-2` by default.
|
|
89
|
+
- Use `ubicloud-standard-4` only when wall-time evidence shows standard-2 is
|
|
90
|
+
insufficient **with** full coverage and workers (document why).
|
|
91
|
+
- Release publish job may use `ubuntu-latest` for npm trusted publishing /
|
|
92
|
+
provenance. Session-memory / platform native matrices that require Darwin or
|
|
93
|
+
Windows may use GH-hosted OS runners **only on the Release (publish=true)
|
|
94
|
+
path**, never on ordinary PR CI.
|
|
95
|
+
- Path filters, `concurrency` cancel-in-progress, and change-scope skips are
|
|
96
|
+
preferred over always-on heavy jobs.
|
|
97
|
+
- Do not add nightly/macOS “perf” jobs that run on every PR; keep them opt-in
|
|
98
|
+
(`workflow_dispatch`, label, or schedule) and prefer Ubicloud for any check
|
|
99
|
+
that is not Apple-signing/display-bound.
|
|
100
|
+
|
|
101
|
+
## PR governance without burning CI
|
|
102
|
+
|
|
103
|
+
These fail **before** expensive tests if you get them wrong — fix **before**
|
|
104
|
+
push/open:
|
|
105
|
+
|
|
106
|
+
- PR description AI/model disclosure + `Session id` (or `Session-skip`)
|
|
107
|
+
- `Review-skip: SKIP <reason>` must match `^Review-skip:` at **line start**
|
|
108
|
+
(not nested under a bullet)
|
|
109
|
+
- `Blueprint-exempt:` / `Changeset-exempt:` in **commit message** and/or body
|
|
110
|
+
when required (blueprint-pr-coverage reads **git trailers**, not only the PR body)
|
|
111
|
+
- Version Packages / bot CI: do not invent admin-merge; use the runbook
|
|
112
|
+
(`docs/runbooks/version-packages-bot-ci.md` when present)
|
|
113
|
+
|
|
114
|
+
## Forbidden agent habits
|
|
115
|
+
|
|
116
|
+
- Push → watch red CI → tweak → push again (the “CI as unit test” loop)
|
|
117
|
+
- Broaden CI timeouts / disable flakes instead of root-cause fix
|
|
118
|
+
- Schedule or matrix-expand macOS/Windows for convenience
|
|
119
|
+
- Upload large artifacts every PR “for debugging”
|
|
120
|
+
- Claim “CI is green” from a partial check while WP check / required jobs pending
|
|
121
|
+
- Force-push past hooks to land red work for “later fix”
|
|
122
|
+
|
|
123
|
+
## Good loop
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
edit → scoped lint/type/test → commit (hooks) → wp ci-preflight → push
|
|
127
|
+
→ open PR with complete body → watch CI once → fix root cause locally if red
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
When CI fails: download/read the failed job log, reproduce with the matching
|
|
131
|
+
local `wp` command, fix, preflight, push **one** corrective commit.
|
|
132
|
+
|
|
133
|
+
## Related
|
|
134
|
+
|
|
135
|
+
- `cmd-execution.md` — bookend QA; scoped commands in the middle
|
|
136
|
+
- `ci-test-perf.md` — parallelism and install cache
|
|
137
|
+
- `pre-implementation.md` — blueprint gates that only fail in CI if left open
|
|
138
|
+
- `hook-hot-path.md` — pre-push stays local and non-network
|
|
139
|
+
- CLI: `wp ci-preflight` (pre-push owner)
|
|
@@ -56,9 +56,13 @@ Mutation/Stryker jobs are auto-exempt when the step/job name or nearby lines men
|
|
|
56
56
|
When a single job still exceeds budget **with full coverage**:
|
|
57
57
|
|
|
58
58
|
1. Prefer **Vitest sharding** (`vitest run --shard=i/n` + blob reporter merge) over raising isolation-off globally.
|
|
59
|
-
2. Prefer a **larger runner** (`ubicloud-standard-4`, etc.) + more `VITEST_MAX_WORKERS` over dropping suites.
|
|
59
|
+
2. Prefer a **larger runner** (`ubicloud-standard-4`, etc.) + more `VITEST_MAX_WORKERS` over dropping suites — only after `ubicloud-standard-2` is proven insufficient. Do not jump to GitHub-hosted macOS/Windows for ordinary test jobs.
|
|
60
60
|
3. Cache **native/build artifacts** when warm steps rebuild every PR (producer-specific).
|
|
61
61
|
|
|
62
|
+
Private-repo default is **Ubicloud** for non-release jobs. GitHub-hosted
|
|
63
|
+
runners are reserved for Release/OIDC publish (and release-native OS builds).
|
|
64
|
+
See `ci-cost-local-first.md`.
|
|
65
|
+
|
|
62
66
|
## Related
|
|
63
67
|
|
|
64
68
|
- Vitest performance: https://vitest.dev/guide/improving-performance
|
|
@@ -14,6 +14,15 @@ paths:
|
|
|
14
14
|
|
|
15
15
|
# Command Execution Rules
|
|
16
16
|
|
|
17
|
+
## Local-first before remote CI
|
|
18
|
+
|
|
19
|
+
Paid CI (Ubicloud + GitHub-hosted) is for confirmation. Use scoped commands
|
|
20
|
+
while iterating, then **`wp ci-preflight` before every push**. In agent-kit
|
|
21
|
+
itself, `.husky/pre-push` enforces that gate; consumer templates may leave
|
|
22
|
+
pre-push checks user-owned. Never `git push --no-verify` to skip a configured
|
|
23
|
+
local gate. See `ci-cost-local-first.md` for runner policy and anti-red-loop
|
|
24
|
+
habits.
|
|
25
|
+
|
|
17
26
|
## BOOKEND Rule: Full QA Runs Exactly Twice
|
|
18
27
|
|
|
19
28
|
The full QA pipeline (e.g. `wp qa`, `bun run qa`) is a
|
|
@@ -264,7 +264,8 @@ Doing it post-merge is also impossible without a second PR: you cannot push the
|
|
|
264
264
|
**Local pre-push check (catches the CI failure before it costs minutes):** the
|
|
265
265
|
local lifecycle audit gives a false pass here because the owner worktree resolves
|
|
266
266
|
on your machine. So do not rely on it alone — before opening or updating the PR,
|
|
267
|
-
confirm no changed blueprint
|
|
267
|
+
run `wp ci-preflight` for ordinary quality gates and confirm no changed blueprint
|
|
268
|
+
is still under `blueprints/in-progress/`:
|
|
268
269
|
|
|
269
270
|
```bash
|
|
270
271
|
git diff --name-only origin/main...HEAD | grep -q '^blueprints/in-progress/' \
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: rule
|
|
3
|
+
slug: test-scan-perf
|
|
4
|
+
title: Test scan performance (no full-repo FS walks)
|
|
5
|
+
status: active
|
|
6
|
+
scope: repo
|
|
7
|
+
applies_to: [agents]
|
|
8
|
+
related:
|
|
9
|
+
- testing-philosophy
|
|
10
|
+
- ci-test-perf
|
|
11
|
+
created: "2026-07-20"
|
|
12
|
+
last_reviewed: "2026-07-20"
|
|
13
|
+
paths:
|
|
14
|
+
- "**/*.{test,spec}.{ts,tsx,js,jsx}"
|
|
15
|
+
- "src/audit/test-scan-perf.ts"
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Test scan performance
|
|
19
|
+
|
|
20
|
+
Unit and contract tests must not walk the whole repository with
|
|
21
|
+
`readdirSync` / `statSync` / `readFileSync` and paper over the cost with a
|
|
22
|
+
30s+ per-test timeout.
|
|
23
|
+
|
|
24
|
+
## Forbidden pattern
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
const repoRoot = findRepoRoot();
|
|
28
|
+
const walk = (dir: string) => {
|
|
29
|
+
for (const entry of readdirSync(dir)) {
|
|
30
|
+
const full = join(dir, entry);
|
|
31
|
+
if (statSync(full).isDirectory()) {
|
|
32
|
+
walk(full);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const text = readFileSync(full, "utf8");
|
|
36
|
+
// ...
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
walk(repoRoot);
|
|
40
|
+
|
|
41
|
+
it("scan", () => {
|
|
42
|
+
/* ... */
|
|
43
|
+
}, 30_000); // band-aid
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Preferred
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
// Tracked files only — seconds, not tens of seconds.
|
|
50
|
+
const stdout = execFileSync(
|
|
51
|
+
"git",
|
|
52
|
+
["-C", root, "grep", "-l", "-I", "-E", "RETIRED_SPECIFIER_A|RETIRED_SPECIFIER_B"],
|
|
53
|
+
{ encoding: "utf8" },
|
|
54
|
+
);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Or walk a **bounded** fixture / package tree (not `findRepoRoot()` / `process.cwd()`).
|
|
58
|
+
|
|
59
|
+
## Guardrail
|
|
60
|
+
|
|
61
|
+
| Surface | Contract |
|
|
62
|
+
| ---------- | ---------------------------------- |
|
|
63
|
+
| Audit | `wp audit test-scan-perf` |
|
|
64
|
+
| Guardrails | included in `wp audit guardrails` |
|
|
65
|
+
| Scope | affected-safe (changed test files) |
|
|
66
|
+
|
|
67
|
+
### Opt-out
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// test-scan-perf-allow — one-off inventory with justification
|
|
71
|
+
walk(repoRoot);
|
|
72
|
+
|
|
73
|
+
// or once per file:
|
|
74
|
+
// test-scan-perf-allow-file — full inventory intentionally walks the tree
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Related
|
|
78
|
+
|
|
79
|
+
- Implementation: `src/audit/test-scan-perf.ts`
|
|
80
|
+
- CI workers/cache: `ci-test-perf` (workflow-level, separate concern)
|
|
@@ -74,8 +74,10 @@ Map routing intent like this:
|
|
|
74
74
|
- debugging and regressions → `investigate` then `fix`
|
|
75
75
|
- bounded cleanup after behavior is green → `ai-deslop`
|
|
76
76
|
- multi-task / parallel execute → `ultragoal` + `/pll` (ready-queue, worktrees)
|
|
77
|
-
- local completeness → `/verify
|
|
78
|
-
(exactly one sequential outside
|
|
77
|
+
- local completeness → `/verify` then `wp ci-preflight` before push; merge-ready
|
|
78
|
+
outside voice → `/verify --merge-ready` (exactly one sequential outside
|
|
79
|
+
reviewer unless user sets N). Do not use remote CI as the first debugger
|
|
80
|
+
(`ci-cost-local-first`).
|
|
79
81
|
|
|
80
82
|
Use the full `wp_*` MCP surface for tests, lint, typecheck, audits, session memory,
|
|
81
83
|
ultragoal, worktrees, PRs, and quality gates — not shell reimplementations. Use
|
|
@@ -122,12 +122,15 @@ Run the narrowest checks that prove the repaired behavior on the real repo surfa
|
|
|
122
122
|
- `wp_test` / targeted tests for the repaired path
|
|
123
123
|
- `wp_lint` / `wp_typecheck` for changed surfaces
|
|
124
124
|
- `wp_qa` only when the blast radius needs the bookend
|
|
125
|
+
- Before push: `wp ci-preflight` (local pre-push owner). Do not use remote CI
|
|
126
|
+
re-runs as the primary fix loop (`ci-cost-local-first`).
|
|
125
127
|
|
|
126
128
|
Rules:
|
|
127
129
|
|
|
128
130
|
- Prefer MCP `wp_*` over raw host Bash.
|
|
129
131
|
- Reuse fresh logs / session-memory indexed output; do not re-run long commands just to re-read.
|
|
130
132
|
- Read the exit code and summary before making a claim.
|
|
133
|
+
- Never `git push --no-verify` to land an unproven fix.
|
|
131
134
|
|
|
132
135
|
Escalate to `/verify <target>` (local) or `/verify <target> --merge-ready` when any of these are true:
|
|
133
136
|
|
|
@@ -109,6 +109,9 @@ workflow:
|
|
|
109
109
|
1. Identify target type (file / package / blueprint slug / all).
|
|
110
110
|
2. Map each claim you plan to make to the exact command or log that proves it.
|
|
111
111
|
3. If the target is a blueprint slug, run the repo's blueprint show/audit surface and record the acceptance boxes that still need proof.
|
|
112
|
+
4. **CI cost / local-first:** treat remote CI as confirmation, not the first
|
|
113
|
+
debugger. Load `ci-cost-local-first` expectations: no hook skips, no
|
|
114
|
+
blind `gh run rerun`, Ubicloud for private non-release jobs.
|
|
112
115
|
|
|
113
116
|
## Phase 1 — Governance gates
|
|
114
117
|
|
|
@@ -130,12 +133,27 @@ Run the narrowest checks that prove the touched behavior:
|
|
|
130
133
|
- `wp_test` / targeted tests
|
|
131
134
|
- `wp_qa`, `wp_e2e`, build / package checks only when the change requires them
|
|
132
135
|
|
|
136
|
+
**Before push or PR open/update**, run the pre-push owner end-to-end:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
wp ci-preflight
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
That is fail-fast branch-scoped format → guardrails → typecheck → lint →
|
|
143
|
+
test. Agent-kit itself enforces it from `.husky/pre-push`; consumer repos may
|
|
144
|
+
keep pre-push checks user-owned, so run the command explicitly before pushing.
|
|
145
|
+
Do **not** claim push-ready if preflight failed. Do **not** bypass hooks to ship
|
|
146
|
+
red work.
|
|
147
|
+
|
|
133
148
|
Rules:
|
|
134
149
|
|
|
135
150
|
- Prefer MCP `wp_*` over raw underlying tools.
|
|
136
151
|
- Reuse fresh logs / session-memory indexed output if the runner auto-saves them.
|
|
137
152
|
- Never claim broader correctness than the commands actually proved.
|
|
138
153
|
- If the repo documents a "full QA" bookend, reserve `wp_qa` / `--full` for the final broad pass rather than every iteration.
|
|
154
|
+
- If CI is already red: read the failed job log, reproduce with the matching
|
|
155
|
+
local `wp` command, fix, re-run `wp ci-preflight`, then push **one**
|
|
156
|
+
corrective commit — do not burn another full matrix “to check.”
|
|
139
157
|
|
|
140
158
|
## Phase 3 — Cross-surface impact scan
|
|
141
159
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
|
-
import {
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join, relative } from "node:path";
|
|
3
4
|
import { resolveBlueprintRoot } from "#utils/blueprint-root.js";
|
|
4
5
|
const TITLE = "Blueprint PR coverage";
|
|
5
6
|
const BLUEPRINT_EXEMPT_PATTERN = /^Blueprint-exempt:\s*(\S.*)$/im;
|
|
@@ -39,14 +40,33 @@ export function auditBlueprintPrCoverage(rootDirectory = process.cwd(), options
|
|
|
39
40
|
const configuredRoot = normalizeRoot(normalizePath(relative(rootDirectory, resolveBlueprintRoot(rootDirectory))));
|
|
40
41
|
const blueprintRoots = [...new Set(["blueprints", configuredRoot].filter(Boolean))];
|
|
41
42
|
const finalEntries = entries.filter((entry) => entry.status !== "D");
|
|
42
|
-
const
|
|
43
|
+
const activeEntries = finalEntries.flatMap((entry) => {
|
|
43
44
|
const location = parseBlueprintLocation(entry.path, blueprintRoots);
|
|
44
|
-
|
|
45
|
+
if (!location || !ACTIVE_LIFECYCLE_DIRECTORIES.has(location.lifecycle))
|
|
46
|
+
return [];
|
|
47
|
+
return [{ entry, location }];
|
|
45
48
|
});
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.
|
|
49
|
+
const ownerActive = activeEntries.filter(({ location }) => location.slug === ownerSlug);
|
|
50
|
+
if (ownerActive.length > 0) {
|
|
51
|
+
return fail(`non-doc landing PR leaves owner blueprint "${ownerSlug}" in active lifecycle at ${ownerActive
|
|
52
|
+
.map(({ entry }) => entry.path)
|
|
53
|
+
.join(", ")}; move completed/${ownerSlug}/_overview.md (or .md) into the PR and drop active-lifecycle owner paths`, changedFiles.length);
|
|
54
|
+
}
|
|
55
|
+
// Parent-roadmap program trackers may co-edit on a child land PR while still
|
|
56
|
+
// active (draft/planned). Executable blueprints (type: blueprint) may not.
|
|
57
|
+
const nonOwnerActive = activeEntries.filter(({ location }) => location.slug !== ownerSlug);
|
|
58
|
+
const programTrackers = [];
|
|
59
|
+
const blockingNonOwner = [];
|
|
60
|
+
for (const { entry, location } of nonOwnerActive) {
|
|
61
|
+
if (isParentRoadmapDocument(rootDirectory, entry.path, location)) {
|
|
62
|
+
programTrackers.push(entry.path);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
blockingNonOwner.push(entry.path);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (blockingNonOwner.length > 0) {
|
|
69
|
+
return fail(`non-doc landing PR changes active non-owner blueprint content at ${blockingNonOwner.join(", ")}; remove those paths from the PR or complete those blueprints first (owner ${ownerSlug} is separate)`, changedFiles.length);
|
|
50
70
|
}
|
|
51
71
|
const matchingCompletedOwner = finalEntries.some((entry) => {
|
|
52
72
|
const location = parseBlueprintLocation(entry.path, blueprintRoots);
|
|
@@ -55,6 +75,9 @@ export function auditBlueprintPrCoverage(rootDirectory = process.cwd(), options
|
|
|
55
75
|
if (!matchingCompletedOwner) {
|
|
56
76
|
return fail(`non-doc PR on ${headRef} must change its completed owner blueprint at completed/${ownerSlug}/_overview.md (or completed/${ownerSlug}.md)`, changedFiles.length);
|
|
57
77
|
}
|
|
78
|
+
if (programTrackers.length > 0) {
|
|
79
|
+
return passWithWarning(`[warn] co-edited parent-roadmap program tracker(s) on non-doc land: ${programTrackers.join(", ")}`, changedFiles.length);
|
|
80
|
+
}
|
|
58
81
|
return pass(changedFiles.length);
|
|
59
82
|
}
|
|
60
83
|
function pass(checked) {
|
|
@@ -134,6 +157,44 @@ function parseBlueprintLocation(filePath, roots) {
|
|
|
134
157
|
}
|
|
135
158
|
return null;
|
|
136
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* True when the changed path belongs to a `type: parent-roadmap` document.
|
|
162
|
+
* Nested non-overview files under a parent-roadmap folder inherit the overview
|
|
163
|
+
* type so review artifacts co-travel. Missing paths (unit-test fakes) return
|
|
164
|
+
* false → fail closed as executable blueprints.
|
|
165
|
+
*/
|
|
166
|
+
function isParentRoadmapDocument(rootDirectory, filePath, location) {
|
|
167
|
+
const normalized = normalizePath(filePath);
|
|
168
|
+
const overviewCandidates = [
|
|
169
|
+
// Prefer the changed overview when it is the document itself.
|
|
170
|
+
...(location.ownerDocument ? [normalized] : []),
|
|
171
|
+
// folder overview: …/<lifecycle>/<slug>/_overview.md
|
|
172
|
+
normalized.replace(new RegExp(`/(draft|planned|in-progress|parked|completed|archived)/${escapeRegex(location.slug)}(?:/.*)?$`, "u"), `/$1/${location.slug}/_overview.md`),
|
|
173
|
+
// flat overview: …/<lifecycle>/<slug>.md
|
|
174
|
+
normalized.replace(new RegExp(`/(draft|planned|in-progress|parked|completed|archived)/${escapeRegex(location.slug)}(?:/.*|\\.md)?$`, "u"), `/$1/${location.slug}.md`),
|
|
175
|
+
];
|
|
176
|
+
const seen = new Set();
|
|
177
|
+
for (const candidate of overviewCandidates) {
|
|
178
|
+
if (seen.has(candidate))
|
|
179
|
+
continue;
|
|
180
|
+
seen.add(candidate);
|
|
181
|
+
const abs = join(rootDirectory, candidate);
|
|
182
|
+
if (!existsSync(abs))
|
|
183
|
+
continue;
|
|
184
|
+
try {
|
|
185
|
+
const head = readFileSync(abs, "utf8").slice(0, 4_096);
|
|
186
|
+
if (/^type:\s*['"]?parent-roadmap['"]?\s*$/mu.test(head))
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
// unreadable → fail closed
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
function escapeRegex(value) {
|
|
196
|
+
return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
197
|
+
}
|
|
137
198
|
function isDependabotDependencyOnlyUpdate(cwd, options, changedFiles) {
|
|
138
199
|
if (!changedFiles.every(isDependabotDependencyFile))
|
|
139
200
|
return false;
|
|
@@ -14,11 +14,11 @@ export interface AuditKindDescriptor {
|
|
|
14
14
|
}
|
|
15
15
|
export declare const SCRIPT_AUDIT_KIND_IDS: readonly ["test-smells", "tph-e2e"];
|
|
16
16
|
export declare const SPECIAL_AUDIT_KIND_IDS: readonly ["bundle-budget", "commit-message", "blueprint-pr-coverage", "mutation", "guardrails", "quality"];
|
|
17
|
-
export declare const REPO_AUDIT_KIND_IDS: readonly ["catalog-drift", "package-surface", "command-surface", "reference-parity-matrix", "blueprint-readme-drift", "blueprint-lifecycle", "blueprint-trust", "roadmap-links", "docs-frontmatter", "agents", "vision", "tech-debt", "supported-agent-clis", "no-relative-parent-imports", "no-link-protocol", "no-relative-package-scripts", "test-isolation", "bucket-boundary", "skill-sizes", "broken-refs", "memory-rotation", "gitignore-agent-surfaces", "memory-unified", "compile-drift", "no-legacy-cli-bin", "architecture-drift", "cloudflare-deploy-contract", "toolchain-isolation", "absolute-path-policy", "no-first-party-mjs", "outside-review-runtime-ownership", "no-math-random", "agent-cost", "blueprint-db-consistency", "tech-debt-cadence", "cross-repo-correlation", "ai-contracts", "atomic-state-writes", "hook-surface", "hook-vendor-drift", "session-memory-hardcut", "open-source-licenses", "secrets-policy", "no-dev-vars", "secret-provider-quarantine", "github-actions-secrets", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "worktree-main-ownership", "sast", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "legacy-workflow-identity", "rules", "skills"];
|
|
17
|
+
export declare const REPO_AUDIT_KIND_IDS: readonly ["catalog-drift", "package-surface", "command-surface", "reference-parity-matrix", "blueprint-readme-drift", "blueprint-lifecycle", "blueprint-trust", "roadmap-links", "docs-frontmatter", "agents", "vision", "tech-debt", "supported-agent-clis", "no-relative-parent-imports", "no-link-protocol", "no-relative-package-scripts", "test-isolation", "bucket-boundary", "skill-sizes", "broken-refs", "memory-rotation", "gitignore-agent-surfaces", "memory-unified", "compile-drift", "no-legacy-cli-bin", "architecture-drift", "cloudflare-deploy-contract", "toolchain-isolation", "absolute-path-policy", "no-first-party-mjs", "outside-review-runtime-ownership", "no-math-random", "agent-cost", "blueprint-db-consistency", "tech-debt-cadence", "cross-repo-correlation", "ai-contracts", "atomic-state-writes", "hook-surface", "hook-vendor-drift", "session-memory-hardcut", "open-source-licenses", "secrets-policy", "no-dev-vars", "secret-provider-quarantine", "github-actions-secrets", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "test-scan-perf", "worktree-main-ownership", "sast", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "legacy-workflow-identity", "rules", "skills"];
|
|
18
18
|
export declare const AUDIT_KIND_DESCRIPTORS: readonly AuditKindDescriptor[];
|
|
19
|
-
export declare const AUDIT_KIND_IDS: readonly ["test-smells", "tph-e2e", ...("absolute-path-policy" | "agent-cost" | "agents" | "ai-contracts" | "architecture-drift" | "atomic-state-writes" | "blueprint-db-consistency" | "blueprint-lifecycle" | "blueprint-pr-coverage" | "blueprint-readme-drift" | "blueprint-trust" | "broken-refs" | "bucket-boundary" | "bundle-budget" | "catalog-drift" | "ci-test-perf" | "cloudflare-deploy-contract" | "command-surface" | "commit-message" | "compile-drift" | "consumer-agent-kit-dependency" | "cross-repo-correlation" | "docs-frontmatter" | "github-actions-secrets" | "gitignore-agent-surfaces" | "guardrails" | "harness-overlay-evidence" | "harness-surfaces" | "hook-surface" | "hook-vendor-drift" | "legacy-workflow-identity" | "memory-rotation" | "memory-unified" | "mutation" | "no-dev-vars" | "no-first-party-mjs" | "no-legacy-cli-bin" | "no-link-protocol" | "no-math-random" | "no-relative-package-scripts" | "no-relative-parent-imports" | "open-source-licenses" | "outside-review-runtime-ownership" | "package-surface" | "quality" | "reference-parity-matrix" | "roadmap-links" | "rules" | "sast" | "secret-provider-quarantine" | "secrets-config" | "secrets-policy" | "security-quality-regressions" | "session-memory-hardcut" | "skill-sizes" | "skills" | "supported-agent-clis" | "tech-debt" | "tech-debt-cadence" | "test-isolation" | "toolchain-isolation" | "vision" | "weakness-mining" | "worktree-main-ownership")[]];
|
|
20
|
-
export declare const MCP_AUDIT_KIND_IDS: readonly ["test-smells", "tph-e2e", "agents", "catalog-drift", "package-surface", "reference-parity-matrix", "docs-frontmatter", "blueprint-readme-drift", "blueprint-pr-coverage", "blueprint-lifecycle", "blueprint-trust", "architecture-drift", "cloudflare-deploy-contract", "absolute-path-policy", "no-first-party-mjs", "no-math-random", "roadmap-links", "bundle-budget", "commit-message", "tech-debt", "supported-agent-clis", "hook-surface", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "ai-contracts", "atomic-state-writes", "no-relative-package-scripts", "toolchain-isolation", "open-source-licenses", "secrets-policy", "no-dev-vars", "github-actions-secrets", "secret-provider-quarantine", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "session-memory-hardcut", "worktree-main-ownership", "sast"];
|
|
21
|
-
export declare const AFFECTED_SAFE_AUDIT_KIND_IDS: readonly ["blueprint-readme-drift", "blueprint-lifecycle", "bucket-boundary", "skill-sizes", "broken-refs", "no-dev-vars", "absolute-path-policy", "secret-provider-quarantine", "secrets-config", "docs-frontmatter", "no-relative-parent-imports", "no-link-protocol", "no-first-party-mjs", "no-math-random"];
|
|
19
|
+
export declare const AUDIT_KIND_IDS: readonly ["test-smells", "tph-e2e", ...("absolute-path-policy" | "agent-cost" | "agents" | "ai-contracts" | "architecture-drift" | "atomic-state-writes" | "blueprint-db-consistency" | "blueprint-lifecycle" | "blueprint-pr-coverage" | "blueprint-readme-drift" | "blueprint-trust" | "broken-refs" | "bucket-boundary" | "bundle-budget" | "catalog-drift" | "ci-test-perf" | "cloudflare-deploy-contract" | "command-surface" | "commit-message" | "compile-drift" | "consumer-agent-kit-dependency" | "cross-repo-correlation" | "docs-frontmatter" | "github-actions-secrets" | "gitignore-agent-surfaces" | "guardrails" | "harness-overlay-evidence" | "harness-surfaces" | "hook-surface" | "hook-vendor-drift" | "legacy-workflow-identity" | "memory-rotation" | "memory-unified" | "mutation" | "no-dev-vars" | "no-first-party-mjs" | "no-legacy-cli-bin" | "no-link-protocol" | "no-math-random" | "no-relative-package-scripts" | "no-relative-parent-imports" | "open-source-licenses" | "outside-review-runtime-ownership" | "package-surface" | "quality" | "reference-parity-matrix" | "roadmap-links" | "rules" | "sast" | "secret-provider-quarantine" | "secrets-config" | "secrets-policy" | "security-quality-regressions" | "session-memory-hardcut" | "skill-sizes" | "skills" | "supported-agent-clis" | "tech-debt" | "tech-debt-cadence" | "test-isolation" | "test-scan-perf" | "toolchain-isolation" | "vision" | "weakness-mining" | "worktree-main-ownership")[]];
|
|
20
|
+
export declare const MCP_AUDIT_KIND_IDS: readonly ["test-smells", "tph-e2e", "agents", "catalog-drift", "package-surface", "reference-parity-matrix", "docs-frontmatter", "blueprint-readme-drift", "blueprint-pr-coverage", "blueprint-lifecycle", "blueprint-trust", "architecture-drift", "cloudflare-deploy-contract", "absolute-path-policy", "no-first-party-mjs", "no-math-random", "roadmap-links", "bundle-budget", "commit-message", "tech-debt", "supported-agent-clis", "hook-surface", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "ai-contracts", "atomic-state-writes", "no-relative-package-scripts", "toolchain-isolation", "open-source-licenses", "secrets-policy", "no-dev-vars", "github-actions-secrets", "secret-provider-quarantine", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "test-scan-perf", "session-memory-hardcut", "worktree-main-ownership", "sast"];
|
|
21
|
+
export declare const AFFECTED_SAFE_AUDIT_KIND_IDS: readonly ["blueprint-readme-drift", "blueprint-lifecycle", "bucket-boundary", "skill-sizes", "broken-refs", "no-dev-vars", "absolute-path-policy", "secret-provider-quarantine", "secrets-config", "docs-frontmatter", "no-relative-parent-imports", "no-link-protocol", "no-first-party-mjs", "no-math-random", "test-scan-perf"];
|
|
22
22
|
export type AuditKindId = (typeof AUDIT_KIND_IDS)[number];
|
|
23
23
|
export type RepoAuditKindId = (typeof REPO_AUDIT_KIND_IDS)[number];
|
|
24
24
|
export type MCPAuditKindId = (typeof MCP_AUDIT_KIND_IDS)[number];
|
|
@@ -16,6 +16,7 @@ const affectedSafeKinds = [
|
|
|
16
16
|
"no-link-protocol",
|
|
17
17
|
"no-first-party-mjs",
|
|
18
18
|
"no-math-random",
|
|
19
|
+
"test-scan-perf",
|
|
19
20
|
];
|
|
20
21
|
const mcpKindIds = [
|
|
21
22
|
"test-smells",
|
|
@@ -56,6 +57,7 @@ const mcpKindIds = [
|
|
|
56
57
|
"secrets-config",
|
|
57
58
|
"consumer-agent-kit-dependency",
|
|
58
59
|
"ci-test-perf",
|
|
60
|
+
"test-scan-perf",
|
|
59
61
|
"session-memory-hardcut",
|
|
60
62
|
"worktree-main-ownership",
|
|
61
63
|
"sast",
|
|
@@ -130,6 +132,7 @@ const repoKinds = [
|
|
|
130
132
|
"secrets-config",
|
|
131
133
|
"consumer-agent-kit-dependency",
|
|
132
134
|
"ci-test-perf",
|
|
135
|
+
"test-scan-perf",
|
|
133
136
|
"worktree-main-ownership",
|
|
134
137
|
"sast",
|
|
135
138
|
"harness-surfaces",
|
|
@@ -58,7 +58,13 @@ export function auditRoadmapLinks(rootDirectory = process.cwd(), options = {}) {
|
|
|
58
58
|
message: "Parent-roadmap execution-wave maps may list local child blueprints only; move cross-repo references to Cross-Plan References and use GitHub links there",
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
|
+
// Archived parent-roadmaps are non-executable program records. They may
|
|
62
|
+
// document completed children without a live execution-wave map or local
|
|
63
|
+
// children still declaring parent_roadmap. Do not fail CI on that residue.
|
|
61
64
|
if (waveMapChildren.size === 0 && localChildren.length === 0) {
|
|
65
|
+
if (roadmap.status === "archived") {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
62
68
|
violations.push({
|
|
63
69
|
file: roadmap.file,
|
|
64
70
|
message: "Roadmap declares no children in its wave map",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guardrail: keep tests from silently growing multi-second / multi-ten-second
|
|
3
|
+
* full-repo filesystem scans, and from "fixing" that cost with elevated
|
|
4
|
+
* per-test timeouts.
|
|
5
|
+
*
|
|
6
|
+
* The private-UI cutover anti-regression suite originally walked the monorepo
|
|
7
|
+
* with readdirSync/statSync/readFileSync and needed a 30s timeout. Prefer
|
|
8
|
+
* `git grep` (tracked files) or a bounded fixture tree instead.
|
|
9
|
+
*
|
|
10
|
+
* Opt-out: `// test-scan-perf-allow` on the same line or previous line as the
|
|
11
|
+
* walk/timeout site, or `// test-scan-perf-allow-file` anywhere in the file.
|
|
12
|
+
*/
|
|
13
|
+
import type { RepoAuditResult, RepoAuditViolation } from "./repo-guardrails.js";
|
|
14
|
+
export declare function isTestScanPerfTargetPath(relativePath: string): boolean;
|
|
15
|
+
export declare function findTestScanPerfViolationsInText(relativePath: string, text: string): RepoAuditViolation[];
|
|
16
|
+
export declare function auditTestScanPerf(rootDirectory?: string, options?: {
|
|
17
|
+
affectedFiles?: readonly string[];
|
|
18
|
+
}): RepoAuditResult;
|