@mjasnikovs/pi-task 0.38.28 → 0.38.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/dist/config/config.d.ts +70 -70
- package/dist/config/config.js +26 -35
- package/dist/config/extension-list.d.ts +6 -5
- package/dist/config/extension-list.js +3 -2
- package/dist/config/reasoning-args.d.ts +9 -7
- package/dist/config/reasoning-args.js +12 -10
- package/dist/config/reasoning.d.ts +44 -105
- package/dist/config/reasoning.js +27 -704
- package/dist/config/register.d.ts +34 -48
- package/dist/config/register.js +41 -51
- package/dist/config/tool-list.d.ts +16 -16
- package/dist/config/tool-list.js +1 -1
- package/dist/remote/bridge.d.ts +19 -10
- package/dist/remote/bridge.js +3 -2
- package/dist/remote/broadcast.js +3 -1
- package/dist/remote/events.js +12 -11
- package/dist/remote/history.d.ts +1 -1
- package/dist/remote/protocol.d.ts +6 -3
- package/dist/remote/protocol.js +2 -1
- package/dist/remote/push.d.ts +16 -16
- package/dist/remote/push.js +27 -27
- package/dist/remote/register.d.ts +3 -3
- package/dist/remote/register.js +17 -19
- package/dist/remote/server.d.ts +9 -8
- package/dist/remote/server.js +15 -14
- package/dist/remote/session-state.d.ts +5 -4
- package/dist/remote/session-state.js +8 -5
- package/dist/remote/sw.d.ts +7 -6
- package/dist/remote/sw.js +7 -6
- package/dist/remote/tailscale.d.ts +4 -2
- package/dist/remote/tailscale.js +4 -2
- package/dist/remote/ui-highlight.js +6 -5
- package/dist/remote/ui-render.js +4 -4
- package/dist/remote/ui-script.js +24 -24
- package/dist/remote/ui-styles.d.ts +1 -1
- package/dist/remote/ui-styles.js +10 -13
- package/dist/remote/ui-tools.js +9 -6
- package/dist/shared/child-extensions.d.ts +29 -17
- package/dist/shared/child-extensions.js +29 -17
- package/dist/shared/child-output.d.ts +30 -24
- package/dist/shared/child-output.js +25 -17
- package/dist/shared/child-process.d.ts +47 -40
- package/dist/shared/child-process.js +50 -59
- package/dist/shared/command-watchdog.d.ts +22 -16
- package/dist/shared/command-watchdog.js +28 -21
- package/dist/shared/fs-text.d.ts +16 -10
- package/dist/shared/fs-text.js +16 -10
- package/dist/shared/git-runner.d.ts +25 -25
- package/dist/shared/git-runner.js +25 -25
- package/dist/shared/leaked-tool-call.d.ts +17 -11
- package/dist/shared/leaked-tool-call.js +23 -15
- package/dist/shared/model-endpoint.d.ts +29 -16
- package/dist/shared/model-endpoint.js +33 -21
- package/dist/shared/pi-invocation.d.ts +7 -4
- package/dist/shared/pi-invocation.js +12 -7
- package/dist/shared/pkg-version.d.ts +13 -5
- package/dist/shared/pkg-version.js +13 -5
- package/dist/shared/reasoning-capability.d.ts +35 -24
- package/dist/shared/reasoning-capability.js +35 -24
- package/dist/shared/stream-watchdog.d.ts +60 -44
- package/dist/shared/stream-watchdog.js +62 -45
- package/dist/task/accept-debt.d.ts +41 -43
- package/dist/task/accept-debt.js +73 -65
- package/dist/task/api-synthesis.d.ts +24 -21
- package/dist/task/api-synthesis.js +32 -26
- package/dist/task/apis-contract.d.ts +32 -64
- package/dist/task/apis-contract.js +32 -64
- package/dist/task/artifact-closure.d.ts +27 -13
- package/dist/task/artifact-closure.js +95 -67
- package/dist/task/auto-commit.d.ts +46 -35
- package/dist/task/auto-commit.js +51 -38
- package/dist/task/auto-io.d.ts +45 -25
- package/dist/task/auto-io.js +57 -29
- package/dist/task/auto-orchestrator.d.ts +26 -24
- package/dist/task/auto-orchestrator.js +178 -162
- package/dist/task/auto-prompts.d.ts +36 -24
- package/dist/task/auto-prompts.js +40 -26
- package/dist/task/autofix-ledger.d.ts +27 -25
- package/dist/task/autofix-ledger.js +29 -26
- package/dist/task/batch-test-task.d.ts +20 -12
- package/dist/task/batch-test-task.js +67 -60
- package/dist/task/boot-probe.d.ts +60 -44
- package/dist/task/boot-probe.js +91 -72
- package/dist/task/cancel-input.d.ts +30 -16
- package/dist/task/cancel-input.js +20 -11
- package/dist/task/cancel-points.d.ts +27 -20
- package/dist/task/cancel-points.js +30 -22
- package/dist/task/child-runner.d.ts +46 -51
- package/dist/task/child-runner.js +48 -49
- package/dist/task/child-status.d.ts +23 -16
- package/dist/task/child-status.js +23 -16
- package/dist/task/clamp-output.js +12 -5
- package/dist/task/command-run.d.ts +31 -28
- package/dist/task/command-run.js +44 -35
- package/dist/task/command-shrink.d.ts +25 -18
- package/dist/task/command-shrink.js +37 -31
- package/dist/task/command-watchdog.d.ts +9 -6
- package/dist/task/command-watchdog.js +21 -15
- package/dist/task/context-attribution.d.ts +34 -26
- package/dist/task/context-attribution.js +34 -26
- package/dist/task/context-silence.d.ts +39 -29
- package/dist/task/context-silence.js +35 -25
- package/dist/task/context-usage.d.ts +25 -7
- package/dist/task/context-usage.js +21 -6
- package/dist/task/contracts.d.ts +8 -4
- package/dist/task/contracts.js +25 -17
- package/dist/task/coverage-loop.d.ts +22 -18
- package/dist/task/coverage-loop.js +35 -30
- package/dist/task/critique-probes.d.ts +13 -14
- package/dist/task/critique-probes.js +50 -39
- package/dist/task/debug-log.d.ts +13 -5
- package/dist/task/debug-log.js +32 -20
- package/dist/task/decompose-fidelity.d.ts +11 -9
- package/dist/task/decompose-fidelity.js +38 -33
- package/dist/task/decompose-granularity.d.ts +41 -38
- package/dist/task/decompose-granularity.js +41 -38
- package/dist/task/deep-render-check.d.ts +22 -14
- package/dist/task/deep-render-check.js +40 -31
- package/dist/task/dropped-input.d.ts +12 -7
- package/dist/task/dropped-input.js +5 -2
- package/dist/task/enforce-attribution.d.ts +38 -47
- package/dist/task/enforce-attribution.js +46 -52
- package/dist/task/enforce-guidelines.d.ts +31 -20
- package/dist/task/enforce-guidelines.js +32 -21
- package/dist/task/enrichment.d.ts +7 -2
- package/dist/task/enrichment.js +26 -14
- package/dist/task/env-notes.d.ts +16 -7
- package/dist/task/env-notes.js +48 -31
- package/dist/task/env-template-closure.d.ts +4 -4
- package/dist/task/env-template-closure.js +42 -34
- package/dist/task/external-context.d.ts +28 -21
- package/dist/task/external-context.js +17 -12
- package/dist/task/failure-classifier.d.ts +4 -5
- package/dist/task/failure-classifier.js +6 -7
- package/dist/task/file-inventory.d.ts +15 -11
- package/dist/task/file-inventory.js +25 -22
- package/dist/task/final-gate-fix.d.ts +74 -86
- package/dist/task/final-gate-fix.js +97 -116
- package/dist/task/final-gate-progress.d.ts +29 -46
- package/dist/task/final-gate-progress.js +40 -51
- package/dist/task/final-gate.d.ts +64 -97
- package/dist/task/final-gate.js +192 -199
- package/dist/task/fix-child.d.ts +21 -27
- package/dist/task/fix-child.js +21 -27
- package/dist/task/foreign-path.d.ts +6 -5
- package/dist/task/foreign-path.js +0 -0
- package/dist/task/frozen-conflict.d.ts +9 -10
- package/dist/task/frozen-conflict.js +61 -64
- package/dist/task/frozen-path-guard.d.ts +35 -14
- package/dist/task/frozen-path-guard.js +56 -39
- package/dist/task/gate-child.d.ts +27 -28
- package/dist/task/gate-child.js +37 -35
- package/dist/task/gate-deps.d.ts +34 -27
- package/dist/task/gate-deps.js +169 -159
- package/dist/task/gate-tally.d.ts +77 -80
- package/dist/task/gate-tally.js +65 -68
- package/dist/task/git-state-guard.d.ts +15 -11
- package/dist/task/git-state-guard.js +76 -66
- package/dist/task/impl-widget.d.ts +25 -16
- package/dist/task/impl-widget.js +27 -17
- package/dist/task/implementation-thinking.d.ts +33 -31
- package/dist/task/implementation-thinking.js +5 -6
- package/dist/task/implementation-turn.d.ts +34 -31
- package/dist/task/implementation-turn.js +29 -27
- package/dist/task/inline-markdown.d.ts +20 -7
- package/dist/task/inline-markdown.js +15 -6
- package/dist/task/launch-config-gap.js +25 -39
- package/dist/task/launch-contract.d.ts +18 -21
- package/dist/task/launch-contract.js +28 -30
- package/dist/task/launch-manifest.d.ts +6 -2
- package/dist/task/launch-manifest.js +35 -34
- package/dist/task/ledger.js +16 -14
- package/dist/task/lint-fix.d.ts +6 -8
- package/dist/task/lint-fix.js +67 -69
- package/dist/task/loop-detector.d.ts +9 -8
- package/dist/task/loop-detector.js +16 -12
- package/dist/task/mid-run-input.d.ts +17 -15
- package/dist/task/mid-run-input.js +17 -15
- package/dist/task/orchestrator.d.ts +24 -28
- package/dist/task/orchestrator.js +62 -64
- package/dist/task/orientation.d.ts +18 -23
- package/dist/task/orientation.js +24 -31
- package/dist/task/owned-freeze-conflict.d.ts +21 -20
- package/dist/task/owned-freeze-conflict.js +52 -85
- package/dist/task/owned-freeze-reassign.d.ts +40 -60
- package/dist/task/owned-freeze-reassign.js +41 -61
- package/dist/task/parsers.d.ts +4 -2
- package/dist/task/parsers.js +4 -4
- package/dist/task/phases.d.ts +41 -48
- package/dist/task/phases.js +180 -248
- package/dist/task/plan-io.d.ts +6 -7
- package/dist/task/plan-io.js +6 -7
- package/dist/task/plan-orchestrator.d.ts +10 -8
- package/dist/task/plan-orchestrator.js +14 -10
- package/dist/task/plan-prompts.d.ts +6 -5
- package/dist/task/plan-prompts.js +6 -5
- package/dist/task/plan-readonly.d.ts +4 -5
- package/dist/task/plan-readonly.js +4 -5
- package/dist/task/plan-rounds.d.ts +17 -29
- package/dist/task/plan-rounds.js +21 -34
- package/dist/task/plan-session.d.ts +58 -72
- package/dist/task/plan-session.js +61 -83
- package/dist/task/probe-gaming.d.ts +28 -27
- package/dist/task/probe-gaming.js +0 -0
- package/dist/task/prohibition-probe.d.ts +14 -16
- package/dist/task/prompts.d.ts +3 -4
- package/dist/task/prompts.js +17 -26
- package/dist/task/qa-transcript.d.ts +15 -22
- package/dist/task/qa-transcript.js +15 -21
- package/dist/task/question-box.d.ts +17 -13
- package/dist/task/question-box.js +19 -15
- package/dist/task/question-dedup.d.ts +6 -7
- package/dist/task/question-dedup.js +13 -14
- package/dist/task/question-dialog.d.ts +22 -32
- package/dist/task/question-dialog.js +22 -32
- package/dist/task/question-source.d.ts +18 -44
- package/dist/task/question-source.js +22 -51
- package/dist/task/refuted-constraint.d.ts +11 -31
- package/dist/task/refuted-constraint.js +27 -51
- package/dist/task/regenerable-artifacts.d.ts +12 -31
- package/dist/task/regenerable-artifacts.js +12 -31
- package/dist/task/render-check.d.ts +11 -22
- package/dist/task/render-check.js +33 -46
- package/dist/task/repo-health-check.d.ts +10 -14
- package/dist/task/repo-health-check.js +17 -23
- package/dist/task/requirements.d.ts +38 -71
- package/dist/task/requirements.js +78 -126
- package/dist/task/research-fanout-budget.d.ts +51 -88
- package/dist/task/research-fanout-budget.js +51 -88
- package/dist/task/research-worker.d.ts +33 -36
- package/dist/task/research-worker.js +39 -61
- package/dist/task/resume-gap.d.ts +14 -15
- package/dist/task/root-cause-repair.d.ts +9 -9
- package/dist/task/root-cause-repair.js +28 -40
- package/dist/task/run-bracket.d.ts +10 -13
- package/dist/task/run-end.d.ts +12 -22
- package/dist/task/run-end.js +8 -16
- package/dist/task/run-final-gate.d.ts +19 -21
- package/dist/task/run-final-gate.js +62 -80
- package/dist/task/runner-globs.d.ts +12 -13
- package/dist/task/runner-globs.js +12 -13
- package/dist/task/runner-resolve.d.ts +9 -9
- package/dist/task/runner-resolve.js +22 -23
- package/dist/task/script-escape.d.ts +10 -12
- package/dist/task/script-escape.js +13 -14
- package/dist/task/serve-entry.d.ts +1 -1
- package/dist/task/serve-entry.js +22 -25
- package/dist/task/service-blocks.js +4 -2
- package/dist/task/shipped-source.d.ts +11 -29
- package/dist/task/shipped-source.js +11 -29
- package/dist/task/skip-escape.js +10 -14
- package/dist/task/spec-urls.d.ts +26 -65
- package/dist/task/spec-urls.js +26 -65
- package/dist/task/spec-validation.d.ts +17 -20
- package/dist/task/spec-validation.js +17 -20
- package/dist/task/stall-detector.d.ts +23 -30
- package/dist/task/stall-detector.js +23 -30
- package/dist/task/stream-watchdog.d.ts +14 -12
- package/dist/task/stream-watchdog.js +14 -12
- package/dist/task/substitution-probe.d.ts +17 -20
- package/dist/task/substitution-probe.js +17 -20
- package/dist/task/task-gates.d.ts +36 -41
- package/dist/task/task-gates.js +95 -106
- package/dist/task/task-io.d.ts +4 -4
- package/dist/task/task-io.js +4 -4
- package/dist/task/task-parsers.js +4 -3
- package/dist/task/task-provenance.d.ts +2 -2
- package/dist/task/task-provenance.js +11 -13
- package/dist/task/task-types.d.ts +4 -3
- package/dist/task/terminal-outcome.d.ts +14 -16
- package/dist/task/terminal-outcome.js +12 -14
- package/dist/task/test-assembly.d.ts +13 -20
- package/dist/task/test-assembly.js +13 -20
- package/dist/task/timings.d.ts +5 -3
- package/dist/task/timings.js +5 -3
- package/dist/task/title-label.d.ts +9 -4
- package/dist/task/title-label.js +9 -4
- package/dist/task/type-only-answer.d.ts +44 -52
- package/dist/task/type-only-answer.js +44 -52
- package/dist/task/unfailable-command.d.ts +18 -24
- package/dist/task/unfailable-command.js +21 -27
- package/dist/task/unknown-routing.d.ts +10 -4
- package/dist/task/unknown-routing.js +10 -4
- package/dist/task/user-directives.d.ts +5 -8
- package/dist/task/user-directives.js +5 -8
- package/dist/task/verify-quality.d.ts +18 -22
- package/dist/task/verify-quality.js +45 -46
- package/dist/task/verify-reconcile.d.ts +15 -10
- package/dist/task/verify-reconcile.js +45 -43
- package/dist/task/verify-resolution.d.ts +24 -20
- package/dist/task/verify-resolution.js +51 -50
- package/dist/task/verify-work.d.ts +59 -66
- package/dist/task/verify-work.js +101 -138
- package/dist/task/widget.d.ts +15 -14
- package/dist/task/widget.js +22 -17
- package/dist/task/wiring-claims.d.ts +25 -32
- package/dist/task/wiring-claims.js +30 -35
- package/dist/task/write-guard.d.ts +39 -39
- package/dist/task/write-guard.js +48 -51
- package/dist/task/yolo.d.ts +34 -30
- package/dist/task/yolo.js +42 -37
- package/dist/workers/abstention.d.ts +21 -41
- package/dist/workers/abstention.js +27 -48
- package/dist/workers/brave-search.d.ts +4 -3
- package/dist/workers/brave-search.js +5 -2
- package/dist/workers/brave-warning.d.ts +7 -4
- package/dist/workers/brave-warning.js +19 -7
- package/dist/workers/ddg-search.d.ts +6 -6
- package/dist/workers/ddg-search.js +18 -12
- package/dist/workers/docs-cache.js +5 -2
- package/dist/workers/docs-chunk.d.ts +30 -37
- package/dist/workers/docs-chunk.js +37 -41
- package/dist/workers/docs-core.d.ts +28 -44
- package/dist/workers/docs-core.js +25 -44
- package/dist/workers/docs-index.js +4 -3
- package/dist/workers/docs-lookup.d.ts +15 -22
- package/dist/workers/docs-lookup.js +12 -21
- package/dist/workers/docs-project.d.ts +15 -9
- package/dist/workers/docs-project.js +17 -10
- package/dist/workers/docs-resolve.d.ts +19 -20
- package/dist/workers/docs-resolve.js +35 -32
- package/dist/workers/docs-retrieve.d.ts +5 -6
- package/dist/workers/docs-retrieve.js +18 -15
- package/dist/workers/exa-search.d.ts +9 -6
- package/dist/workers/exa-search.js +23 -12
- package/dist/workers/fetch-core.d.ts +13 -16
- package/dist/workers/fetch-core.js +23 -23
- package/dist/workers/focused-extractor.d.ts +12 -12
- package/dist/workers/focused-extractor.js +16 -19
- package/dist/workers/html-clean.js +24 -14
- package/dist/workers/http-request.d.ts +28 -20
- package/dist/workers/http-request.js +22 -17
- package/dist/workers/npm-version.d.ts +28 -11
- package/dist/workers/npm-version.js +24 -15
- package/dist/workers/phantom-imports.d.ts +15 -12
- package/dist/workers/phantom-imports.js +30 -24
- package/dist/workers/pi-worker-core.d.ts +86 -54
- package/dist/workers/pi-worker-core.js +112 -112
- package/dist/workers/pi-worker-docs.d.ts +24 -19
- package/dist/workers/pi-worker-docs.js +67 -76
- package/dist/workers/pi-worker-fetch.d.ts +7 -3
- package/dist/workers/pi-worker-fetch.js +27 -19
- package/dist/workers/pi-worker-search.js +12 -8
- package/dist/workers/pi-worker.d.ts +9 -4
- package/dist/workers/pi-worker.js +23 -10
- package/dist/workers/reasoning-warning.d.ts +18 -17
- package/dist/workers/reasoning-warning.js +22 -20
- package/dist/workers/research-cache.js +50 -78
- package/dist/workers/search-core.js +7 -5
- package/dist/workers/search-types.d.ts +10 -9
- package/dist/workers/search-types.js +9 -8
- package/dist/workers/session-hint.d.ts +13 -14
- package/dist/workers/session-hint.js +8 -9
- package/dist/workers/shared.d.ts +21 -25
- package/dist/workers/shared.js +0 -0
- package/dist/workers/single-read-extension.d.ts +14 -7
- package/dist/workers/single-read-extension.js +14 -7
- package/dist/workers/single-read-guard.d.ts +25 -28
- package/dist/workers/single-read-guard.js +32 -32
- package/dist/workers/typeonly-log.d.ts +12 -9
- package/dist/workers/typeonly-log.js +29 -33
- package/dist/workers/worker-channels.d.ts +15 -23
- package/dist/workers/worker-channels.js +15 -23
- package/dist/workers/worker-failure.d.ts +38 -46
- package/dist/workers/worker-failure.js +31 -39
- package/dist/workers/worker-kill.d.ts +25 -26
- package/dist/workers/worker-kill.js +16 -19
- package/dist/workers/worker-profiles.d.ts +43 -53
- package/dist/workers/worker-profiles.js +30 -38
- package/package.json +10 -8
package/dist/task/gate-deps.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* gate-deps — builds the concrete {@link GateDeps} (verify / enforce / recommend /
|
|
3
|
-
* commit / revert) that the post-implementation gate sequence drives.
|
|
3
|
+
* commit / revert) that the post-implementation gate sequence drives. Both
|
|
4
|
+
* /task-auto and the single /task command construct the gate children through it,
|
|
5
|
+
* so they are identical.
|
|
4
6
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* `runTask` (the AUTOFIX re-run) is INJECTED rather than imported, which is what
|
|
8
|
+
* keeps the graph acyclic: this module names the orchestrators only in comments,
|
|
9
|
+
* while orchestrator.ts, auto-orchestrator.ts and plan-orchestrator.ts all import
|
|
10
|
+
* from here.
|
|
9
11
|
*
|
|
10
|
-
* The gate children
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* The gate children run on the `gate` worker profile: no wall-clock timeout, and
|
|
13
|
+
* the path-revisit loop rule disabled because re-running the same check IS the
|
|
14
|
+
* job, leaving only the exact-match rule. Each gets a status widget and a per-gate
|
|
15
|
+
* debug log under `.pi-tasks/`.
|
|
16
|
+
*
|
|
17
|
+
* NONE of them is read-only by capability. `VERIFY_TOOLS` and `RESOLUTION_TOOLS`
|
|
18
|
+
* are both `read,bash` and `ENFORCE_TOOLS` is `read,edit`, so verify and recommend
|
|
19
|
+
* are read-only by CONTRACT only — which is exactly why GATE_CHILD_KINDS marks
|
|
20
|
+
* those two `guarded` and the git-state guard restores what they move.
|
|
15
21
|
*/
|
|
16
22
|
import { existsSync, readFileSync } from 'node:fs';
|
|
17
23
|
import * as fsp from 'node:fs/promises';
|
|
@@ -47,12 +53,15 @@ import { makeDebugAppender } from './debug-log.js';
|
|
|
47
53
|
import { startAutoLoader } from './widget.js';
|
|
48
54
|
import { ChildStatus } from './child-status.js';
|
|
49
55
|
import { makeGateChild } from './gate-child.js';
|
|
50
|
-
/** Max chars of a tool result kept in the gate debug log
|
|
56
|
+
/** Max chars of a tool result kept in the gate debug log. */
|
|
51
57
|
const TOOL_RESULT_LOG_LIMIT = 300;
|
|
52
58
|
/**
|
|
53
59
|
* One-line, tail-kept, whitespace-flattened summary of a tool's output for the gate
|
|
54
|
-
* debug log. The TAIL is kept
|
|
55
|
-
*
|
|
60
|
+
* debug log. The TAIL is kept — a bind failure, a final status or an assertion
|
|
61
|
+
* lands at the END of the output — with a leading ellipsis when truncated.
|
|
62
|
+
* Measured: all-whitespace and empty input both give "(no output)", internal
|
|
63
|
+
* newlines collapse to single spaces, and a 410-char input comes back 301 chars
|
|
64
|
+
* long, starting `…` and ending on the input's last characters.
|
|
56
65
|
*/
|
|
57
66
|
export function truncateToolResult(text, limit = TOOL_RESULT_LOG_LIMIT) {
|
|
58
67
|
const flat = text.replace(/\s+/g, ' ').trim();
|
|
@@ -67,11 +76,14 @@ const EXCLUDE_TASKS_DIR = ':(exclude).pi-tasks';
|
|
|
67
76
|
*
|
|
68
77
|
* `parseAddedLines` reads the file out of the `+++ b/…` header, but the prefix is
|
|
69
78
|
* user-configurable: `diff.mnemonicPrefix=true` emits `i/` and `w/` instead of
|
|
70
|
-
* `a/` and `b/`, and `diff.noprefix=true` emits none.
|
|
71
|
-
*
|
|
72
|
-
* `
|
|
73
|
-
*
|
|
74
|
-
*
|
|
79
|
+
* `a/` and `b/`, and `diff.noprefix=true` emits none. Not hypothetical: this
|
|
80
|
+
* machine has `diff.mnemonicPrefix=true` set globally, and measured on git 2.55.0,
|
|
81
|
+
* an unpinned `git diff HEAD` here emits `--- c/src/app.ts` / `+++ w/src/app.ts`
|
|
82
|
+
* (a bare `git diff` emits `i/` and `w/`). Every added line would then be
|
|
83
|
+
* attributed to `w/src/app.ts`, a path that exists nowhere, and the probe-gaming
|
|
84
|
+
* and sandbox-path probes would silently read a diff of files not in the repo.
|
|
85
|
+
* With these two arguments the header comes back as `a/` and `b/` under
|
|
86
|
+
* mnemonicPrefix and under noprefix alike.
|
|
75
87
|
*/
|
|
76
88
|
const DIFF_PREFIX_ARGS = ['--src-prefix=a/', '--dst-prefix=b/'];
|
|
77
89
|
const splitLines = (s) => s
|
|
@@ -116,7 +128,7 @@ export async function collectChangedFiles(cwd, signal) {
|
|
|
116
128
|
}
|
|
117
129
|
/**
|
|
118
130
|
* Collect the task's added lines WITH CONTENT (path + text) for the probe-gaming
|
|
119
|
-
* probe
|
|
131
|
+
* probe, which needs the actual line text the numstat-shape collector omits.
|
|
120
132
|
* Pre-commit the work is the tree-vs-HEAD diff plus untracked files (read whole, as
|
|
121
133
|
* all-added); on the post-enforce re-verify the tree is clean, so fall back to the
|
|
122
134
|
* last commit's diff. Failures degrade to an empty list — the probe is a sharpener,
|
|
@@ -143,10 +155,10 @@ export async function collectAddedLines(cwd, signal) {
|
|
|
143
155
|
return lines;
|
|
144
156
|
}
|
|
145
157
|
/**
|
|
146
|
-
* Deterministic sandbox-path-leak pass (see foreign-path.ts
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
158
|
+
* Deterministic sandbox-path-leak pass (see foreign-path.ts): find absolute paths
|
|
159
|
+
* the task committed that resolve nowhere on this machine while the real file sits
|
|
160
|
+
* in the repo, REPAIR the ones whose relative form provably resolves, and return
|
|
161
|
+
* verify findings for whatever is left.
|
|
150
162
|
*
|
|
151
163
|
* The repair runs here, before the verify child, for the same reason lint-fix
|
|
152
164
|
* does: the defect is mechanical and the correct target is already known, so
|
|
@@ -176,9 +188,8 @@ export async function collectForeignPathFindings(cwd, signal, logDebug) {
|
|
|
176
188
|
/** Manifests whose `scripts` the check-script scanner understands. */
|
|
177
189
|
const MANIFEST_RE = /(^|\/)package\.json$/;
|
|
178
190
|
/**
|
|
179
|
-
* Deterministic neutered-check-script pass (see script-escape.ts
|
|
180
|
-
*
|
|
181
|
-
* task changed.
|
|
191
|
+
* Deterministic neutered-check-script pass (see script-escape.ts): check-class
|
|
192
|
+
* scripts that cannot report failure, in a manifest THIS task changed.
|
|
182
193
|
*
|
|
183
194
|
* Scoped to manifests the task touched, so the finding lands on the task that
|
|
184
195
|
* authored the script rather than being re-served to every later task. A script
|
|
@@ -219,10 +230,9 @@ async function readOrNull(cwd, rel) {
|
|
|
219
230
|
}
|
|
220
231
|
}
|
|
221
232
|
/**
|
|
222
|
-
* Deterministic test-runner glob-collision pass (see runner-globs.ts
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
* and dies during collection.
|
|
233
|
+
* Deterministic test-runner glob-collision pass (see runner-globs.ts): the manifest
|
|
234
|
+
* declares both `bun test` and `playwright test` without a provably disjoint file
|
|
235
|
+
* set, so `bun test` imports the playwright specs and dies during collection.
|
|
226
236
|
*
|
|
227
237
|
* Whole-repo rather than diff-scoped, unlike the neutered-script probe: a collision
|
|
228
238
|
* is a property of the PAIR of declarations, and the task that completes the pair is
|
|
@@ -267,10 +277,15 @@ export async function collectTreeChanges(cwd, signal) {
|
|
|
267
277
|
return r.exitCode === 0 ? parseTreeChanges(r.stdout) : { modified: [], deleted: [], added: [] };
|
|
268
278
|
}
|
|
269
279
|
/**
|
|
270
|
-
* Build output directories declared by the project's OWN build commands
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
280
|
+
* Build output directories declared by the project's OWN build commands, so the
|
|
281
|
+
* ignored-write exemption follows the real tooling instead of a name list.
|
|
282
|
+
*
|
|
283
|
+
* The pattern is `--outdir` or `--out-dir`, LOWERCASE, followed by `=` or a space.
|
|
284
|
+
* Measured on a manifest declaring all four spellings: `--outdir=./dist/` yields
|
|
285
|
+
* `dist` and `--out-dir build` yields `build`, while `--outDir out` (tsc's
|
|
286
|
+
* spelling) yields nothing and a bare `--outdir -` is dropped by the leading-dash
|
|
287
|
+
* guard. Best-effort: an unreadable or non-JSON manifest contributes nothing and
|
|
288
|
+
* the name-list fallback in classifyIgnoredPath applies.
|
|
274
289
|
*/
|
|
275
290
|
export function parseBuildOutdirs(cwd) {
|
|
276
291
|
let raw;
|
|
@@ -300,17 +315,18 @@ export function parseBuildOutdirs(cwd) {
|
|
|
300
315
|
return [...out];
|
|
301
316
|
}
|
|
302
317
|
/**
|
|
303
|
-
* IGNORED-PATH CHANNEL (
|
|
318
|
+
* IGNORED-PATH CHANNEL (see write-guard.ts). A fingerprint of every
|
|
304
319
|
* ACTIONABLE ignored path (`git status --porcelain --ignored=matching`, minus
|
|
305
320
|
* build output / node_modules / .pi-tasks / .git), taken before and after a
|
|
306
321
|
* write-capable gate child so its writes to files git never reports are
|
|
307
322
|
* attributable to it.
|
|
308
323
|
*
|
|
309
324
|
* `--ignored=matching` collapses a wholly-ignored directory into ONE entry, which
|
|
310
|
-
* is what keeps this cheap:
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
325
|
+
* is what keeps this cheap: run against a repo ignoring `logs/`, `node_modules/`
|
|
326
|
+
* and `.env`, with files in all three, it reports exactly three lines —
|
|
327
|
+
* `!! .env`, `!! logs/`, `!! node_modules/` — never one per file. Every failure
|
|
328
|
+
* mode degrades to `{}` (no git, a git that rejects the flag, an unreadable path),
|
|
329
|
+
* so the gate behaves as if the channel were absent.
|
|
314
330
|
*/
|
|
315
331
|
export async function collectIgnoredSnapshot(cwd, signal) {
|
|
316
332
|
const r = await git(cwd, ['status', '--porcelain', '--ignored=matching', '--', '.', EXCLUDE_TASKS_DIR], signal);
|
|
@@ -356,9 +372,11 @@ export async function gatePassesWithoutIgnored(cwd, paths, runGate, log) {
|
|
|
356
372
|
try {
|
|
357
373
|
for (const rel of paths) {
|
|
358
374
|
// `--ignored=matching` reports a wholly-ignored DIRECTORY with a trailing
|
|
359
|
-
// slash
|
|
360
|
-
//
|
|
361
|
-
//
|
|
375
|
+
// slash — measured, it prints `logs/`, not `logs`. Left on,
|
|
376
|
+
// `path.join('/repo', 'logs/')` is `/repo/logs/`, so the probe target
|
|
377
|
+
// becomes `/repo/logs/.pi-gate-probe` — a path INSIDE the directory, and
|
|
378
|
+
// the rename is a move-into-itself that answers null for every directory
|
|
379
|
+
// entry. Stripped, the target is the sibling `/repo/logs.pi-gate-probe`.
|
|
362
380
|
const from = path.join(cwd, rel.replace(/\/+$/, ''));
|
|
363
381
|
const to = `${from}.pi-gate-probe`;
|
|
364
382
|
try {
|
|
@@ -425,9 +443,9 @@ async function readRepoFile(cwd, rel) {
|
|
|
425
443
|
}
|
|
426
444
|
}
|
|
427
445
|
/**
|
|
428
|
-
* Deterministic test-assembly probe input
|
|
429
|
-
*
|
|
430
|
-
*
|
|
446
|
+
* Deterministic test-assembly probe input: read the task's own changed TEST files
|
|
447
|
+
* plus the repo's tracked source files, and return the finding lines naming any
|
|
448
|
+
* test that rebuilds a production assembly it never imports.
|
|
431
449
|
* Pure import-graph shape; failures degrade to no findings (the probe is a sharpener,
|
|
432
450
|
* never a blocker). `changed` is the already-collected task diff, reused so the probe
|
|
433
451
|
* costs one extra tracked-file listing, not a second diff.
|
|
@@ -464,7 +482,7 @@ export async function collectTestAssemblyFindings(cwd, changed, signal) {
|
|
|
464
482
|
* section, and an unreadable task file is the same case — both are null, and every
|
|
465
483
|
* caller already treats null as "nothing to hold the work to" (verify no-ops,
|
|
466
484
|
* frozen paths are empty, recommend falls back to the title). Never throws. This
|
|
467
|
-
*
|
|
485
|
+
* would otherwise be the same four-line try/catch at four gate sites.
|
|
468
486
|
*/
|
|
469
487
|
export async function readSpecForVerification(cwd, taskId) {
|
|
470
488
|
try {
|
|
@@ -504,41 +522,38 @@ export function buildVerifyProbes(params) {
|
|
|
504
522
|
return Promise.resolve([]);
|
|
505
523
|
return collectChangedFiles(cwd, signal).then(files => findProhibitionViolations(banned, files));
|
|
506
524
|
},
|
|
507
|
-
// Deterministic cross-task deletion probe
|
|
508
|
-
//
|
|
509
|
-
//
|
|
510
|
-
//
|
|
511
|
-
//
|
|
525
|
+
// Deterministic cross-task deletion probe: tracked files this task's
|
|
526
|
+
// diff DELETES whose introducing commit belongs to a DIFFERENT task —
|
|
527
|
+
// a sibling's committed deliverable destroyed, typically to green a
|
|
528
|
+
// check. Injected under rule 4d and carried on a FAIL so an ACCEPT
|
|
529
|
+
// records durable debts.
|
|
512
530
|
crossTaskDeletion: () => collectTaskTreeChanges(cwd, signal).then(changes => findCrossTaskDeletions(changes, taskId, rel => taskThatIntroduced(cwd, rel))),
|
|
513
|
-
// Deterministic probe-gaming probe
|
|
514
|
-
//
|
|
515
|
-
//
|
|
516
|
-
//
|
|
531
|
+
// Deterministic probe-gaming probe: added lines whose stated purpose
|
|
532
|
+
// is to make a check pass rather than meet the requirement ("return
|
|
533
|
+
// 401 so the verification test passes") become rule-4c findings, so
|
|
534
|
+
// the child verifies the real requirement and not the check.
|
|
517
535
|
probeGaming: () => collectAddedLines(cwd, signal).then(findProbeGaming),
|
|
518
|
-
// Deterministic sandbox-path-leak probe
|
|
519
|
-
//
|
|
520
|
-
//
|
|
521
|
-
//
|
|
522
|
-
//
|
|
523
|
-
// that
|
|
524
|
-
// caught it report nothing rather than failing.
|
|
536
|
+
// Deterministic sandbox-path-leak probe: absolute paths committed
|
|
537
|
+
// from the authoring child's own environment (`/workspace/src/shared`)
|
|
538
|
+
// that resolve nowhere here. Repaired deterministically where the
|
|
539
|
+
// relative form provably resolves; the remainder is injected under
|
|
540
|
+
// rule 4e, whose point is that such a path breaks the BUILD — so the
|
|
541
|
+
// checks that would have caught it report nothing rather than failing.
|
|
525
542
|
foreignPath: () => collectForeignPathFindings(cwd, signal, log),
|
|
526
|
-
// Deterministic neutered-check-script probe
|
|
527
|
-
//
|
|
528
|
-
//
|
|
529
|
-
//
|
|
530
|
-
// script — it passes, which IS the defect.
|
|
543
|
+
// Deterministic neutered-check-script probe: a check script this task
|
|
544
|
+
// authored that cannot fail (`… || true`, an inverted-grep launder).
|
|
545
|
+
// Injected under rule 4f, because the child cannot find this by
|
|
546
|
+
// running the script — it passes, which IS the defect.
|
|
531
547
|
scriptEscape: () => collectScriptEscapeFindings(cwd, signal),
|
|
532
|
-
// Deterministic runner glob-collision probe
|
|
533
|
-
//
|
|
534
|
-
//
|
|
535
|
-
//
|
|
536
|
-
// not look like a test failure.
|
|
548
|
+
// Deterministic runner glob-collision probe: both `bun test` and
|
|
549
|
+
// `playwright test` declared with no proof their file sets are
|
|
550
|
+
// disjoint. Injected under rule 4g — the collision kills the suite
|
|
551
|
+
// during COLLECTION, which does not look like a test failure.
|
|
537
552
|
runnerGlob: () => collectRunnerGlobFindings(cwd),
|
|
538
|
-
// Deterministic test-assembly probe
|
|
539
|
-
//
|
|
540
|
-
//
|
|
541
|
-
//
|
|
553
|
+
// Deterministic test-assembly probe: authored test files that rebuild
|
|
554
|
+
// production wiring — importing the leaf modules the shipped entry
|
|
555
|
+
// composes and assembling their own copy — become rule-3f findings,
|
|
556
|
+
// so the child drives the REAL assembly and not the copy.
|
|
542
557
|
testAssembly: () => collectChangedFiles(cwd, signal).then(changed => collectTestAssemblyFindings(cwd, changed, signal))
|
|
543
558
|
};
|
|
544
559
|
}
|
|
@@ -551,10 +566,9 @@ export function buildVerifyProbes(params) {
|
|
|
551
566
|
*/
|
|
552
567
|
export function buildGateDeps(params) {
|
|
553
568
|
const { signal, parentContextWindow, runTask } = params;
|
|
554
|
-
// A/B seam
|
|
555
|
-
//
|
|
556
|
-
//
|
|
557
|
-
// SAME binary rather than against a remembered baseline. Unset in every real run.
|
|
569
|
+
// A/B seam, same shape as CANCEL_AB_ARM in cancel-points.ts: drop the loader
|
|
570
|
+
// across the deterministic stage so the dead air can be measured in the SAME
|
|
571
|
+
// binary. Unset in every real run.
|
|
558
572
|
const deadAirBaseline = process.env.DEADAIR_AB_ARM === 'baseline';
|
|
559
573
|
// ONE live status for every gate child, so the widget mirrors the running
|
|
560
574
|
// child's latest output line and context usage exactly like the single-task
|
|
@@ -565,9 +579,10 @@ export function buildGateDeps(params) {
|
|
|
565
579
|
// child run (see git-state-guard.ts). runWorkVerification reads this through its
|
|
566
580
|
// mutationCheck dep to discard a verdict computed on a mutated tree.
|
|
567
581
|
let lastGuardReconcile = null;
|
|
568
|
-
// Restore tracked files to HEAD and drop files a pass created
|
|
569
|
-
// trail
|
|
570
|
-
//
|
|
582
|
+
// Restore tracked files to HEAD and drop files a pass created. The `.pi-tasks`
|
|
583
|
+
// trail and log writes made during the pass survive both: the checkout excludes
|
|
584
|
+
// that directory by pathspec and the clean excludes it with `-e`. Shared by the
|
|
585
|
+
// enforce pre-commit gate (discardEdits) and the final-gate autofix guards.
|
|
571
586
|
const discardTreeEdits = async (cwd2) => {
|
|
572
587
|
await git(cwd2, ['checkout', '--', '.', EXCLUDE_TASKS_DIR], signal);
|
|
573
588
|
await git(cwd2, ['clean', '-fd', '-e', '.pi-tasks'], signal);
|
|
@@ -604,7 +619,7 @@ export function buildGateDeps(params) {
|
|
|
604
619
|
// Durable per-task gate trail: every verdict/decision lands in the task
|
|
605
620
|
// file's `## gates` section so gate behavior is auditable from artifacts.
|
|
606
621
|
record: (cwd2, taskId, line) => appendGateRecord(cwd2, taskId, line),
|
|
607
|
-
// Durable defect ledger under
|
|
622
|
+
// Durable defect ledger under `.pi-tasks/` (survives discardEdits): every
|
|
608
623
|
// recorded class — accepted, yolo-accepted, enforce-revert, enforce-kept,
|
|
609
624
|
// frozen-blocked, cross-task-deletion, root-cause — lands here with its
|
|
610
625
|
// origin, and the final integration gate re-checks each one at run end.
|
|
@@ -643,10 +658,10 @@ export function buildGateDeps(params) {
|
|
|
643
658
|
const c = parseTreeChanges(r.stdout);
|
|
644
659
|
return [...c.modified, ...c.added, ...c.deleted];
|
|
645
660
|
}
|
|
646
|
-
// `enforce-commit` is HEAD ALONE — at the enforce
|
|
647
|
-
// the ENFORCE commit, and that commit's own diff
|
|
648
|
-
// that can answer "could reverting this repair
|
|
649
|
-
//
|
|
661
|
+
// `enforce-commit` is HEAD ALONE (`log -n 1`) — at the enforce
|
|
662
|
+
// differential HEAD is the ENFORCE commit, and that commit's own diff
|
|
663
|
+
// is the only file set that can answer "could reverting this repair
|
|
664
|
+
// the failure?". Every other scope reads the last two commits.
|
|
650
665
|
const r = await git(cwd2, [
|
|
651
666
|
'log',
|
|
652
667
|
'-n',
|
|
@@ -690,19 +705,18 @@ export function buildGateDeps(params) {
|
|
|
690
705
|
cwd: cwd2,
|
|
691
706
|
signal,
|
|
692
707
|
mode,
|
|
693
|
-
// Run the worker child
|
|
694
|
-
//
|
|
695
|
-
//
|
|
696
|
-
// research-worker guards mislabel
|
|
697
|
-
//
|
|
698
|
-
//
|
|
708
|
+
// Run the worker child with no loop detector and no wall clock. This
|
|
709
|
+
// pass reworks files in place until every violation is fixed and
|
|
710
|
+
// legitimately reads and edits the same file many times, which the
|
|
711
|
+
// research-worker guards would mislabel as a runaway.
|
|
712
|
+
// classifyEnforceChildFailure still blocks on a real failure — a
|
|
713
|
+
// non-zero exit, a leaked tool call — or a user cancel.
|
|
699
714
|
//
|
|
700
|
-
//
|
|
701
|
-
//
|
|
702
|
-
//
|
|
703
|
-
// tool-result logging,
|
|
704
|
-
//
|
|
705
|
-
// unobservable.
|
|
715
|
+
// The enforce child goes through the same makeGateChild call as
|
|
716
|
+
// every other kind; what differs is its GATE_CHILD_KINDS row — no
|
|
717
|
+
// git-state guard, because editing is this pass's job, no
|
|
718
|
+
// tool-result logging, and its own end marker. Its debug log is
|
|
719
|
+
// separate because the enforce child is otherwise unobservable.
|
|
706
720
|
runChild: gateChild(enforceCtx, cwd2, taskTitle, 'enforce', 'enforce-debug.log')
|
|
707
721
|
});
|
|
708
722
|
},
|
|
@@ -715,15 +729,14 @@ export function buildGateDeps(params) {
|
|
|
715
729
|
// runWorkVerification treats a null spec as a no-op pass.
|
|
716
730
|
const spec = await readSpecForVerification(cwd2, taskId);
|
|
717
731
|
// DEAD AIR (the reason this loader exists). The gate's DETERMINISTIC
|
|
718
|
-
// stage — repo health plus
|
|
719
|
-
// and the child's own loader only starts once the
|
|
720
|
-
// widget
|
|
721
|
-
//
|
|
722
|
-
//
|
|
723
|
-
//
|
|
724
|
-
//
|
|
725
|
-
//
|
|
726
|
-
// deterministic stage and the child — so the run is never silent.
|
|
732
|
+
// stage — repo health plus the nine PROBE_ADAPTERS rows — runs before
|
|
733
|
+
// the verify child, and the child's own loader only starts once the
|
|
734
|
+
// child does. The implementation widget is cleared at `agent_end`, so
|
|
735
|
+
// without this the screen has no spinner, no clock and no line for the
|
|
736
|
+
// whole stage. A `verifying…` notify would not help: pi-tui schedules
|
|
737
|
+
// every render through `process.nextTick` (pi-tui/dist/tui.js), so a
|
|
738
|
+
// synchronous health check starves the render entirely. One loader spans
|
|
739
|
+
// the WHOLE gate — the deterministic stage and the child.
|
|
727
740
|
const gateStartedAt = Date.now();
|
|
728
741
|
let stageLine;
|
|
729
742
|
// `track` clears the PREVIOUS child's trailer before the loader goes
|
|
@@ -757,15 +770,13 @@ export function buildGateDeps(params) {
|
|
|
757
770
|
},
|
|
758
771
|
// Deterministic whole-repo static-analysis gate — runs the project's
|
|
759
772
|
// own lint/typecheck and fails on a real non-zero exit, independent of
|
|
760
|
-
// the model-authored VERIFY block
|
|
761
|
-
//
|
|
762
|
-
//
|
|
763
|
-
//
|
|
764
|
-
//
|
|
765
|
-
//
|
|
766
|
-
//
|
|
767
|
-
// made `DEADAIR_AB_ARM=baseline` silently uncancellable and
|
|
768
|
-
// mute. The arm's real difference is the LOADER, above.
|
|
773
|
+
// the model-authored VERIFY block, which may not lint at all. ASYNC,
|
|
774
|
+
// so the lint does not starve pi-tui's nextTick-scheduled renders.
|
|
775
|
+
//
|
|
776
|
+
// ONE call, both arms. A baseline arm that dropped the signal or the
|
|
777
|
+
// progress hook here would be uncancellable and mute for reasons
|
|
778
|
+
// unrelated to the thing under test. The arm's only difference is
|
|
779
|
+
// the LOADER, above.
|
|
769
780
|
repoHealth: () => runRepoHealthCheck(cwd2, {
|
|
770
781
|
signal,
|
|
771
782
|
onCommand: c => {
|
|
@@ -786,23 +797,23 @@ export function buildGateDeps(params) {
|
|
|
786
797
|
// when the mutation touched graded state (verdictTainted). A child
|
|
787
798
|
// that merely left test-runner output behind (test-results/,
|
|
788
799
|
// playwright-report/ …) judged an equivalent tree; its verdict stands
|
|
789
|
-
// and the artifacts
|
|
790
|
-
//
|
|
800
|
+
// and the artifacts are still cleaned. See git-state-guard.ts for
|
|
801
|
+
// which mutations count as tainting.
|
|
791
802
|
mutationCheck: () => lastGuardReconcile?.verdictTainted ?
|
|
792
803
|
{ mutated: true, detail: lastGuardReconcile.actions.join('; ') }
|
|
793
804
|
: { mutated: false, detail: '' },
|
|
794
|
-
// Per-run environment-facts cache under
|
|
805
|
+
// Per-run environment-facts cache under `.pi-tasks/` (survives
|
|
795
806
|
// discardEdits): earlier children's discoveries save this child
|
|
796
807
|
// the re-archaeology; its own ENV-NOTE lines are stored for the
|
|
797
808
|
// next one, stamped with this task's id as their origin so a
|
|
798
809
|
// later child sees a cited fact is second-hand and must
|
|
799
|
-
// re-validate before excusing a failure
|
|
800
|
-
//
|
|
810
|
+
// re-validate before excusing a failure. Facts only — verdict
|
|
811
|
+
// rules unaffected.
|
|
801
812
|
envNotes: {
|
|
802
813
|
read: () => readEnvNotes(cwd2),
|
|
803
814
|
append: notes => appendEnvNotes(cwd2, notes, taskId)
|
|
804
815
|
},
|
|
805
|
-
// Per-run cross-slice contract registry under
|
|
816
|
+
// Per-run cross-slice contract registry under `.pi-tasks/`: the
|
|
806
817
|
// verbatim interface facts the design pins that multiple slices
|
|
807
818
|
// share, so the verify child checks this slice's boundary against
|
|
808
819
|
// them. Empty on single-`/task` runs or a design with no shared
|
|
@@ -811,12 +822,12 @@ export function buildGateDeps(params) {
|
|
|
811
822
|
}));
|
|
812
823
|
},
|
|
813
824
|
lintFix: async (fixCtx, cwd2, taskTitle, taskId, failReason) => {
|
|
814
|
-
// Same frozen extraction the enforce guard and the verify rule-4b
|
|
815
|
-
//
|
|
816
|
-
//
|
|
817
|
-
//
|
|
818
|
-
//
|
|
819
|
-
//
|
|
825
|
+
// Same frozen extraction the enforce guard and the verify rule-4b probe
|
|
826
|
+
// consume. A linter's own error text can instruct an edit inside a
|
|
827
|
+
// spec-frozen file, so the lint-fix child must both KNOW the do-not-touch
|
|
828
|
+
// list and be mechanically denied it — knowing alone is not enough when
|
|
829
|
+
// the tool output is telling it otherwise. Spec unreadable → no frozen
|
|
830
|
+
// paths, and the guard degrades to a no-op.
|
|
820
831
|
const frozenPaths = frozenPathsFromSpec(await readSpecForVerification(cwd2, taskId));
|
|
821
832
|
return runBoundedLintFix({
|
|
822
833
|
cwd: cwd2,
|
|
@@ -829,20 +840,21 @@ export function buildGateDeps(params) {
|
|
|
829
840
|
return { exitCode: r.exitCode, stdout: r.stdout };
|
|
830
841
|
},
|
|
831
842
|
frozenPaths,
|
|
832
|
-
// Cross-task deletion guard
|
|
833
|
-
// is blind to a
|
|
834
|
-
// greens the lint and the pass returns ok.
|
|
835
|
-
//
|
|
836
|
-
// reports not-applied naming the owner.
|
|
843
|
+
// Cross-task deletion guard: the revert-guard only watches files the
|
|
844
|
+
// task had already dirtied, so it is blind to a CLEAN tracked sibling
|
|
845
|
+
// deliverable — deleting one greens the lint and the pass returns ok.
|
|
846
|
+
// Provenance is the discriminator: the guard restores the sibling's
|
|
847
|
+
// deleted file and reports not-applied, naming the owner.
|
|
837
848
|
currentTaskId: taskId,
|
|
838
849
|
introducedBy: rel => Promise.resolve(taskThatIntroduced(cwd2, rel))
|
|
839
850
|
});
|
|
840
851
|
},
|
|
841
852
|
// Deterministic static check + tree helpers for the enforce pre-commit gate.
|
|
842
|
-
//
|
|
843
|
-
//
|
|
844
|
-
//
|
|
845
|
-
//
|
|
853
|
+
// task-gates.ts calls it up to twice per task in `edit` mode — a baseline
|
|
854
|
+
// before the edit pass, and a differential check after it when edits were
|
|
855
|
+
// made. Each run is as long as the project's own lint, so it gets the same
|
|
856
|
+
// treatment as the verify-side run: async, under a live loader naming the
|
|
857
|
+
// command.
|
|
846
858
|
repoHealth: (healthCtx, cwd2, label) => {
|
|
847
859
|
const startedAt = Date.now();
|
|
848
860
|
let running;
|
|
@@ -880,28 +892,26 @@ export function buildGateDeps(params) {
|
|
|
880
892
|
discoverLabels: discoverGateCommandLabels,
|
|
881
893
|
discoverBodies: discoverGateCommandBodies,
|
|
882
894
|
discard: discardTreeEdits,
|
|
883
|
-
// WRITE-GUARD STACK
|
|
884
|
-
//
|
|
885
|
-
//
|
|
886
|
-
//
|
|
887
|
-
//
|
|
888
|
-
//
|
|
889
|
-
//
|
|
890
|
-
//
|
|
891
|
-
//
|
|
892
|
-
//
|
|
893
|
-
// it only when a run-GLOBAL freeze source exists (a design-level
|
|
894
|
-
// preserve registry), never a per-task union.
|
|
895
|
+
// WRITE-GUARD STACK. This child has free bash, so it needs one.
|
|
896
|
+
// Diff capture happens at the makeGateChild seam, keyed on the
|
|
897
|
+
// child's TOOLS; the deletion guard and the probe scan
|
|
898
|
+
// reject-and-discard inside runFinalGateAutofix. The frozen-path
|
|
899
|
+
// deny (FinalFixDeps.frozenPaths/revertFrozen) is deliberately NOT
|
|
900
|
+
// wired here: per-task fences are task-SCOPED — "this task must not
|
|
901
|
+
// touch a sibling's territory" — so their union across a run can
|
|
902
|
+
// fence off a file a legitimate whole-repo fix has to touch. Wire it
|
|
903
|
+
// only when a run-GLOBAL freeze source exists, never a per-task
|
|
904
|
+
// union.
|
|
895
905
|
treeChanges: () => collectTreeChanges(cwd2, signal),
|
|
896
906
|
probeScan: () => collectAddedLines(cwd2, signal).then(findProbeGaming),
|
|
897
|
-
// IGNORED-PATH CHANNEL
|
|
898
|
-
// `git status --porcelain`, which
|
|
899
|
-
//
|
|
900
|
-
//
|
|
901
|
-
//
|
|
902
|
-
// does not reject the write
|
|
903
|
-
// make a check run
|
|
904
|
-
// depend on it.
|
|
907
|
+
// IGNORED-PATH CHANNEL: every write guard above reads
|
|
908
|
+
// `git status --porcelain`, which does not report ignored paths, so
|
|
909
|
+
// a pass that greens a command by writing credentials into a
|
|
910
|
+
// gitignored `.env` is structurally invisible to all of them — and
|
|
911
|
+
// the gate would certify a PASS no fresh clone can reproduce. This
|
|
912
|
+
// does not reject the write; a local `.env` is often the only way to
|
|
913
|
+
// make a check run at all. It records it, and downgrades a PASS
|
|
914
|
+
// proven to depend on it.
|
|
905
915
|
ignoredSnapshot: () => collectIgnoredSnapshot(cwd2, signal),
|
|
906
916
|
...(ignoredKnown && ignoredKnown.length > 0 ? { ignoredKnown } : {}),
|
|
907
917
|
gateWithoutIgnored: paths => gatePassesWithoutIgnored(cwd2, paths, c => runFinalIntegrationGate(c, { signal }), makeDebugAppender(path.join(tasksDir(cwd2), 'final-gate-debug.log'))),
|