@mjasnikovs/pi-task 0.38.29 → 0.38.31
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/index.js +2 -0
- 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 +85 -16
- package/dist/shared/command-watchdog.js +115 -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 +192 -165
- 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 +124 -55
- package/dist/task/child-runner.js +298 -90
- 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 +16 -9
- package/dist/task/context-usage.js +16 -9
- 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 +30 -8
- 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 +36 -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-guards.d.ts +26 -0
- package/dist/task/implementation-guards.js +177 -0
- package/dist/task/implementation-thinking.d.ts +33 -31
- package/dist/task/implementation-thinking.js +5 -6
- package/dist/task/implementation-turn.d.ts +39 -31
- package/dist/task/implementation-turn.js +41 -28
- 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 +27 -8
- package/dist/task/loop-detector.js +38 -14
- 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 +89 -66
- 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 +196 -252
- 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 +29 -39
- package/dist/task/research-worker.js +37 -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 +13 -12
- package/dist/workers/focused-extractor.js +27 -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 +65 -96
- package/dist/workers/pi-worker-core.js +93 -181
- 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 +21 -14
- 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 +27 -30
- package/dist/workers/single-read-guard.js +36 -36
- 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 +54 -56
- package/dist/workers/worker-profiles.js +63 -39
- package/package.json +10 -8
|
@@ -3,13 +3,10 @@
|
|
|
3
3
|
* declares the finished project must expose, extracted once at plan time and diffed
|
|
4
4
|
* by the final gate against the shipped manifest.
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* the finished manifest against the design's own list, so the run completed missing
|
|
11
|
-
* two of its declared entrypoints. A per-slice gate cannot catch this — it is a
|
|
12
|
-
* whole-project launch-surface fact — and the final gate never had the design's list.
|
|
6
|
+
* The gap it closes is structural. A script the design names but no task owned can
|
|
7
|
+
* fall through decompose and ship missing, and a per-slice gate cannot see that: it
|
|
8
|
+
* is a whole-project launch-surface fact, and nothing else re-reads the finished
|
|
9
|
+
* manifest against the design's own list.
|
|
13
10
|
*
|
|
14
11
|
* Mechanism (mirrors contracts.ts): a plan-time child EMITs `SCRIPT:` lines naming the
|
|
15
12
|
* scripts the design declares; the host GROUNDS each against the design — a name is
|
|
@@ -17,9 +14,13 @@
|
|
|
17
14
|
* form designs use to declare a script. A paraphrase or a script the model invented is
|
|
18
15
|
* not grounded and is dropped, so the diff can never false-flag on a hallucinated
|
|
19
16
|
* requirement. The grounded list is appended HOST-SIDE to `.pi-tasks/launch-contract.md`
|
|
20
|
-
*
|
|
17
|
+
* — the extraction child runs `--no-tools` and so has no write tool at all. Both halves
|
|
18
|
+
* of `discardTreeEdits` skip that directory (`checkout -- . :(exclude).pi-tasks`, then
|
|
19
|
+
* `clean -fd -e .pi-tasks`), and the git-state guard excludes it from the tree it
|
|
20
|
+
* hashes, so the file outlives a discarded pass.
|
|
21
21
|
*
|
|
22
|
-
* At run end the final gate reads the list, reads the manifest's
|
|
22
|
+
* At run end the final gate reads the list, reads the shipped manifest's script names
|
|
23
|
+
* (`readLaunchManifest`: package.json `scripts`, else a Makefile's targets), and FAILs
|
|
23
24
|
* naming any declared script the manifest is missing. FP-safe by construction: an
|
|
24
25
|
* empty/ungrounded list (a design that never backticks a script name) yields no check.
|
|
25
26
|
*/
|
|
@@ -93,22 +94,20 @@ export function keepGroundedScripts(names, sourceDoc) {
|
|
|
93
94
|
return kept;
|
|
94
95
|
}
|
|
95
96
|
/**
|
|
96
|
-
* DETERMINISTIC RECALL
|
|
97
|
+
* DETERMINISTIC RECALL: enumerate every backticked, script-name-shaped
|
|
97
98
|
* token in a paragraph that mentions the word "script", as extraction CANDIDATES.
|
|
98
99
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* enumerates candidates and hands them to the child as an explicit checklist; the
|
|
105
|
-
* model's job flips from recall (weak) to per-candidate classification (strong).
|
|
100
|
+
* Grounding can only DROP a candidate, never add one, so without this the recall of a
|
|
101
|
+
* script declared far from the design's summary list is entirely the model's. This
|
|
102
|
+
* makes recall mechanical: the host enumerates the candidates and hands them to the
|
|
103
|
+
* child as an explicit checklist, so the model's job flips from recall (weak) to
|
|
104
|
+
* per-candidate classification (strong).
|
|
106
105
|
*
|
|
107
106
|
* The paragraph gate (`\bscripts?\b`, word-bounded so "TypeScript"/"JavaScript"
|
|
108
107
|
* don't match) is a grounded-context filter, not a tuned knob: a design declares a
|
|
109
|
-
* script by calling it one. It keeps package-name paragraphs
|
|
110
|
-
*
|
|
111
|
-
*
|
|
108
|
+
* script by calling it one. It keeps package-name paragraphs out of the checklist so
|
|
109
|
+
* a weak model isn't invited to keep junk the grounding guard would then bless —
|
|
110
|
+
* every package name is backticked somewhere. A design with no
|
|
112
111
|
* such paragraph yields no candidates and the prompt is unchanged.
|
|
113
112
|
*/
|
|
114
113
|
export function enumerateScriptCandidates(sourceDoc) {
|
|
@@ -153,13 +152,12 @@ export async function appendDeclaredScripts(cwd, names) {
|
|
|
153
152
|
*/
|
|
154
153
|
const BOOT_CLASS_RE = /^(?:dev|start|serve|preview|watch)(?:[:_-].*)?$/i;
|
|
155
154
|
/**
|
|
156
|
-
* The declared scripts the final gate must EXECUTE as one-shot commands
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* existence is not launchability.
|
|
155
|
+
* The declared scripts the final gate must EXECUTE as one-shot commands: everything
|
|
156
|
+
* the launch contract declares that is neither boot-class (the boot check exercises
|
|
157
|
+
* those) nor already covered by the gate's integration commands (`covered`,
|
|
158
|
+
* case-insensitive — the test/build-shaped scripts that ran). Checking only that a
|
|
159
|
+
* script is DECLARED says nothing about whether running it works; existence is not
|
|
160
|
+
* launchability.
|
|
163
161
|
*/
|
|
164
162
|
export function runnableDeclaredScripts(declared, covered) {
|
|
165
163
|
const have = new Set(covered.map(s => s.toLowerCase()));
|
|
@@ -189,9 +187,9 @@ export function missingDeclaredScripts(declared, manifestScripts) {
|
|
|
189
187
|
* (keepGroundedScripts), so a hallucinated script cannot reach the diff.
|
|
190
188
|
*
|
|
191
189
|
* `candidates` is enumerateScriptCandidates' mechanical checklist. It exists so the
|
|
192
|
-
* model cannot MISS a declared script buried far from the design's summary list
|
|
193
|
-
*
|
|
194
|
-
*
|
|
190
|
+
* model cannot MISS a declared script buried far from the design's summary list; the
|
|
191
|
+
* model still classifies each candidate against the design, and the host grounding
|
|
192
|
+
* still applies. Empty ⇒ the prompt is unchanged.
|
|
195
193
|
*/
|
|
196
194
|
export const LAUNCH_EXTRACT_PROMPT = (feature, candidates = []) => [
|
|
197
195
|
'You are recording the PACKAGE/BUILD SCRIPTS the design below says the finished',
|
|
@@ -31,12 +31,16 @@ export declare function makeTargets(src: string): string[];
|
|
|
31
31
|
export declare function readLaunchManifest(cwd: string): LaunchManifest;
|
|
32
32
|
/**
|
|
33
33
|
* The one line an INERT contract leaves behind. It rides in the gate's UNOBSERVED
|
|
34
|
-
* channel rather than in `warnings` for
|
|
34
|
+
* channel rather than in `warnings` for one reason: a check that
|
|
35
35
|
* silently did nothing must not read later as a check that passed.
|
|
36
36
|
*/
|
|
37
37
|
export declare function inertLaunchContractNote(declared: string[], manifest: LaunchManifest): string;
|
|
38
38
|
/** The `scripts` map of this tree's package.json, or `{}` when there isn't one.
|
|
39
39
|
* Shared by the gate and the boot probe — both ask the same manifest question. */
|
|
40
40
|
export declare function packageScripts(cwd: string): Record<string, string>;
|
|
41
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Does this tree's Makefile declare `target`? Reads the literal name `Makefile`
|
|
43
|
+
* only — unlike {@link readLaunchManifest}, this one does not walk make's lookup
|
|
44
|
+
* order, so a `GNUmakefile`-only tree answers false.
|
|
45
|
+
*/
|
|
42
46
|
export declare function makeHasTarget(cwd: string, target: string): boolean;
|
|
@@ -1,54 +1,50 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* launch-manifest — WHICH manifest the launch-contract diff is entitled to diff
|
|
3
|
-
* against, and whether there is one at all
|
|
3
|
+
* against, and whether there is one at all.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* design does. The diff end hardcoded the ecosystem anyway:
|
|
5
|
+
* WHY THE DIFF NEEDS ITS OWN RESOLVER. The extraction end of the launch contract
|
|
6
|
+
* has no ecosystem test anywhere in it: `enumerateScriptCandidates` scrapes
|
|
7
|
+
* backticked, script-name-shaped tokens out of any design paragraph that says
|
|
8
|
+
* "script", and `keepGroundedScripts` can only DROP a candidate. A Makefile design
|
|
9
|
+
* saying *"the Makefile must expose `build`, `test`, `migrate`"* therefore records
|
|
10
|
+
* exactly the same artifact an npm design does.
|
|
12
11
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* That text seeds the autofix child's prompt (final-gate.ts's FinalGateOutcome.reason),
|
|
20
|
-
* so the most likely repair on a CMake project was to write a package.json.
|
|
21
|
-
*
|
|
22
|
-
* IAR1 is how close this got: `plan-debug.log:10` records "launch-contract
|
|
23
|
-
* extraction: 0 grounded script(s) kept from 3 emitted" — a non-npm project that
|
|
24
|
-
* reached extraction and emitted three candidates, saved only by its design not
|
|
25
|
-
* backticking them in a "script" paragraph.
|
|
12
|
+
* The diff cannot then reach for `packageScripts` alone. Its catch returns `{}`, so
|
|
13
|
+
* "this project has no package.json" is indistinguishable from "its package.json
|
|
14
|
+
* declares no scripts", and every declared script reads as missing — in wording that
|
|
15
|
+
* NAMES a file the project was never meant to have. `tally.fail` text becomes the
|
|
16
|
+
* gate's `reason`, which `buildFinalFixPrompt` hands to the autofix child, so on a
|
|
17
|
+
* non-npm tree the repair that text invites is to write a package.json.
|
|
26
18
|
*
|
|
27
19
|
* THE RULE, and it is deliberately two ecosystems wide, not three:
|
|
28
20
|
* • package.json present and parseable ⇒ diff against its `scripts` keys, exactly
|
|
29
|
-
* as before (byte-identical failure text on every npm tree —
|
|
21
|
+
* as before (byte-identical failure text on every npm tree — a missing
|
|
30
22
|
* `build`/`seed` is a TRUE positive and must keep failing).
|
|
31
|
-
* • no package.json but a Makefile ⇒ diff against its TARGETS.
|
|
32
|
-
* already in final-gate.ts (`makeHasTarget`); the diff simply never called it.
|
|
23
|
+
* • no package.json but a Makefile ⇒ diff against its TARGETS.
|
|
33
24
|
* • neither ⇒ the check is INERT. No failure, and a note saying the contract was
|
|
34
25
|
* recorded but is not checkable here, so the silence is not read later as a pass
|
|
35
26
|
* (the repo-health-check / env-template-closure discipline: ENOENT = pass, and a
|
|
36
27
|
* check must never invent a file the project chose not to have).
|
|
37
28
|
*
|
|
38
|
-
* cargo/poetry/gradle are NOT here on purpose
|
|
39
|
-
*
|
|
40
|
-
* that
|
|
29
|
+
* cargo/poetry/gradle are NOT here on purpose: nothing in this repo knows how to
|
|
30
|
+
* enumerate their entrypoints, and a third resolver written without one would be a
|
|
31
|
+
* guess that can only produce false FAILs.
|
|
41
32
|
*/
|
|
42
33
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
43
34
|
import * as path from 'node:path';
|
|
44
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* GNU make's own lookup order, and nothing beyond it — this is one ecosystem.
|
|
37
|
+
* Confirmed against `make` itself: with all three files present in one directory it
|
|
38
|
+
* runs GNUmakefile; with only `makefile` and `Makefile`, it runs `makefile`.
|
|
39
|
+
*/
|
|
45
40
|
const MAKEFILE_NAMES = ['GNUmakefile', 'makefile', 'Makefile'];
|
|
46
41
|
/** A target we are willing to name in a failure: an ordinary word-shaped target. */
|
|
47
42
|
const TARGET_NAME_RE = /^[a-z0-9][a-z0-9._-]{0,39}$/i;
|
|
48
43
|
/**
|
|
49
44
|
* A variable assignment, in every form make accepts (`=`, `:=`, `::=`, `?=`, `+=`,
|
|
50
45
|
* `!=`, with an optional `override`/`export`). Matched BEFORE the target rule
|
|
51
|
-
* because `FLAGS ::= -O2` otherwise reads as a target named `FLAGS
|
|
46
|
+
* because `FLAGS ::= -O2` otherwise reads as a target named `FLAGS` — make itself
|
|
47
|
+
* reports that line as a variable, not a rule.
|
|
52
48
|
*/
|
|
53
49
|
const ASSIGN_RE = /^(?:override\s+|export\s+)?[A-Za-z_][A-Za-z0-9_.]*\s*(?:::|:|\?|\+|!)?=/;
|
|
54
50
|
/**
|
|
@@ -87,9 +83,10 @@ export function makeTargets(src) {
|
|
|
87
83
|
}
|
|
88
84
|
/**
|
|
89
85
|
* The makefiles that really exist in `cwd`, in GNU make's lookup order, named as
|
|
90
|
-
* the DIRECTORY spells them.
|
|
91
|
-
*
|
|
92
|
-
*
|
|
86
|
+
* the DIRECTORY spells them. The invariant is that `manifest.file` is always a name
|
|
87
|
+
* `readdirSync(cwd)` contains, so a failure can never name a file the project does
|
|
88
|
+
* not have. An `existsSync` probe per candidate name cannot promise that, because it
|
|
89
|
+
* answers about a name we chose rather than a name on disk.
|
|
93
90
|
*/
|
|
94
91
|
function makefilesOnDisk(cwd) {
|
|
95
92
|
let entries;
|
|
@@ -141,7 +138,7 @@ export function readLaunchManifest(cwd) {
|
|
|
141
138
|
}
|
|
142
139
|
/**
|
|
143
140
|
* The one line an INERT contract leaves behind. It rides in the gate's UNOBSERVED
|
|
144
|
-
* channel rather than in `warnings` for
|
|
141
|
+
* channel rather than in `warnings` for one reason: a check that
|
|
145
142
|
* silently did nothing must not read later as a check that passed.
|
|
146
143
|
*/
|
|
147
144
|
export function inertLaunchContractNote(declared, manifest) {
|
|
@@ -160,7 +157,11 @@ export function packageScripts(cwd) {
|
|
|
160
157
|
return {};
|
|
161
158
|
}
|
|
162
159
|
}
|
|
163
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* Does this tree's Makefile declare `target`? Reads the literal name `Makefile`
|
|
162
|
+
* only — unlike {@link readLaunchManifest}, this one does not walk make's lookup
|
|
163
|
+
* order, so a `GNUmakefile`-only tree answers false.
|
|
164
|
+
*/
|
|
164
165
|
export function makeHasTarget(cwd, target) {
|
|
165
166
|
try {
|
|
166
167
|
const mk = readFileSync(path.join(cwd, 'Makefile'), 'utf8');
|
package/dist/task/ledger.js
CHANGED
|
@@ -3,24 +3,26 @@
|
|
|
3
3
|
* `.pi-tasks/` (contracts, launch-contract, env-notes, accept-debt, repair-queue,
|
|
4
4
|
* requirements, requirements-owned).
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
6
|
+
* The ritual is seven steps: read the file (ANY error → ''), parse it into records,
|
|
7
|
+
* key the records, drop an incoming item whose key is already present, cap to the
|
|
8
|
+
* newest MAX (oldest dropped), mkdir the tasks dir, write the whole file back
|
|
9
|
+
* (`lines.join('\n') + '\n'`, plain `writeFile`, NOT atomic). Every fault is
|
|
10
|
+
* swallowed — a ledger is a sharpener or an auditing aid, never a blocker of the
|
|
11
|
+
* phase or gate that calls it.
|
|
12
|
+
*
|
|
13
|
+
* What varies per site is the DATA SHAPE (file name, cap, key, line format, parser)
|
|
14
|
+
* and exactly one RULE — what an append does when it adds nothing new (see
|
|
15
|
+
* `onNoop`). Everything else here is the ritual, so a module that keeps a ledger is
|
|
16
|
+
* an ADAPTER: it declares its ledger and calls read/append/write.
|
|
16
17
|
*
|
|
17
18
|
* Contract details a caller can rely on:
|
|
18
19
|
* • `readRaw` is the trimmed file text ('' when absent or unreadable). Prompt-block
|
|
19
20
|
* builders take this string.
|
|
20
|
-
* • `read` is `parse(readRaw)`; every parser skips blank lines and lines
|
|
21
|
-
* read, so a corrupt line is dropped, never thrown on.
|
|
22
|
-
* • `append` with an empty batch is a no-op
|
|
23
|
-
* the first item with a key wins; a key already stored wins over
|
|
21
|
+
* • `read` is `parse(readRaw)`; every adapter's parser skips blank lines and lines
|
|
22
|
+
* it cannot read, so a corrupt line is dropped, never thrown on.
|
|
23
|
+
* • `append` with an empty batch is a no-op — it does not even create `.pi-tasks/`.
|
|
24
|
+
* Within a batch the first item with a key wins; a key already stored wins over
|
|
25
|
+
* the batch.
|
|
24
26
|
* • `write` overwrites with exactly these records; an empty list writes an empty
|
|
25
27
|
* file (this is how a drained queue and a fully-resolved debt ledger look).
|
|
26
28
|
* • Neither `append` nor `write` ever throws.
|
package/dist/task/lint-fix.d.ts
CHANGED
|
@@ -43,20 +43,18 @@ export interface LintFixDeps {
|
|
|
43
43
|
*/
|
|
44
44
|
introducedBy?: (rel: string) => Promise<string | null>;
|
|
45
45
|
/**
|
|
46
|
-
* Debug-log sink.
|
|
47
|
-
*
|
|
48
|
-
* three of its own — and a guard whose firing leaves no record cannot be
|
|
49
|
-
* distinguished from one that never armed.
|
|
46
|
+
* Debug-log sink. Every guard below logs its own trip through it: a guard whose
|
|
47
|
+
* firing leaves no record cannot be distinguished from one that never armed.
|
|
50
48
|
*/
|
|
51
49
|
log?: (msg: string) => void;
|
|
52
50
|
}
|
|
53
51
|
/** The fix child edits and runs the checker; bash exists to RUN the check, not git. */
|
|
54
52
|
export declare const LINT_FIX_TOOLS = "read,edit,bash";
|
|
55
53
|
/**
|
|
56
|
-
* Build the fix child's prompt.
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
54
|
+
* Build the fix child's prompt. Two constraints carry the design: smallest edits
|
|
55
|
+
* only — the re-run's rewrite habit is the defect this pass replaces — and an
|
|
56
|
+
* explicit ban on discarding work, which is the cheapest route to a green check and
|
|
57
|
+
* exactly what the revert-guard exists to catch.
|
|
60
58
|
*/
|
|
61
59
|
export declare function buildLintFixPrompt(failReason: string, frozenPaths?: string[]): string;
|
|
62
60
|
/**
|
package/dist/task/lint-fix.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* lint-fix — the bounded, graduated resolution for a repo-health verify FAIL.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* (read,edit,bash) reached lint-clean in 64s and 106s, 2/2.
|
|
4
|
+
* WHY A SEPARATE PASS. AUTOFIX's only hammer is a FULL implementation re-run. For a
|
|
5
|
+
* repo-health FAIL of a few trivial lint findings the re-run REGENERATES the work
|
|
6
|
+
* rather than editing it, and fresh output fails lint differently — the loop cannot
|
|
7
|
+
* converge because the tool is bigger than the defect. A bounded fix child
|
|
8
|
+
* (read,edit,bash) edits only the findings.
|
|
10
9
|
*
|
|
11
|
-
*
|
|
12
|
-
* `git checkout --
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* REVERT-GUARD. A fix child can reach lint-clean by DISCARDING the task's
|
|
11
|
+
* uncommitted work: `git checkout -- <the work file>` makes every finding vanish.
|
|
12
|
+
* The prompt forbids it, but the guard is outcome-based, because command filtering
|
|
13
|
+
* cannot catch every path to the same effect:
|
|
15
14
|
*
|
|
16
15
|
* - Before the child runs: snapshot the full working state (`git add -A` +
|
|
17
16
|
* `git write-tree`, then unstage) and record which files differ from HEAD.
|
|
@@ -28,34 +27,38 @@
|
|
|
28
27
|
* recommend → AUTOFIX/ACCEPT/dismiss picker, so this pass can only make the loop
|
|
29
28
|
* faster, never change what it can decide.
|
|
30
29
|
*
|
|
31
|
-
* FROZEN-PATH GUARD
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
30
|
+
* FROZEN-PATH GUARD. The checker's own error text can INSTRUCT an edit to a
|
|
31
|
+
* spec-frozen file. Typed ESLint, asked to lint a file outside the tsconfig
|
|
32
|
+
* `include`, prints:
|
|
33
|
+
*
|
|
34
|
+
* Parsing error: <file> was not found by the project service. Consider either
|
|
35
|
+
* including it in the tsconfig.json or including it in allowDefaultProject.
|
|
36
|
+
*
|
|
37
|
+
* A child that complies edits `tsconfig.json`. If the task's spec froze that file,
|
|
38
|
+
* verify's prohibition probe raises rule 4b — "SPEC PROHIBITIONS ARE PART OF THE
|
|
39
|
+
* BAR — YOU HAVE NO WAIVER AUTHORITY" — and FAILs the TASK for the gate child's
|
|
40
|
+
* edit. Two gates, contradictory rules, same file; the loop never converges.
|
|
41
|
+
*
|
|
42
|
+
* So the deny is mechanical rather than framing: the spec's frozen paths are
|
|
40
43
|
* threaded in via `frozenPaths`, injected into the prompt as a do-not-touch list
|
|
41
|
-
* (belt), and any frozen path the child still changed is deterministically
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
44
|
+
* (belt), and any frozen path the child still changed is deterministically reverted
|
|
45
|
+
* post-child and the fix reported not-applied (suspenders). Only paths that were
|
|
46
|
+
* CLEAN before the child ran are reverted — a frozen path already dirty with
|
|
47
|
+
* (possibly task) work is left alone, in the guard's safe direction: cost time,
|
|
48
|
+
* never work.
|
|
46
49
|
*
|
|
47
|
-
* CROSS-TASK DELETION GUARD
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* introducing task (per `introducedBy`, git history) differs from the CURRENT
|
|
50
|
+
* CROSS-TASK DELETION GUARD. The revert-guard above is outcome-based but blind to a
|
|
51
|
+
* CLEAN tracked file. Delete one and `git status --porcelain` reports ` D <path>`
|
|
52
|
+
* while it appears in NEITHER of the guard's two lists: it was not pre-dirty (it
|
|
53
|
+
* matched HEAD) and not pre-untracked (it is tracked). If the lint then converges,
|
|
54
|
+
* the pass returns ok having destroyed a sibling task's committed deliverable. The
|
|
55
|
+
* discriminator is PROVENANCE, not deletion per se: a tracked file the CHILD deleted
|
|
56
|
+
* whose introducing task (per `introducedBy`, git history) differs from the CURRENT
|
|
55
57
|
* task is restored from HEAD and the fix reported not-applied naming the owner.
|
|
56
|
-
* Same-task deletions, unknown provenance, relocations
|
|
57
|
-
*
|
|
58
|
-
* `currentTaskId` and
|
|
58
|
+
* Same-task deletions, unknown provenance, relocations (a deletion whose basename
|
|
59
|
+
* reappears among the added paths) and any git error all step aside — the guard may
|
|
60
|
+
* only cost time, never work. Armed only when both `currentTaskId` and
|
|
61
|
+
* `introducedBy` are wired.
|
|
59
62
|
*/
|
|
60
63
|
import { parseChangedFrozenFiles, pathNamedIn, revertFrozenPaths } from './frozen-path-guard.js';
|
|
61
64
|
import { runFixChild } from './fix-child.js';
|
|
@@ -64,10 +67,10 @@ import { findCrossTaskDeletions } from './task-provenance.js';
|
|
|
64
67
|
/** The fix child edits and runs the checker; bash exists to RUN the check, not git. */
|
|
65
68
|
export const LINT_FIX_TOOLS = 'read,edit,bash';
|
|
66
69
|
/**
|
|
67
|
-
* Build the fix child's prompt.
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
70
|
+
* Build the fix child's prompt. Two constraints carry the design: smallest edits
|
|
71
|
+
* only — the re-run's rewrite habit is the defect this pass replaces — and an
|
|
72
|
+
* explicit ban on discarding work, which is the cheapest route to a green check and
|
|
73
|
+
* exactly what the revert-guard exists to catch.
|
|
71
74
|
*/
|
|
72
75
|
export function buildLintFixPrompt(failReason, frozenPaths = []) {
|
|
73
76
|
const frozenBlock = frozenPaths.length === 0 ?
|
|
@@ -123,7 +126,7 @@ export function revertGuardViolations(preDirty, stillDirty) {
|
|
|
123
126
|
const EXCLUDE_TASKS_DIR = ':(exclude).pi-tasks';
|
|
124
127
|
/**
|
|
125
128
|
* Files differing from HEAD, or null when git itself failed. The distinction is
|
|
126
|
-
* load-bearing:
|
|
129
|
+
* load-bearing: without it a run rolls back GOOD converged fixes because a git
|
|
127
130
|
* failure after the child read as "[] files still dirty" → every pre-existing work
|
|
128
131
|
* file looked reverted → false "discarded work". A git error is INCONCLUSIVE, not
|
|
129
132
|
* evidence of destruction.
|
|
@@ -205,12 +208,10 @@ export async function runBoundedLintFix(deps) {
|
|
|
205
208
|
// guard for this run (inconclusive ≠ evidence).
|
|
206
209
|
const deletionGuardArmed = Boolean(deps.currentTaskId && deps.introducedBy);
|
|
207
210
|
const preChanges = deletionGuardArmed ? await treeChanges(deps) : null;
|
|
208
|
-
// The four-rung ladder lives in task/fix-child.ts
|
|
209
|
-
// (
|
|
210
|
-
//
|
|
211
|
-
//
|
|
212
|
-
// whole guard stack and a repo-health re-run (15–69s measured) to be told
|
|
213
|
-
// `did not converge`, instead of its own stated reason.
|
|
211
|
+
// The four-rung ladder lives in task/fix-child.ts: a cancel propagates as a
|
|
212
|
+
// THROW (so the caller's USER_CANCELLED path is unchanged), a child that threw
|
|
213
|
+
// for any other reason is `error`, a self-declared BLOCKED is `blocked`, and
|
|
214
|
+
// anything else is `done`.
|
|
214
215
|
const end = await runFixChild({
|
|
215
216
|
runChild: deps.runChild,
|
|
216
217
|
tools: LINT_FIX_TOOLS,
|
|
@@ -228,10 +229,10 @@ export async function runBoundedLintFix(deps) {
|
|
|
228
229
|
// where the twin consults its own.
|
|
229
230
|
// REVERT-GUARD: every pre-existing work file must still differ from HEAD, and
|
|
230
231
|
// every pre-existing untracked file must still exist. Trip → restore snapshot.
|
|
231
|
-
// Every comparison requires git to have actually SUCCEEDED
|
|
232
|
-
// the child
|
|
233
|
-
//
|
|
234
|
-
//
|
|
232
|
+
// Every comparison requires git to have actually SUCCEEDED. A git error after
|
|
233
|
+
// the child reads as "nothing is dirty", which would flag every pre-existing
|
|
234
|
+
// work file as discarded — inconclusive, not evidence. The guard then steps
|
|
235
|
+
// aside and the converge check below still decides.
|
|
235
236
|
const stillDirtyList = await dirtyFiles(deps);
|
|
236
237
|
let guardNote;
|
|
237
238
|
const violations = [];
|
|
@@ -271,10 +272,9 @@ export async function runBoundedLintFix(deps) {
|
|
|
271
272
|
}
|
|
272
273
|
// CROSS-TASK DELETION GUARD: a tracked file the CHILD deleted whose
|
|
273
274
|
// introducing task differs from the current task is a sibling's committed
|
|
274
|
-
// deliverable destroyed to go green
|
|
275
|
-
//
|
|
276
|
-
//
|
|
277
|
-
// is neither). Restore JUST those paths from HEAD (they were clean pre-child,
|
|
275
|
+
// deliverable destroyed to go green. The revert-guard above only watches
|
|
276
|
+
// pre-dirty and pre-untracked files, and a clean tracked sibling file is
|
|
277
|
+
// neither. Restore JUST those paths from HEAD (they were clean pre-child,
|
|
278
278
|
// so nothing of the task's work can be lost) and report not-applied naming the
|
|
279
279
|
// owner. Inconclusive on any side — git error, unknown provenance, same-task
|
|
280
280
|
// deletion, relocation — steps aside.
|
|
@@ -300,14 +300,13 @@ export async function runBoundedLintFix(deps) {
|
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
302
|
}
|
|
303
|
-
// FROZEN-PATH GUARD: a frozen path that was clean pre-child and is changed
|
|
304
|
-
//
|
|
305
|
-
//
|
|
306
|
-
//
|
|
307
|
-
//
|
|
308
|
-
//
|
|
309
|
-
//
|
|
310
|
-
// side) → guard steps aside; the verify probe still catches what survives.
|
|
303
|
+
// FROZEN-PATH GUARD: a frozen path that was clean pre-child and is changed now
|
|
304
|
+
// is the child's edit — the exact write verify's rule-4b prohibition probe
|
|
305
|
+
// fails the TASK for. Revert JUST those paths (they were clean, so HEAD ==
|
|
306
|
+
// pre-state: no work can be lost) and report not-applied so the caller falls
|
|
307
|
+
// through to the ordinary recommend → AUTOFIX/ACCEPT picker. Inconclusive git
|
|
308
|
+
// (either side) → guard steps aside; the verify probe still catches what
|
|
309
|
+
// survives.
|
|
311
310
|
if (preFrozenDirty !== null) {
|
|
312
311
|
const postFrozenDirty = await frozenDirtySet(deps, frozen);
|
|
313
312
|
if (postFrozenDirty !== null) {
|
|
@@ -341,18 +340,17 @@ export async function runBoundedLintFix(deps) {
|
|
|
341
340
|
// while the child's edits sit in the working tree.
|
|
342
341
|
//
|
|
343
342
|
// So BLOCKED does not decide; it only supplies a better REASON when the check
|
|
344
|
-
// agrees nothing converged.
|
|
345
|
-
//
|
|
343
|
+
// agrees nothing converged. Skipping the re-run on the marker alone is not
|
|
344
|
+
// worth that risk.
|
|
346
345
|
const health = await deps.repoHealth();
|
|
347
346
|
if (!health.ok) {
|
|
348
347
|
if (end.kind === 'blocked') {
|
|
349
348
|
return { ok: false, reason: `fix child blocked: ${end.note}` };
|
|
350
349
|
}
|
|
351
|
-
// FROZEN-PATH TRACE on non-convergence
|
|
352
|
-
//
|
|
353
|
-
//
|
|
354
|
-
//
|
|
355
|
-
// consider including it in the tsconfig.json"), the findings can only be
|
|
350
|
+
// FROZEN-PATH TRACE on non-convergence: when the child was honest — it did
|
|
351
|
+
// NOT touch the frozen path, so the guard above never tripped — but the
|
|
352
|
+
// check is still red and its own output NAMES a frozen path (the typed
|
|
353
|
+
// ESLint message quoted in this file's header), the findings can only be
|
|
356
354
|
// fixed by an edit this task's spec forbids. Report it under the same
|
|
357
355
|
// `frozen-path:` prefix as the guard trip, so the gate loop can route
|
|
358
356
|
// straight to the human picker instead of burning unattended AUTOFIX
|
|
@@ -12,7 +12,19 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Either pattern returns a LoopHit so the caller can kill the child and re-spawn
|
|
14
14
|
* with a hint. No I/O. No imports from index.ts. Trivially unit-testable.
|
|
15
|
+
*
|
|
16
|
+
* The three tuning constants live here rather than in child-runner.ts because
|
|
17
|
+
* worker-profiles.ts reads them at module top level to build DEFAULT_LOOP_DETECTOR.
|
|
18
|
+
* From child-runner.ts that is a cycle — child-runner → worker-profiles →
|
|
19
|
+
* child-runner — and the failure is a TDZ ReferenceError on import order, which
|
|
20
|
+
* no compile step catches. This module imports nothing, so it cannot close one.
|
|
15
21
|
*/
|
|
22
|
+
/** Recent tool calls the exact-repeat rule looks back over. */
|
|
23
|
+
export declare const LOOP_WINDOW = 20;
|
|
24
|
+
/** Repeats of one key within the window that trip the detector. */
|
|
25
|
+
export declare const LOOP_THRESHOLD = 5;
|
|
26
|
+
/** Re-spawns allowed after a loop kill — 3 attempts total with the initial one. */
|
|
27
|
+
export declare const MAX_LOOP_RESTARTS = 2;
|
|
16
28
|
export interface ToolCall {
|
|
17
29
|
name: string;
|
|
18
30
|
args: unknown;
|
|
@@ -27,6 +39,12 @@ export interface LoopHit {
|
|
|
27
39
|
* Arrays preserve their order (positional). undefined / primitives passthrough.
|
|
28
40
|
*/
|
|
29
41
|
export declare function stableStringify(value: unknown): string;
|
|
42
|
+
/**
|
|
43
|
+
* The exact-match identity of a tool call. Exported because implementation-guards.ts
|
|
44
|
+
* keys its own per-call strike count on it, and a second hand-written copy of this
|
|
45
|
+
* expression is free to drift away from the one `record` uses.
|
|
46
|
+
*/
|
|
47
|
+
export declare function loopKey(call: ToolCall): string;
|
|
30
48
|
/**
|
|
31
49
|
* The primary file path a tool call targets, mirroring summarizeToolArgs' field
|
|
32
50
|
* precedence. Returns null when the call names no path (e.g. bash, or a grep
|
|
@@ -47,15 +65,16 @@ export declare class LoopDetector {
|
|
|
47
65
|
/**
|
|
48
66
|
* Count same-path calls in the window that are "revisits" — accesses that end
|
|
49
67
|
* no further into the file than the furthest line already covered for that
|
|
50
|
-
* path.
|
|
51
|
-
*
|
|
68
|
+
* path. The FIRST call on a path is therefore never a revisit: it sets the
|
|
69
|
+
* high-water mark. Paging yields zero revisits and never trips; repeated
|
|
70
|
+
* whole-file re-reads, backward jumps, narrower re-reads and repeated
|
|
71
|
+
* path-targeting greps all accumulate.
|
|
52
72
|
*
|
|
53
|
-
* The comparison is on the RANGE, not the offset.
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* path alone, and it is corrected the same way.
|
|
73
|
+
* The comparison is on the RANGE, not the offset. Keying on offset alone scores
|
|
74
|
+
* `{offset:80, limit:400}` after `{offset:80, limit:300}` as a revisit, even
|
|
75
|
+
* though it covers 100 lines the child has never seen. That is the same mistake
|
|
76
|
+
* SingleReadGuard made by keying on the path alone, and it is corrected the same
|
|
77
|
+
* way.
|
|
59
78
|
*/
|
|
60
79
|
private countRevisits;
|
|
61
80
|
}
|