@mjasnikovs/pi-task 0.38.29 → 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 +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 +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 +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-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 +179 -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 +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 +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 +69 -71
- package/dist/workers/pi-worker-core.js +100 -109
- 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 +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/fix-child.d.ts
CHANGED
|
@@ -1,32 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Running ONE bounded fix child and deciding what its ending MEANS.
|
|
3
3
|
*
|
|
4
|
-
* Two graduated-resolution passes
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Two graduated-resolution passes — `lint-fix.ts` and `final-gate-fix.ts` — drive
|
|
5
|
+
* a fix child through the same four rungs: a cancel propagates as a throw, a
|
|
6
|
+
* child that threw for any other reason is an `error`, a self-declared BLOCKED is
|
|
7
|
+
* `blocked`, and anything else is `done`. `final-gate-fix.ts`'s own header says
|
|
8
|
+
* it "mirrors the per-task graduated-resolution shape (lint-fix.ts)". This is
|
|
9
|
+
* that ladder, written once.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* two had actually drifted.
|
|
11
|
+
* Both prompts instruct the marker their pass parses: `LINT-FIX: DONE` /
|
|
12
|
+
* `LINT-FIX: BLOCKED <why>` and `FINAL-GATE-FIX: DONE` / `FINAL-GATE-FIX:
|
|
13
|
+
* BLOCKED <why>`.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* measured), and the user was told `did not converge: <health.reason>` instead
|
|
22
|
-
* of the child's own stated reason. The suite fed `'LINT-FIX: DONE'` as fake
|
|
23
|
-
* output, so it stayed green whether the marker was parsed or deleted.
|
|
24
|
-
* - **The cancel rung re-typed its constant.** `lint-fix.ts` compared against a
|
|
25
|
-
* literal `'__user_cancelled__'`; it was the only production site in `src/` not
|
|
26
|
-
* importing `USER_CANCELLED`.
|
|
27
|
-
*
|
|
28
|
-
* What stays per-site: the arbiter (a gate re-run vs a repo-health re-run), the
|
|
29
|
-
* result shape, and the guard sets. Only the child call is shared.
|
|
15
|
+
* What stays per-site: the arbiter, the result shape, and the guard sets. Only
|
|
16
|
+
* the child call is shared. The arbiters differ in kind — `final-gate-fix` calls
|
|
17
|
+
* `deps.gate`, `lint-fix` calls `deps.repoHealth` — and so does what BLOCKED
|
|
18
|
+
* buys: `final-gate-fix` skips its gate re-run on a blocked child, while
|
|
19
|
+
* `lint-fix` runs repo-health regardless and uses the marker only to word the
|
|
20
|
+
* failure.
|
|
30
21
|
*/
|
|
31
22
|
/** How one fix child ended. A CANCEL is not a member: it throws, so the caller's
|
|
32
23
|
* own `USER_CANCELLED` path runs unchanged. */
|
|
@@ -52,9 +43,12 @@ export interface FixChildInput {
|
|
|
52
43
|
}
|
|
53
44
|
/**
|
|
54
45
|
* Parse a fix child's final marker. Last match wins: the model reasons before
|
|
55
|
-
* concluding, and
|
|
56
|
-
*
|
|
57
|
-
*
|
|
46
|
+
* concluding, and both passes give the child `bash`, so its own command output is
|
|
47
|
+
* in the text being scraped.
|
|
48
|
+
*
|
|
49
|
+
* No marker → DONE. Neither pass treats the marker as the verdict — the arbiter
|
|
50
|
+
* decides — so a missing marker costs at most the blocked early-out in
|
|
51
|
+
* `final-gate-fix`, and nothing at all in `lint-fix`.
|
|
58
52
|
*/
|
|
59
53
|
export declare function parseFixMarker(marker: string, text: string): {
|
|
60
54
|
blocked: boolean;
|
package/dist/task/fix-child.js
CHANGED
|
@@ -1,39 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Running ONE bounded fix child and deciding what its ending MEANS.
|
|
3
3
|
*
|
|
4
|
-
* Two graduated-resolution passes
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Two graduated-resolution passes — `lint-fix.ts` and `final-gate-fix.ts` — drive
|
|
5
|
+
* a fix child through the same four rungs: a cancel propagates as a throw, a
|
|
6
|
+
* child that threw for any other reason is an `error`, a self-declared BLOCKED is
|
|
7
|
+
* `blocked`, and anything else is `done`. `final-gate-fix.ts`'s own header says
|
|
8
|
+
* it "mirrors the per-task graduated-resolution shape (lint-fix.ts)". This is
|
|
9
|
+
* that ladder, written once.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* two had actually drifted.
|
|
11
|
+
* Both prompts instruct the marker their pass parses: `LINT-FIX: DONE` /
|
|
12
|
+
* `LINT-FIX: BLOCKED <why>` and `FINAL-GATE-FIX: DONE` / `FINAL-GATE-FIX:
|
|
13
|
+
* BLOCKED <why>`.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* measured), and the user was told `did not converge: <health.reason>` instead
|
|
22
|
-
* of the child's own stated reason. The suite fed `'LINT-FIX: DONE'` as fake
|
|
23
|
-
* output, so it stayed green whether the marker was parsed or deleted.
|
|
24
|
-
* - **The cancel rung re-typed its constant.** `lint-fix.ts` compared against a
|
|
25
|
-
* literal `'__user_cancelled__'`; it was the only production site in `src/` not
|
|
26
|
-
* importing `USER_CANCELLED`.
|
|
27
|
-
*
|
|
28
|
-
* What stays per-site: the arbiter (a gate re-run vs a repo-health re-run), the
|
|
29
|
-
* result shape, and the guard sets. Only the child call is shared.
|
|
15
|
+
* What stays per-site: the arbiter, the result shape, and the guard sets. Only
|
|
16
|
+
* the child call is shared. The arbiters differ in kind — `final-gate-fix` calls
|
|
17
|
+
* `deps.gate`, `lint-fix` calls `deps.repoHealth` — and so does what BLOCKED
|
|
18
|
+
* buys: `final-gate-fix` skips its gate re-run on a blocked child, while
|
|
19
|
+
* `lint-fix` runs repo-health regardless and uses the marker only to word the
|
|
20
|
+
* failure.
|
|
30
21
|
*/
|
|
31
22
|
import { USER_CANCELLED } from './child-runner.js';
|
|
32
23
|
/**
|
|
33
24
|
* Parse a fix child's final marker. Last match wins: the model reasons before
|
|
34
|
-
* concluding, and
|
|
35
|
-
*
|
|
36
|
-
*
|
|
25
|
+
* concluding, and both passes give the child `bash`, so its own command output is
|
|
26
|
+
* in the text being scraped.
|
|
27
|
+
*
|
|
28
|
+
* No marker → DONE. Neither pass treats the marker as the verdict — the arbiter
|
|
29
|
+
* decides — so a missing marker costs at most the blocked early-out in
|
|
30
|
+
* `final-gate-fix`, and nothing at all in `lint-fix`.
|
|
37
31
|
*/
|
|
38
32
|
export function parseFixMarker(marker, text) {
|
|
39
33
|
const re = new RegExp(`${marker}:\\s*(DONE|BLOCKED)\\b[ \\t]*(.*)`, 'gi');
|
|
@@ -18,8 +18,9 @@ export interface ForeignPathFinding {
|
|
|
18
18
|
* `src/client/api.ts`). Returns the resolved repo-relative path, or null.
|
|
19
19
|
*
|
|
20
20
|
* This mirrors how the tools that CONSUME these paths (vite/tsconfig aliases,
|
|
21
|
-
* bundler resolvers) look them up
|
|
22
|
-
*
|
|
21
|
+
* bundler resolvers) look them up. Without it an extensionless leak is missed:
|
|
22
|
+
* measured here, `src/task/foreign-path` resolves to `src/task/foreign-path.ts`,
|
|
23
|
+
* and `src/nope` resolves to null.
|
|
23
24
|
*/
|
|
24
25
|
export declare function resolveRepoPath(rel: string, exists: (rel: string) => boolean): string | null;
|
|
25
26
|
/**
|
|
@@ -30,9 +31,9 @@ export declare function resolveRepoPath(rel: string, exists: (rel: string) => bo
|
|
|
30
31
|
* synthetic tree.
|
|
31
32
|
*
|
|
32
33
|
* The tail search strips the FEWEST leading segments that still resolve, so the
|
|
33
|
-
* finding names the smallest foreign prefix
|
|
34
|
-
*
|
|
35
|
-
*
|
|
34
|
+
* finding names the smallest foreign prefix and the largest repo-relative target —
|
|
35
|
+
* the reading that matches how a mount shadows a tree. Measured:
|
|
36
|
+
* `/aaa/bbb/src/task/foreign-path.ts` reports prefix `/aaa/bbb`, not `/aaa`.
|
|
36
37
|
*/
|
|
37
38
|
export declare function findForeignPaths(lines: AddedLine[], existsOnHost: (abs: string) => boolean, existsInRepo: (rel: string) => boolean): ForeignPathFinding[];
|
|
38
39
|
/**
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** One unsatisfiable freeze/requires-edit pair found in a composed spec. */
|
|
2
2
|
export interface FrozenPathConflict {
|
|
3
|
-
/** The frozen path (normalized: no leading
|
|
3
|
+
/** The frozen path (normalized: no leading./, no trailing /). */
|
|
4
4
|
path: string;
|
|
5
5
|
/** The freeze line, verbatim (the `Do NOT modify` constraint). */
|
|
6
6
|
constraint: string;
|
|
@@ -20,17 +20,16 @@ export interface FrozenPathConflict {
|
|
|
20
20
|
* SPEC alone; research contributes only the statement side (live compose
|
|
21
21
|
* sometimes drops the research's "must also be included" nuance from the spec
|
|
22
22
|
* text while shipping the freeze and the file creation - the contradiction is
|
|
23
|
-
* then visible only across the compose boundary). Deterministic
|
|
24
|
-
* the
|
|
25
|
-
*
|
|
26
|
-
* nothing.
|
|
23
|
+
* then visible only across the compose boundary). Deterministic and pure text,
|
|
24
|
+
* so the model cannot self-report its way past it. Empty on a null spec or one
|
|
25
|
+
* that froze nothing.
|
|
27
26
|
*/
|
|
28
27
|
export declare function findFrozenPathConflicts(spec: string | null | undefined, research?: string | null): FrozenPathConflict[];
|
|
29
28
|
/**
|
|
30
|
-
* The forced critique-rewrite defect text
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
29
|
+
* The forced critique-rewrite defect text: MANDATORY, self-contained, and it
|
|
30
|
+
* names the exact resolution options. Only two are permitted — scoped ownership
|
|
31
|
+
* or dropping the creation — and prose acknowledging the gap is called out as a
|
|
32
|
+
* non-resolution, because that is the shape a model reaches for first and it
|
|
33
|
+
* leaves the contradiction intact.
|
|
35
34
|
*/
|
|
36
35
|
export declare function frozenConflictProbeText(conflicts: FrozenPathConflict[]): string;
|
|
@@ -1,54 +1,50 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* frozen-conflict — deterministic detection of an UNSATISFIABLE spec pair at
|
|
3
|
-
* compose time
|
|
3
|
+
* compose time.
|
|
4
4
|
*
|
|
5
|
-
* The
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* `bun run lint` hard-errors REPO-WIDE and permanently — and the "owning"
|
|
14
|
-
* steps 1–2 completed long ago, so NO task may ever perform the edit (every
|
|
15
|
-
* spec carries the same freeze). Every subsequent task then burned its
|
|
16
|
-
* unattended AUTOFIX rounds on a repo-health FAIL none of them was allowed to
|
|
17
|
-
* fix, and the eventual "escape" was a child DELETING the deliverables.
|
|
5
|
+
* The shape: a spec blanket-freezes a config file while its own deliverable
|
|
6
|
+
* needs exactly the registration edit that freeze forbids, and the
|
|
7
|
+
* contradiction is "resolved" in prose ("Accept that it will not be covered by
|
|
8
|
+
* `tsc --noEmit` since `tsconfig.json` is not modified in this step"). A typed
|
|
9
|
+
* linter accepts nothing. The moment the created files land the repo-wide
|
|
10
|
+
* static check fails PERMANENTLY, and because the step that owns the frozen
|
|
11
|
+
* file has already completed, no later task is allowed to fix it either — every
|
|
12
|
+
* one of them burns its autofix rounds on a defect none of them may touch.
|
|
18
13
|
*
|
|
19
|
-
* The contradiction is visible IN THE COMPOSED TEXT ITSELF, so it
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
14
|
+
* The contradiction is visible IN THE COMPOSED TEXT ITSELF, so it dies at spec
|
|
15
|
+
* time: the detector is deterministic and its finding is FORCED into the
|
|
16
|
+
* critique rewrite, which must either grant scoped ownership ("MAY edit `X`
|
|
17
|
+
* ONLY to register the files this task creates") or drop the file creation.
|
|
18
|
+
*
|
|
19
|
+
* High-precision by construction. Each rule below was run against the detector:
|
|
25
20
|
*
|
|
26
|
-
* High-precision by construction (FP-swept over the 26 real mx5 run-12 specs):
|
|
27
21
|
* - the freeze side must be BLANKET — a `Do NOT modify` line with no
|
|
28
|
-
* exception clause
|
|
29
|
-
*
|
|
30
|
-
* and
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
22
|
+
* exception clause. A scoped freeze is already the resolution shape and
|
|
23
|
+
* must never re-fire; "… except to add …", "You MAY edit `X` ONLY to
|
|
24
|
+
* register …" and "Only edit `X` (…)" each yield zero against a statement
|
|
25
|
+
* that otherwise fires;
|
|
26
|
+
* - the statement side is judged per SENTENCE, not per line, because real
|
|
27
|
+
* GOALs are one giant line. Measured: a line carrying the GOAL, a
|
|
28
|
+
* response-shape "must include `id` and `name`", and a path mention yields
|
|
29
|
+
* nothing, while the same line shape carrying a real registration sentence
|
|
30
|
+
* yields one;
|
|
31
|
+
* - a prohibition-shaped sentence ("Preserve … do not remove or modify …") is
|
|
32
|
+
* the freeze side restated and yields nothing;
|
|
33
|
+
* - the sentence must NAME the frozen path AND match one of the phrasing
|
|
34
|
+
* families. All six fire: passive registration, unless-added,
|
|
35
|
+
* not-checked-unless, "requires adding … to", "must add … to", and the
|
|
36
|
+
* surrender pair.
|
|
37
|
+
*
|
|
38
|
+
* Mere co-mention never fires: "The build reads `tsconfig.json` at startup."
|
|
39
|
+
* yields nothing.
|
|
43
40
|
*/
|
|
44
41
|
import { extractProhibitions, PROHIBITION_RE } from './prohibition-probe.js';
|
|
45
42
|
import { pathNamedIn } from './frozen-path-guard.js';
|
|
46
43
|
/**
|
|
47
44
|
* A freeze that carves out its own exception is SCOPED, not blanket — it is
|
|
48
|
-
* exactly the resolution shape the probe demands
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* the recomposed spec would re-fire forever.
|
|
45
|
+
* exactly the resolution shape the probe demands, so it never counts as the
|
|
46
|
+
* freeze side of a conflict. Without this the recomposed spec would re-fire
|
|
47
|
+
* forever on its own fix.
|
|
52
48
|
*/
|
|
53
49
|
const EXCEPTION_RE = /\b(?:except|unless|beyond|other\s+than|apart\s+from|only\s+(?:to|for|if|when|where|edit|modify|change|touch|update)|may\s+(?:edit|modify|change|update|add))\b/i;
|
|
54
50
|
/** Passive registration: "must (also) be included/added/registered/…". */
|
|
@@ -58,13 +54,13 @@ const UNLESS_ADDED_RE = /\bunless\s+(?:it\s+is\s+|it'?s\s+|they\s+are\s+|first\s
|
|
|
58
54
|
/** "won't be type-checked/compiled/linted/covered … unless …". */
|
|
59
55
|
const NOT_CHECKED_UNLESS_RE = /\b(?:won'?t|will\s+not|cannot|can'?t|does\s+not|doesn'?t|is\s+not|isn'?t)\s+(?:be\s+)?[\w\s-]{0,40}?(?:type-?check|compil|lint|cover|resolv|recogni[sz]|includ|pick)\w*[^;]{0,80}?\bunless\b/i;
|
|
60
56
|
/** Directional active: "requires adding … to …" / "must add … to/into/in …".
|
|
61
|
-
* The preposition
|
|
62
|
-
*
|
|
57
|
+
* The preposition is what keeps a response-shape sentence from counting as a
|
|
58
|
+
* registration edit — measured, "The response must include `tsconfig.json`."
|
|
59
|
+
* yields nothing while "You must add the new entry to `tsconfig.json`." fires. */
|
|
63
60
|
const REQUIRES_DIRECTIONAL_RE = /\brequires?\s+(?:add|includ|regist|updat|edit|modify|chang)\w*[^;]{0,80}?\b(?:to|into|in)\b/i;
|
|
64
61
|
const MUST_ADD_DIRECTIONAL_RE = /\bmust\s+(?:also\s+)?(?:add|includ|regist|updat)\w*[^;]{0,80}?\b(?:to|into|in)\b/i;
|
|
65
62
|
/** The prose-surrender pair: an artifact "will not be covered/type-checked/…"
|
|
66
|
-
* BECAUSE the (frozen) path "is not modified".
|
|
67
|
-
* this is the exact contradiction shape the live TASK_0020 spec shipped. */
|
|
63
|
+
* BECAUSE the (frozen) path "is not modified". BOTH halves must be present. */
|
|
68
64
|
const NOT_COVERED_RE = /\b(?:will\s+not|won'?t|cannot|can'?t|is\s+not|isn'?t)\s+(?:be\s+)?(?:covered|type-?checked|checked|compiled|linted|validated|included)\b/i;
|
|
69
65
|
const BECAUSE_NOT_MODIFIED_RE = /\b(?:since|because|as)\b[^;]{0,80}?\b(?:is\s+|are\s+|was\s+|were\s+)?not\s+(?:be(?:ing)?\s+)?(?:modif|edit|chang|updat|touch)\w*/i;
|
|
70
66
|
function isRequiresEditStatement(sentence) {
|
|
@@ -77,16 +73,18 @@ function isRequiresEditStatement(sentence) {
|
|
|
77
73
|
}
|
|
78
74
|
/**
|
|
79
75
|
* Split a spec line into sentences: a `.` or `;` followed by whitespace and a
|
|
80
|
-
* capital
|
|
81
|
-
* keeps `e.g. foo` and mid-path dots intact
|
|
82
|
-
*
|
|
83
|
-
* scannable without cross-sentence false fires.
|
|
76
|
+
* capital, backtick or bracket opener ends a sentence. The opener requirement
|
|
77
|
+
* keeps `e.g. foo` and mid-path dots intact — measured, a sentence containing
|
|
78
|
+
* "e.g." still matches as one piece. Judging per sentence is what makes
|
|
79
|
+
* one-giant-line GOALs scannable without cross-sentence false fires.
|
|
84
80
|
*/
|
|
85
81
|
function splitSentences(line) {
|
|
86
82
|
return line.split(/[.;]\s+(?=[A-Z`([-])/);
|
|
87
83
|
}
|
|
88
|
-
/** Backtick-quoted path-shaped tokens in a sentence
|
|
89
|
-
*
|
|
84
|
+
/** Backtick-quoted path-shaped tokens in a sentence, minus surrounding quotes.
|
|
85
|
+
* The same three-way test `looksLikePath` applies in prohibition-probe.ts:
|
|
86
|
+
* path characters only, and either a separator, an extension, or a leading
|
|
87
|
+
* dot. */
|
|
90
88
|
function pathTokensIn(sentence) {
|
|
91
89
|
const out = [];
|
|
92
90
|
for (const m of sentence.matchAll(/`([^`]+)`/g)) {
|
|
@@ -103,11 +101,11 @@ function pathTokensIn(sentence) {
|
|
|
103
101
|
* frozen path, appending each new pair to `out`.
|
|
104
102
|
*
|
|
105
103
|
* `anchorSpec` (research scans only): a research statement counts ONLY when,
|
|
106
|
-
* besides the frozen path, it names at least one other path that still
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* the spec
|
|
110
|
-
*
|
|
104
|
+
* besides the frozen path, it names at least one other path that still appears
|
|
105
|
+
* in the SPEC. That anchor is what makes resolution (b) terminal — measured,
|
|
106
|
+
* the same research sentence fires while the spec still creates the file and
|
|
107
|
+
* goes quiet once the spec no longer mentions it, instead of re-firing forever
|
|
108
|
+
* on stale research. */
|
|
111
109
|
function scanForStatements(text, blanket, source, out, seen, anchorSpec) {
|
|
112
110
|
for (const raw of text.split('\n')) {
|
|
113
111
|
for (const fragment of splitSentences(raw)) {
|
|
@@ -146,10 +144,9 @@ function scanForStatements(text, blanket, source, out, seen, anchorSpec) {
|
|
|
146
144
|
* SPEC alone; research contributes only the statement side (live compose
|
|
147
145
|
* sometimes drops the research's "must also be included" nuance from the spec
|
|
148
146
|
* text while shipping the freeze and the file creation - the contradiction is
|
|
149
|
-
* then visible only across the compose boundary). Deterministic
|
|
150
|
-
* the
|
|
151
|
-
*
|
|
152
|
-
* nothing.
|
|
147
|
+
* then visible only across the compose boundary). Deterministic and pure text,
|
|
148
|
+
* so the model cannot self-report its way past it. Empty on a null spec or one
|
|
149
|
+
* that froze nothing.
|
|
153
150
|
*/
|
|
154
151
|
export function findFrozenPathConflicts(spec, research) {
|
|
155
152
|
if (!spec)
|
|
@@ -171,11 +168,11 @@ export function findFrozenPathConflicts(spec, research) {
|
|
|
171
168
|
return out;
|
|
172
169
|
}
|
|
173
170
|
/**
|
|
174
|
-
* The forced critique-rewrite defect text
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
171
|
+
* The forced critique-rewrite defect text: MANDATORY, self-contained, and it
|
|
172
|
+
* names the exact resolution options. Only two are permitted — scoped ownership
|
|
173
|
+
* or dropping the creation — and prose acknowledging the gap is called out as a
|
|
174
|
+
* non-resolution, because that is the shape a model reaches for first and it
|
|
175
|
+
* leaves the contradiction intact.
|
|
179
176
|
*/
|
|
180
177
|
export function frozenConflictProbeText(conflicts) {
|
|
181
178
|
const items = conflicts.map(c => `- the spec FREEZES \`${c.path}\` ("${c.constraint.slice(0, 160)}") yet `
|
|
@@ -5,19 +5,24 @@ export type FrozenGit = (args: string[]) => Promise<{
|
|
|
5
5
|
}>;
|
|
6
6
|
/**
|
|
7
7
|
* The concrete paths the spec forbids modifying, normalized and de-duplicated —
|
|
8
|
-
* the
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* `extractProhibitions`, the same extraction the verify prohibition probe
|
|
9
|
+
* (gate-deps.ts) and the compose-time conflict detector (frozen-conflict.ts)
|
|
10
|
+
* consume, so "frozen" means one thing across the gates.
|
|
11
|
+
*
|
|
12
|
+
* Normalisation strips a leading `./` and a trailing `/`: measured, a spec
|
|
13
|
+
* banning `` `./src/a.ts` `` and `` `src/b/` `` yields `src/a.ts` and `src/b`.
|
|
14
|
+
* A null spec, or one with no modification-ban line naming a path, yields an
|
|
15
|
+
* empty list and the guard is a no-op by construction.
|
|
12
16
|
*/
|
|
13
17
|
export declare function frozenPathsFromSpec(spec: string | null | undefined): string[];
|
|
14
18
|
/**
|
|
15
|
-
* Does this prose
|
|
16
|
-
* sides
|
|
17
|
-
* and a bare mention
|
|
18
|
-
* (a different file)
|
|
19
|
-
* compose-time unsatisfiable-pair
|
|
20
|
-
* non-convergence trace, so "the
|
|
19
|
+
* Does this prose or tool-output text NAME the given path? Word-bounded on both
|
|
20
|
+
* sides. Measured against `tsconfig.json`: `` `tsconfig.json` ``,
|
|
21
|
+
* `(tsconfig.json:18)` and a bare mention all match; `foo.tsconfig.json`,
|
|
22
|
+
* `config/tsconfig.json` (a different file), `tsconfig.json5` and
|
|
23
|
+
* `tsconfig.json.bak` all do not. Shared by the compose-time unsatisfiable-pair
|
|
24
|
+
* detector (frozen-conflict.ts) and lint-fix's non-convergence trace, so "the
|
|
25
|
+
* text names a frozen path" means one thing.
|
|
21
26
|
*/
|
|
22
27
|
export declare function pathNamedIn(text: string, path: string): boolean;
|
|
23
28
|
/**
|
|
@@ -26,6 +31,10 @@ export declare function pathNamedIn(text: string, path: string): boolean;
|
|
|
26
31
|
* anything must be reverted at all. A rename line (`R old -> new`) yields the NEW
|
|
27
32
|
* path — the side that carries the child's write. Deterministic and pure so the
|
|
28
33
|
* parsing is unit-tested without a real repo.
|
|
34
|
+
*
|
|
35
|
+
* Every shape below was taken from real `git status --porcelain` output, not
|
|
36
|
+
* assumed: ` M path`, ` D path`, `?? path`, `R old -> new`, and a path
|
|
37
|
+
* containing a space, which git emits wrapped in double quotes.
|
|
29
38
|
*/
|
|
30
39
|
export declare function parseChangedFrozenFiles(porcelain: string): string[];
|
|
31
40
|
/**
|
|
@@ -36,10 +45,22 @@ export declare function parseChangedFrozenFiles(porcelain: string): string[];
|
|
|
36
45
|
* Runs AFTER the task's own work is committed (HEAD), so "restore to HEAD" keeps
|
|
37
46
|
* the verified task's version of the frozen file and discards ONLY the gate
|
|
38
47
|
* child's edit on top of it — the task's own frozen-path edits, if any, are a
|
|
39
|
-
* separate concern the verify prohibition
|
|
40
|
-
* covers modified
|
|
41
|
-
*
|
|
42
|
-
* the frozen pathspec
|
|
48
|
+
* separate concern the verify prohibition probe surfaces. `git checkout -f HEAD`
|
|
49
|
+
* covers modified and deleted tracked files under each pathspec; `git clean -fdq`
|
|
50
|
+
* removes untracked files the pass created under a frozen directory. Both are
|
|
51
|
+
* scoped to the frozen pathspec.
|
|
52
|
+
*
|
|
53
|
+
* Run against a real repo with one frozen directory and one free one: a modified
|
|
54
|
+
* file came back to its HEAD content, a deleted file came back, and two untracked
|
|
55
|
+
* creations (one with a space in its name) were removed, while an edit to a file
|
|
56
|
+
* OUTSIDE the pathspec survived untouched.
|
|
57
|
+
*
|
|
58
|
+
* ONE CASE IS NOT FULLY UNDONE: a rename already STAGED in the index. `git mv`
|
|
59
|
+
* inside the frozen directory leaves `frozen/new.txt` present and staged after
|
|
60
|
+
* both commands, because checkout cannot restore a path HEAD does not contain and
|
|
61
|
+
* clean skips tracked files — while this function still reports it as reverted.
|
|
62
|
+
* An ordinary edit-tool rename is a delete plus an untracked create, and that IS
|
|
63
|
+
* fully undone; staging requires git, which the enforce child does not have.
|
|
43
64
|
*
|
|
44
65
|
* Best-effort: an empty frozen list, a non-git tree, or any git error yields an
|
|
45
66
|
* empty result — the guard must never break the gate on a project it cannot reason
|
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* frozen-path-guard — deterministic write-deny on spec-frozen paths for the
|
|
3
|
-
* write-capable gate children
|
|
3
|
+
* write-capable gate children, the enforce EDIT pass especially.
|
|
4
4
|
*
|
|
5
|
-
* The failure class
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* frozen contract is silently mutated by the very pass meant to police the work.
|
|
5
|
+
* The failure class: a spec's CONSTRAINTS pin a path as off-limits ("**Do NOT
|
|
6
|
+
* modify** `src/server/index.ts`"), and a later write-enabled GATE pass edits it
|
|
7
|
+
* anyway. The enforce child runs with `ENFORCE_TOOLS = 'read,edit'`, its edits
|
|
8
|
+
* are judged only for guideline compliance, and they are then committed as an
|
|
9
|
+
* `ENFORCE GUIDELINES` snapshot on top of the verified task — so the frozen
|
|
10
|
+
* contract gets mutated by the very pass meant to police the work.
|
|
12
11
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* interception (only tool-NAME allow/deny), so the achievable, thrash-free,
|
|
20
|
-
* stack-agnostic realization of a tool-layer deny is this: let the pass edit
|
|
21
|
-
* freely, then deterministically UNDO any frozen-path change it made before those
|
|
22
|
-
* edits can be committed. The violating write never lands in a commit, regardless
|
|
23
|
-
* of what the model intended — no model in the loop, same discipline as
|
|
24
|
-
* git-state-guard.
|
|
12
|
+
* A tool-layer deny is not available. pi 0.84.4 offers `--tools` and
|
|
13
|
+
* `--exclude-tools`, both allow/deny by tool NAME; no flag scopes an edit to a
|
|
14
|
+
* path. A chmod-style physical deny would leave the child thrashing on a bare
|
|
15
|
+
* EACCES, and the enforce child has NO WALL CLOCK to stop it — the `gate` row of
|
|
16
|
+
* WORKER_PROFILES sets `worker-timeout` to `{timeoutMs: 0}`, leaving only a
|
|
17
|
+
* per-command watchdog and a stream watchdog.
|
|
25
18
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
19
|
+
* So the achievable deny is after the fact: let the pass edit freely, then
|
|
20
|
+
* deterministically UNDO any frozen-path change before those edits can be
|
|
21
|
+
* committed. No model is in the loop, the same discipline as git-state-guard.
|
|
22
|
+
*
|
|
23
|
+
* Everything degrades to a no-op when the spec froze nothing — a single-`/task`
|
|
24
|
+
* run, or a spec with no `Do NOT modify` line naming a path — and on any git
|
|
25
|
+
* error. Pure git shape, zero stack assumptions: a frozen path exists for a CLI,
|
|
26
|
+
* a library or a script collection exactly as for a web app.
|
|
31
27
|
*/
|
|
32
28
|
import { extractProhibitions } from './prohibition-probe.js';
|
|
33
29
|
/**
|
|
34
30
|
* The concrete paths the spec forbids modifying, normalized and de-duplicated —
|
|
35
|
-
* the
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
31
|
+
* `extractProhibitions`, the same extraction the verify prohibition probe
|
|
32
|
+
* (gate-deps.ts) and the compose-time conflict detector (frozen-conflict.ts)
|
|
33
|
+
* consume, so "frozen" means one thing across the gates.
|
|
34
|
+
*
|
|
35
|
+
* Normalisation strips a leading `./` and a trailing `/`: measured, a spec
|
|
36
|
+
* banning `` `./src/a.ts` `` and `` `src/b/` `` yields `src/a.ts` and `src/b`.
|
|
37
|
+
* A null spec, or one with no modification-ban line naming a path, yields an
|
|
38
|
+
* empty list and the guard is a no-op by construction.
|
|
39
39
|
*/
|
|
40
40
|
export function frozenPathsFromSpec(spec) {
|
|
41
41
|
if (!spec)
|
|
@@ -50,12 +50,13 @@ export function frozenPathsFromSpec(spec) {
|
|
|
50
50
|
}
|
|
51
51
|
const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
52
52
|
/**
|
|
53
|
-
* Does this prose
|
|
54
|
-
* sides
|
|
55
|
-
* and a bare mention
|
|
56
|
-
* (a different file)
|
|
57
|
-
* compose-time unsatisfiable-pair
|
|
58
|
-
* non-convergence trace, so "the
|
|
53
|
+
* Does this prose or tool-output text NAME the given path? Word-bounded on both
|
|
54
|
+
* sides. Measured against `tsconfig.json`: `` `tsconfig.json` ``,
|
|
55
|
+
* `(tsconfig.json:18)` and a bare mention all match; `foo.tsconfig.json`,
|
|
56
|
+
* `config/tsconfig.json` (a different file), `tsconfig.json5` and
|
|
57
|
+
* `tsconfig.json.bak` all do not. Shared by the compose-time unsatisfiable-pair
|
|
58
|
+
* detector (frozen-conflict.ts) and lint-fix's non-convergence trace, so "the
|
|
59
|
+
* text names a frozen path" means one thing.
|
|
59
60
|
*/
|
|
60
61
|
export function pathNamedIn(text, path) {
|
|
61
62
|
const p = path.replace(/^\.\//, '').replace(/\/+$/, '');
|
|
@@ -69,6 +70,10 @@ export function pathNamedIn(text, path) {
|
|
|
69
70
|
* anything must be reverted at all. A rename line (`R old -> new`) yields the NEW
|
|
70
71
|
* path — the side that carries the child's write. Deterministic and pure so the
|
|
71
72
|
* parsing is unit-tested without a real repo.
|
|
73
|
+
*
|
|
74
|
+
* Every shape below was taken from real `git status --porcelain` output, not
|
|
75
|
+
* assumed: ` M path`, ` D path`, `?? path`, `R old -> new`, and a path
|
|
76
|
+
* containing a space, which git emits wrapped in double quotes.
|
|
72
77
|
*/
|
|
73
78
|
export function parseChangedFrozenFiles(porcelain) {
|
|
74
79
|
const out = [];
|
|
@@ -104,10 +109,22 @@ export function parseChangedFrozenFiles(porcelain) {
|
|
|
104
109
|
* Runs AFTER the task's own work is committed (HEAD), so "restore to HEAD" keeps
|
|
105
110
|
* the verified task's version of the frozen file and discards ONLY the gate
|
|
106
111
|
* child's edit on top of it — the task's own frozen-path edits, if any, are a
|
|
107
|
-
* separate concern the verify prohibition
|
|
108
|
-
* covers modified
|
|
109
|
-
*
|
|
110
|
-
* the frozen pathspec
|
|
112
|
+
* separate concern the verify prohibition probe surfaces. `git checkout -f HEAD`
|
|
113
|
+
* covers modified and deleted tracked files under each pathspec; `git clean -fdq`
|
|
114
|
+
* removes untracked files the pass created under a frozen directory. Both are
|
|
115
|
+
* scoped to the frozen pathspec.
|
|
116
|
+
*
|
|
117
|
+
* Run against a real repo with one frozen directory and one free one: a modified
|
|
118
|
+
* file came back to its HEAD content, a deleted file came back, and two untracked
|
|
119
|
+
* creations (one with a space in its name) were removed, while an edit to a file
|
|
120
|
+
* OUTSIDE the pathspec survived untouched.
|
|
121
|
+
*
|
|
122
|
+
* ONE CASE IS NOT FULLY UNDONE: a rename already STAGED in the index. `git mv`
|
|
123
|
+
* inside the frozen directory leaves `frozen/new.txt` present and staged after
|
|
124
|
+
* both commands, because checkout cannot restore a path HEAD does not contain and
|
|
125
|
+
* clean skips tracked files — while this function still reports it as reverted.
|
|
126
|
+
* An ordinary edit-tool rename is a delete plus an untracked create, and that IS
|
|
127
|
+
* fully undone; staging requires git, which the enforce child does not have.
|
|
111
128
|
*
|
|
112
129
|
* Best-effort: an empty frozen list, a non-git tree, or any git error yields an
|
|
113
130
|
* empty result — the guard must never break the gate on a project it cannot reason
|