@miller-tech/uap 2.11.1 → 2.16.4
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/config/capacity-policy.json +15 -3
- package/config/model-profiles/qwen38.json +42 -34
- package/dist/.tsbuildinfo +1 -1
- package/dist/bin/cli.js +39 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/capacity/policy.d.ts +15 -0
- package/dist/capacity/policy.d.ts.map +1 -1
- package/dist/capacity/policy.js +23 -0
- package/dist/capacity/policy.js.map +1 -1
- package/dist/capacity/probe.d.ts.map +1 -1
- package/dist/capacity/probe.js +6 -1
- package/dist/capacity/probe.js.map +1 -1
- package/dist/cli/deliver.d.ts.map +1 -1
- package/dist/cli/deliver.js +148 -2
- package/dist/cli/deliver.js.map +1 -1
- package/dist/cli/inference.d.ts +13 -0
- package/dist/cli/inference.d.ts.map +1 -0
- package/dist/cli/inference.js +132 -0
- package/dist/cli/inference.js.map +1 -0
- package/dist/cli/loops.d.ts +39 -0
- package/dist/cli/loops.d.ts.map +1 -0
- package/dist/cli/loops.js +154 -0
- package/dist/cli/loops.js.map +1 -0
- package/dist/cli/wizard-config.d.ts.map +1 -1
- package/dist/cli/wizard-config.js +5 -1
- package/dist/cli/wizard-config.js.map +1 -1
- package/dist/cli/worktree.d.ts.map +1 -1
- package/dist/cli/worktree.js +8 -4
- package/dist/cli/worktree.js.map +1 -1
- package/dist/delivery/adversarial-attack.d.ts +99 -0
- package/dist/delivery/adversarial-attack.d.ts.map +1 -0
- package/dist/delivery/adversarial-attack.js +326 -0
- package/dist/delivery/adversarial-attack.js.map +1 -0
- package/dist/delivery/adversarial-gate.d.ts +120 -0
- package/dist/delivery/adversarial-gate.d.ts.map +1 -0
- package/dist/delivery/adversarial-gate.js +259 -0
- package/dist/delivery/adversarial-gate.js.map +1 -0
- package/dist/delivery/adversarial-sanction.d.ts +52 -0
- package/dist/delivery/adversarial-sanction.d.ts.map +1 -0
- package/dist/delivery/adversarial-sanction.js +134 -0
- package/dist/delivery/adversarial-sanction.js.map +1 -0
- package/dist/delivery/agentic-executor.d.ts +69 -22
- package/dist/delivery/agentic-executor.d.ts.map +1 -1
- package/dist/delivery/agentic-executor.js +152 -8
- package/dist/delivery/agentic-executor.js.map +1 -1
- package/dist/delivery/applier.d.ts +8 -0
- package/dist/delivery/applier.d.ts.map +1 -1
- package/dist/delivery/applier.js +3 -1
- package/dist/delivery/applier.js.map +1 -1
- package/dist/delivery/convergence-loop.d.ts +15 -0
- package/dist/delivery/convergence-loop.d.ts.map +1 -1
- package/dist/delivery/convergence-loop.js.map +1 -1
- package/dist/delivery/criteria-lint.d.ts +74 -0
- package/dist/delivery/criteria-lint.d.ts.map +1 -0
- package/dist/delivery/criteria-lint.js +134 -0
- package/dist/delivery/criteria-lint.js.map +1 -0
- package/dist/delivery/deliver-toggle.d.ts +21 -0
- package/dist/delivery/deliver-toggle.d.ts.map +1 -0
- package/dist/delivery/deliver-toggle.js +40 -0
- package/dist/delivery/deliver-toggle.js.map +1 -0
- package/dist/delivery/delivery-evidence.d.ts +109 -0
- package/dist/delivery/delivery-evidence.d.ts.map +1 -0
- package/dist/delivery/delivery-evidence.js +139 -0
- package/dist/delivery/delivery-evidence.js.map +1 -0
- package/dist/delivery/epic-mission.d.ts +5 -1
- package/dist/delivery/epic-mission.d.ts.map +1 -1
- package/dist/delivery/epic-mission.js +34 -6
- package/dist/delivery/epic-mission.js.map +1 -1
- package/dist/delivery/execution-gate.d.ts.map +1 -1
- package/dist/delivery/execution-gate.js +90 -7
- package/dist/delivery/execution-gate.js.map +1 -1
- package/dist/delivery/index.d.ts +9 -1
- package/dist/delivery/index.d.ts.map +1 -1
- package/dist/delivery/index.js +9 -1
- package/dist/delivery/index.js.map +1 -1
- package/dist/delivery/journey-depth.d.ts +61 -0
- package/dist/delivery/journey-depth.d.ts.map +1 -0
- package/dist/delivery/journey-depth.js +91 -0
- package/dist/delivery/journey-depth.js.map +1 -0
- package/dist/delivery/master-pipeline.d.ts +50 -0
- package/dist/delivery/master-pipeline.d.ts.map +1 -0
- package/dist/delivery/master-pipeline.js +52 -0
- package/dist/delivery/master-pipeline.js.map +1 -0
- package/dist/delivery/mission-acceptance.d.ts.map +1 -1
- package/dist/delivery/mission-acceptance.js +54 -2
- package/dist/delivery/mission-acceptance.js.map +1 -1
- package/dist/delivery/orchestrated-mission.d.ts +4 -1
- package/dist/delivery/orchestrated-mission.d.ts.map +1 -1
- package/dist/delivery/orchestrated-mission.js +18 -9
- package/dist/delivery/orchestrated-mission.js.map +1 -1
- package/dist/delivery/plan-check.d.ts +1 -0
- package/dist/delivery/plan-check.d.ts.map +1 -1
- package/dist/delivery/plan-check.js +48 -0
- package/dist/delivery/plan-check.js.map +1 -1
- package/dist/delivery/task-orchestrator.d.ts +16 -9
- package/dist/delivery/task-orchestrator.d.ts.map +1 -1
- package/dist/delivery/task-orchestrator.js +4 -2
- package/dist/delivery/task-orchestrator.js.map +1 -1
- package/dist/delivery/task-workspace.d.ts +35 -5
- package/dist/delivery/task-workspace.d.ts.map +1 -1
- package/dist/delivery/task-workspace.js +53 -7
- package/dist/delivery/task-workspace.js.map +1 -1
- package/dist/delivery/test-oracle-additive.d.ts +26 -6
- package/dist/delivery/test-oracle-additive.d.ts.map +1 -1
- package/dist/delivery/test-oracle-additive.js +40 -15
- package/dist/delivery/test-oracle-additive.js.map +1 -1
- package/dist/delivery/user-validation.d.ts +14 -0
- package/dist/delivery/user-validation.d.ts.map +1 -1
- package/dist/delivery/user-validation.js +103 -9
- package/dist/delivery/user-validation.js.map +1 -1
- package/dist/delivery/verifier-ladder.d.ts.map +1 -1
- package/dist/delivery/verifier-ladder.js +24 -6
- package/dist/delivery/verifier-ladder.js.map +1 -1
- package/dist/inference/analysis.d.ts +138 -0
- package/dist/inference/analysis.d.ts.map +1 -0
- package/dist/inference/analysis.js +243 -0
- package/dist/inference/analysis.js.map +1 -0
- package/dist/inference/probe.d.ts +85 -0
- package/dist/inference/probe.d.ts.map +1 -0
- package/dist/inference/probe.js +403 -0
- package/dist/inference/probe.js.map +1 -0
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js +45 -18
- package/dist/models/types.js.map +1 -1
- package/dist/self-tuning/profiles/qwen38.d.ts +17 -8
- package/dist/self-tuning/profiles/qwen38.d.ts.map +1 -1
- package/dist/self-tuning/profiles/qwen38.js +21 -11
- package/dist/self-tuning/profiles/qwen38.js.map +1 -1
- package/dist/utils/model-slots.d.ts +11 -5
- package/dist/utils/model-slots.d.ts.map +1 -1
- package/dist/utils/model-slots.js +11 -5
- package/dist/utils/model-slots.js.map +1 -1
- package/docs/INDEX.md +1 -0
- package/docs/guides/CAPACITY_POLICY.md +24 -0
- package/docs/guides/INFERENCE_HEALTH.md +184 -0
- package/docs/guides/PROXY.md +1 -0
- package/docs/guides/QWEN38_EXL3.md +268 -0
- package/docs/plans/hlg-master-architecture-uplift-2026-09-24.md +67 -0
- package/docs/reference/CONFIGURATION.md +10 -1
- package/docs/reference/CONFIGURATION_REFERENCE.md +14 -0
- package/package.json +2 -2
- package/scripts/lib/llama-upstream.sh +7 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/enforcers/__pycache__/expert_review_required.cpython-312.pyc +0 -0
- package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-312.pyc +0 -0
- package/src/policies/enforcers/expert_review_required.py +1 -4
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +374 -16
- package/tools/agents/scripts/confidence_escalation.py +4 -2
- package/tools/agents/scripts/project_telemetry.py +1 -0
- package/tools/agents/scripts/tool_risk.py +1 -0
- package/tools/agents/scripts/tool_risk_calibrate.py +1 -0
- package/tools/agents/scripts/toolcall_path_normalizer.py +1 -0
- package/tools/agents/tests/test_anthropic_proxy_streaming.py +52 -1
- package/tools/agents/tests/test_confidence_escalation.py +3 -2
- package/tools/agents/tests/test_count_tokens_scale_per_session.py +126 -0
- package/tools/agents/tests/test_expert_review_pr_scope.py +10 -11
- package/tools/agents/tests/test_lockstep_escalation.py +324 -0
- package/tools/agents/tests/test_thinking_template_kwargs.py +10 -4
|
@@ -32,6 +32,15 @@
|
|
|
32
32
|
* - `parallelTasks` should be sized to CPU cores, not inference slots: the
|
|
33
33
|
* model-slot lease bounds model calls, but concurrent GATE runs (npm
|
|
34
34
|
* test/build per worktree) have no governor.
|
|
35
|
+
*
|
|
36
|
+
* Parallel-by-default: since the default flip, an unset config resolves to
|
|
37
|
+
* DEFAULT_PARALLEL_TASKS (not 1) — see resolveParallelTasks. The safety
|
|
38
|
+
* property the historical sequential default protected (one writer to the
|
|
39
|
+
* working tree at a time) is now enforced STRUCTURALLY instead of by
|
|
40
|
+
* default: parallel dispatch only happens with worktree isolation active
|
|
41
|
+
* (runOrchestratedMission degrades to sequential, with a logged reason, when
|
|
42
|
+
* no workspace manager is available), and merge-backs are serialized under
|
|
43
|
+
* the caller's merge lock.
|
|
35
44
|
*/
|
|
36
45
|
import { execFileSync } from 'child_process';
|
|
37
46
|
import { copyFileSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readlinkSync, rmSync, statSync, symlinkSync, } from 'fs';
|
|
@@ -64,16 +73,53 @@ function sweepStaleWorkspaces() {
|
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
75
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
76
|
+
* Default fan-out when neither config nor env says otherwise. Parallel is the
|
|
77
|
+
* DEFAULT since the default flip: independent READY tasks run concurrently,
|
|
78
|
+
* each in its own detached git worktree (this module). The orchestrator's
|
|
79
|
+
* wave slice (`ready.slice(0, concurrency)`) already caps a wave at the
|
|
80
|
+
* number of independent READY tasks, so a small DAG never over-dispatches.
|
|
81
|
+
* Sized to a modest CPU budget, not inference slots (see the header notes).
|
|
82
|
+
*/
|
|
83
|
+
export const DEFAULT_PARALLEL_TASKS = 4;
|
|
84
|
+
/**
|
|
85
|
+
* Resolve the effective `deliver.parallelTasks` fan-out, clamped to [1, 8].
|
|
86
|
+
*
|
|
87
|
+
* Precedence: the `UAP_DELIVER_PARALLEL_TASKS` env var > the `.uap.json`
|
|
88
|
+
* `deliver.parallelTasks` value > DEFAULT_PARALLEL_TASKS. The env knob exists
|
|
89
|
+
* ONLY because parallel is now the default: the original config-only design
|
|
90
|
+
* barred env so one exported variable could never silently parallelize every
|
|
91
|
+
* run on a machine; that danger is gone (parallel is the default), and the
|
|
92
|
+
* env serves the safe direction — `UAP_DELIVER_PARALLEL_TASKS=1` forces
|
|
93
|
+
* sequential execution everywhere as an escape hatch, or retunes the cap.
|
|
94
|
+
* Set-but-unparseable values (either layer) fail SAFE to sequential; only an
|
|
95
|
+
* UNSET config falls through to the parallel default.
|
|
96
|
+
*
|
|
97
|
+
* Parallel dispatch additionally requires worktree isolation — see
|
|
98
|
+
* runOrchestratedMission, which degrades to sequential with a logged reason
|
|
99
|
+
* when no workspace manager is available. The resolved number alone never
|
|
100
|
+
* enables concurrency.
|
|
71
101
|
*/
|
|
72
|
-
export function resolveParallelTasks(raw) {
|
|
102
|
+
export function resolveParallelTasks(raw, env = process.env) {
|
|
103
|
+
const clamp = (n) => (n <= 1 ? 1 : Math.min(Math.floor(n), HARD_PARALLEL_CEILING));
|
|
104
|
+
const envRaw = env.UAP_DELIVER_PARALLEL_TASKS;
|
|
105
|
+
if (envRaw !== undefined && envRaw.trim() !== '') {
|
|
106
|
+
const n = Number(envRaw);
|
|
107
|
+
if (!Number.isFinite(n)) {
|
|
108
|
+
// Fail-safe must not be SILENT: an exported typo quietly pinning every
|
|
109
|
+
// run to sequential is exactly the surprise this knob was blamed for.
|
|
110
|
+
console.log(` task-workspace: UAP_DELIVER_PARALLEL_TASKS='${envRaw}' is not a number — forcing sequential (1)`);
|
|
111
|
+
return 1;
|
|
112
|
+
}
|
|
113
|
+
return clamp(n);
|
|
114
|
+
}
|
|
115
|
+
if (raw === undefined || raw === null)
|
|
116
|
+
return DEFAULT_PARALLEL_TASKS;
|
|
73
117
|
const n = Number(raw);
|
|
74
|
-
if (!Number.isFinite(n)
|
|
118
|
+
if (!Number.isFinite(n)) {
|
|
119
|
+
console.log(` task-workspace: deliver.parallelTasks=${JSON.stringify(raw)} is not a number — forcing sequential (1)`);
|
|
75
120
|
return 1;
|
|
76
|
-
|
|
121
|
+
}
|
|
122
|
+
return clamp(n);
|
|
77
123
|
}
|
|
78
124
|
function git(cwd, args, input, timeoutMs = 120_000) {
|
|
79
125
|
return execFileSync('git', args, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-workspace.js","sourceRoot":"","sources":["../../src/delivery/task-workspace.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"task-workspace.js","sourceRoot":"","sources":["../../src/delivery/task-workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,14 +29,34 @@
|
|
|
29
29
|
* Bounded honestly: appended MODULE-SCOPE code still executes before test
|
|
30
30
|
* callbacks run, so a deliberately adversarial append that patches the SUT's
|
|
31
31
|
* module cache can weaken old tests without tripping the denylist. The
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
32
|
+
* SUPPRESSOR/EXIT/ASSERT regexes themselves are evadable too — comment
|
|
33
|
+
* separators (`test./* *\/only(...)`) and computed access (`assert['equal']=`,
|
|
34
|
+
* Object.assign, Reflect.set) all slip past them; the rule is a
|
|
35
|
+
* gradient-drift control, NOT a boundary. And the hooks/mocks steering below
|
|
36
|
+
* is JS-runner-centric: under pytest's shared-session process, module-scope
|
|
37
|
+
* patching in a NEW test file (conftest-style monkeypatching, sys.modules
|
|
38
|
+
* edits) can still reach pre-existing tests. The durable control for these
|
|
39
|
+
* residuals is behavioral: compare the runner's per-test results against
|
|
40
|
+
* baseline (the ladder already captures per-test names) — tracked as
|
|
41
|
+
* follow-up. This rule closes the convergence-drift paths a model reaches by
|
|
42
|
+
* gradient, in every write layer, with ONE definition — a divergence between
|
|
43
|
+
* layers is how "two write paths, one guard" incidents happen.
|
|
38
44
|
*/
|
|
39
45
|
export declare function extractTestTitles(source: string): string[];
|
|
46
|
+
/**
|
|
47
|
+
* Delta-level refusal checks shared by the additive edit rule and by callers
|
|
48
|
+
* that sanction wholly NEW test files (the adversarial red-team gate):
|
|
49
|
+
* suppression modifiers, process.exit, and assertion-machinery reassignment.
|
|
50
|
+
*
|
|
51
|
+
* Deliberately EXCLUDES the file-scope hook/mock check (HOOK_OR_MOCK_RE) —
|
|
52
|
+
* that rule exists because an APPENDED `beforeEach`/`vi.mock` reaches the
|
|
53
|
+
* frozen tests above it. In a brand-new file hooks and mocks cannot touch any
|
|
54
|
+
* pre-existing test, which is exactly why the additive rule steers such tests
|
|
55
|
+
* into a new file. Callers sanctioning an APPEND must keep the hook/mock
|
|
56
|
+
* check (additiveTestEditRefusal does); callers sanctioning a NEW file use
|
|
57
|
+
* this helper alone.
|
|
58
|
+
*/
|
|
59
|
+
export declare function additiveTestDeltaRefusal(delta: string): string | null;
|
|
40
60
|
/**
|
|
41
61
|
* Null when replacing `oldContent` with `newContent` is a sanctioned ADDITIVE
|
|
42
62
|
* test edit; otherwise a short human-readable refusal reason.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-oracle-additive.d.ts","sourceRoot":"","sources":["../../src/delivery/test-oracle-additive.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"test-oracle-additive.d.ts","sourceRoot":"","sources":["../../src/delivery/test-oracle-additive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAqCH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAK1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWrE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0B7F;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMzE"}
|
|
@@ -29,12 +29,18 @@
|
|
|
29
29
|
* Bounded honestly: appended MODULE-SCOPE code still executes before test
|
|
30
30
|
* callbacks run, so a deliberately adversarial append that patches the SUT's
|
|
31
31
|
* module cache can weaken old tests without tripping the denylist. The
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
32
|
+
* SUPPRESSOR/EXIT/ASSERT regexes themselves are evadable too — comment
|
|
33
|
+
* separators (`test./* *\/only(...)`) and computed access (`assert['equal']=`,
|
|
34
|
+
* Object.assign, Reflect.set) all slip past them; the rule is a
|
|
35
|
+
* gradient-drift control, NOT a boundary. And the hooks/mocks steering below
|
|
36
|
+
* is JS-runner-centric: under pytest's shared-session process, module-scope
|
|
37
|
+
* patching in a NEW test file (conftest-style monkeypatching, sys.modules
|
|
38
|
+
* edits) can still reach pre-existing tests. The durable control for these
|
|
39
|
+
* residuals is behavioral: compare the runner's per-test results against
|
|
40
|
+
* baseline (the ladder already captures per-test names) — tracked as
|
|
41
|
+
* follow-up. This rule closes the convergence-drift paths a model reaches by
|
|
42
|
+
* gradient, in every write layer, with ONE definition — a divergence between
|
|
43
|
+
* layers is how "two write paths, one guard" incidents happen.
|
|
38
44
|
*/
|
|
39
45
|
/** Test-case titles: JS/TS (test/it/describe, incl. .each/.skip forms) and python (def test_*). */
|
|
40
46
|
const JS_TITLE_RE = /\b(?:test|it|describe)(?:\.\w+)*\s*\(\s*(['"`])((?:\\.|(?!\1).)*?)\1/g;
|
|
@@ -73,6 +79,31 @@ export function extractTestTitles(source) {
|
|
|
73
79
|
titles.push(m[1]);
|
|
74
80
|
return titles;
|
|
75
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Delta-level refusal checks shared by the additive edit rule and by callers
|
|
84
|
+
* that sanction wholly NEW test files (the adversarial red-team gate):
|
|
85
|
+
* suppression modifiers, process.exit, and assertion-machinery reassignment.
|
|
86
|
+
*
|
|
87
|
+
* Deliberately EXCLUDES the file-scope hook/mock check (HOOK_OR_MOCK_RE) —
|
|
88
|
+
* that rule exists because an APPENDED `beforeEach`/`vi.mock` reaches the
|
|
89
|
+
* frozen tests above it. In a brand-new file hooks and mocks cannot touch any
|
|
90
|
+
* pre-existing test, which is exactly why the additive rule steers such tests
|
|
91
|
+
* into a new file. Callers sanctioning an APPEND must keep the hook/mock
|
|
92
|
+
* check (additiveTestEditRefusal does); callers sanctioning a NEW file use
|
|
93
|
+
* this helper alone.
|
|
94
|
+
*/
|
|
95
|
+
export function additiveTestDeltaRefusal(delta) {
|
|
96
|
+
if ([...delta.matchAll(SUPPRESSOR_RE)].length > 0) {
|
|
97
|
+
return 'it adds test-suppression modifiers (.only/.skip/.todo/x*/f*/skip options), which silence existing tests while their titles remain';
|
|
98
|
+
}
|
|
99
|
+
if ([...delta.matchAll(EXIT_RE)].length > 0) {
|
|
100
|
+
return 'it adds process.exit, which can end the run before existing tests execute';
|
|
101
|
+
}
|
|
102
|
+
if ([...delta.matchAll(ASSERT_PATCH_RE)].length > 0) {
|
|
103
|
+
return 'it reassigns assertion machinery (assert/expect), which can neutralize existing tests';
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
76
107
|
/**
|
|
77
108
|
* Null when replacing `oldContent` with `newContent` is a sanctioned ADDITIVE
|
|
78
109
|
* test edit; otherwise a short human-readable refusal reason.
|
|
@@ -94,15 +125,9 @@ export function additiveTestEditRefusal(oldContent, newContent) {
|
|
|
94
125
|
if (delta.length > 0 && !/^\s/.test(delta)) {
|
|
95
126
|
return 'the appended content must start on a new line after the existing content';
|
|
96
127
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if ([...delta.matchAll(EXIT_RE)].length > 0) {
|
|
101
|
-
return 'it adds process.exit, which can end the run before existing tests execute';
|
|
102
|
-
}
|
|
103
|
-
if ([...delta.matchAll(ASSERT_PATCH_RE)].length > 0) {
|
|
104
|
-
return 'it reassigns assertion machinery (assert/expect), which can neutralize existing tests';
|
|
105
|
-
}
|
|
128
|
+
const deltaRefusal = additiveTestDeltaRefusal(delta);
|
|
129
|
+
if (deltaRefusal)
|
|
130
|
+
return deltaRefusal;
|
|
106
131
|
if ([...delta.matchAll(HOOK_OR_MOCK_RE)].length > 0) {
|
|
107
132
|
return ('it appends file-scope lifecycle hooks or module mocking (beforeEach/vi.mock/mock.method/…), ' +
|
|
108
133
|
'which affect the existing tests — put tests that need hooks or mocks in a NEW test file');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-oracle-additive.js","sourceRoot":"","sources":["../../src/delivery/test-oracle-additive.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"test-oracle-additive.js","sourceRoot":"","sources":["../../src/delivery/test-oracle-additive.ts"],"names":[],"mappings":"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"}
|
|
@@ -147,6 +147,20 @@ export declare function createUserValidationRunner(runOpts?: RunUserValidationOp
|
|
|
147
147
|
export interface UserPathsNote {
|
|
148
148
|
note: string;
|
|
149
149
|
trusted: boolean;
|
|
150
|
+
/**
|
|
151
|
+
* True when a PASSING report rests on shallow journeys only — no journey
|
|
152
|
+
* performs a state-changing interaction with a subsequent assertion
|
|
153
|
+
* (journey-depth.ts; the rubiks-cube-onvukh measured failure). Advisory
|
|
154
|
+
* here; the delivery-evidence gate makes the blocking decision.
|
|
155
|
+
*/
|
|
156
|
+
shallow?: boolean;
|
|
157
|
+
/** Structured fields for the delivery-evidence gate (B/D): the report's
|
|
158
|
+
* verdict and the manifest's depth rollup, when both are readable. */
|
|
159
|
+
verdict?: 'pass' | 'fail' | 'na';
|
|
160
|
+
depth?: import('./journey-depth.js').ManifestDepth;
|
|
161
|
+
/** True when the manifest on disk changed after the validated run — the
|
|
162
|
+
* depth rollup was withheld; the remediation is re-running validation. */
|
|
163
|
+
stale?: boolean;
|
|
150
164
|
}
|
|
151
165
|
/**
|
|
152
166
|
* Build the acceptance-judge runtime note from the on-disk report, refusing
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-validation.d.ts","sourceRoot":"","sources":["../../src/delivery/user-validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"user-validation.d.ts","sourceRoot":"","sources":["../../src/delivery/user-validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,15 +17,16 @@
|
|
|
17
17
|
* browser paths skipped (rung non-blocking) rather than failing delivery on an
|
|
18
18
|
* environment gap — but the skip is loud in the report and the judge note.
|
|
19
19
|
*/
|
|
20
|
-
import { execFileSync, spawn, spawnSync } from 'node:child_process';
|
|
21
|
-
import { createHash } from 'node:crypto';
|
|
22
20
|
// SECURITY: every spawn below that runs project/model code must use
|
|
23
|
-
// sanitizedEnv() (secret-stripped env) — see ./sanitized-env.
|
|
21
|
+
// sanitizedEnv() (secret-stripped env) — see ./sanitized-env.js.
|
|
24
22
|
import { sanitizedEnv } from './sanitized-env.js';
|
|
23
|
+
import { createHash } from 'node:crypto';
|
|
24
|
+
import { spawn, spawnSync, execFileSync } from 'node:child_process';
|
|
25
25
|
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
26
|
-
import { join, relative, sep } from 'node:path';
|
|
26
|
+
import { join, relative, resolve, sep } from 'node:path';
|
|
27
27
|
import { findWebEntryDir, startStaticServer } from './execution-gate.js';
|
|
28
28
|
import { loadUserPaths, USER_PATHS_FILE, } from './user-paths.js';
|
|
29
|
+
import { assessManifestDepth, shallowDepthNote } from './journey-depth.js';
|
|
29
30
|
export const VALIDATION_REPORT_FILE = join('agents', 'data', 'validation', 'latest.json');
|
|
30
31
|
export const USER_VALIDATION_RUNG_ID = 'user-validation';
|
|
31
32
|
/* ------------------------------------------------------------------ trust */
|
|
@@ -271,7 +272,19 @@ export function jsonContains(actual, expected) {
|
|
|
271
272
|
* Python check"; the alias is an environment detail); any other spawn failure
|
|
272
273
|
* is returned as-is for the caller to report explicitly.
|
|
273
274
|
*/
|
|
275
|
+
/**
|
|
276
|
+
* Tag a fallback re-spawn so journey evidence shows WHICH interpreter/file
|
|
277
|
+
* actually ran (`via=tsx`, `via=strip-types`, `via=dist:dist/foo.js`), not
|
|
278
|
+
* only the argv the manifest declared. Without it, a fallback that runs a
|
|
279
|
+
* different file than the journey named looks identical in the report.
|
|
280
|
+
*/
|
|
281
|
+
function tagVia(r, tag) {
|
|
282
|
+
return Object.assign(r, { __via: tag });
|
|
283
|
+
}
|
|
274
284
|
function spawnJourneyStep(argv, ctx, run) {
|
|
285
|
+
// SECURITY: runCliPath's spawnSync must run with the secret-stripped env —
|
|
286
|
+
// env: sanitizedEnv() is applied here so every CLI-path step (project/model
|
|
287
|
+
// code) inherits no host credentials.
|
|
275
288
|
const opts = {
|
|
276
289
|
cwd: ctx.projectRoot,
|
|
277
290
|
env: sanitizedEnv(),
|
|
@@ -287,6 +300,54 @@ function spawnJourneyStep(argv, ctx, run) {
|
|
|
287
300
|
if (!alt.error)
|
|
288
301
|
return alt;
|
|
289
302
|
}
|
|
303
|
+
// A .ts/.tsx journey target is a TypeScript source file: Node cannot exec
|
|
304
|
+
// it directly (EACCES — no exec bit, and Node does not parse .ts without a
|
|
305
|
+
// loader). Re-spawn through the project's TypeScript runner when one is
|
|
306
|
+
// available (tsx, ts-node), then Node's type stripping. Last resort: the
|
|
307
|
+
// project's own compiled output (npm run build → dist/) — the source tree
|
|
308
|
+
// mirrors dist/ 1:1, so a journey targeting src/delivery/foo.ts can run
|
|
309
|
+
// dist/delivery/foo.js when the build is current. Without these fallbacks a
|
|
310
|
+
// .ts journey EACCESes on every box — an unsatisfiable gate the agent can
|
|
311
|
+
// only fight (run 20260824T054426's user-path gate burned its turns there).
|
|
312
|
+
// Every re-spawn is tagged (__via) so the step evidence shows WHICH
|
|
313
|
+
// interpreter/file actually ran, not just the argv the manifest declared.
|
|
314
|
+
if (r.error && r.error.code === 'EACCES' && /\.(ts|tsx)$/.test(cmd)) {
|
|
315
|
+
for (const runner of ['tsx', 'ts-node']) {
|
|
316
|
+
const alt = spawnSync(runner, [cmd, ...rest], opts);
|
|
317
|
+
if (!alt.error)
|
|
318
|
+
return tagVia(alt, runner);
|
|
319
|
+
}
|
|
320
|
+
const stripped = spawnSync(process.execPath, ['--experimental-strip-types', cmd, ...rest], opts);
|
|
321
|
+
if (!stripped.error) {
|
|
322
|
+
// On Node < 22.6 the flag itself is rejected ("bad option"): the spawn
|
|
323
|
+
// succeeds but the run is garbage. Fall through to the dist mirror
|
|
324
|
+
// instead of returning a dead end that hides the working fallback.
|
|
325
|
+
if (!/bad option|unknown option/i.test(stripped.stderr ?? ''))
|
|
326
|
+
return tagVia(stripped, 'strip-types');
|
|
327
|
+
}
|
|
328
|
+
// Resolve against the project root (the manifest's cwd) so absolute,
|
|
329
|
+
// ./-relative and bare src/ spellings all reach the mirror; only spawn a
|
|
330
|
+
// mirror that exists (a stale/missing build reports the original EACCES
|
|
331
|
+
// rather than a confusing Cannot-find-module exit).
|
|
332
|
+
const srcRel = relative(ctx.projectRoot, resolve(ctx.projectRoot, cmd));
|
|
333
|
+
if (srcRel.startsWith('src/')) {
|
|
334
|
+
const distRel = srcRel.replace(/^src\//, 'dist/').replace(/\.tsx?$/, '.js');
|
|
335
|
+
if (existsSync(join(ctx.projectRoot, distRel))) {
|
|
336
|
+
const viaDist = spawnSync(process.execPath, [distRel, ...rest], opts);
|
|
337
|
+
if (!viaDist.error)
|
|
338
|
+
return tagVia(viaDist, `dist:${distRel}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// A .js/.mjs journey target that is NOT executable (no exec bit) also
|
|
343
|
+
// EACCESes on a direct spawn. Re-spawn through the Node binary — the
|
|
344
|
+
// journey's intent is "run this script", the exec bit is an environment
|
|
345
|
+
// detail (same precedent as the python→python3 fallback above).
|
|
346
|
+
if (r.error && r.error.code === 'EACCES' && /\.(js|mjs|cjs)$/.test(cmd)) {
|
|
347
|
+
const alt = spawnSync(process.execPath, [cmd, ...rest], opts);
|
|
348
|
+
if (!alt.error)
|
|
349
|
+
return alt;
|
|
350
|
+
}
|
|
290
351
|
return r;
|
|
291
352
|
}
|
|
292
353
|
function runCliPath(path, ctx) {
|
|
@@ -324,7 +385,12 @@ function runCliPath(path, ctx) {
|
|
|
324
385
|
lastExit = r.status;
|
|
325
386
|
lastStdout = r.stdout ?? '';
|
|
326
387
|
lastStderr = r.stderr ?? '';
|
|
327
|
-
|
|
388
|
+
const via = r.__via;
|
|
389
|
+
steps.push({
|
|
390
|
+
step: label,
|
|
391
|
+
ok: true,
|
|
392
|
+
observed: `exit=${String(lastExit)}${via ? ` via=${via}` : ''} stdout=${lastStdout.slice(0, 120)}`,
|
|
393
|
+
});
|
|
328
394
|
}
|
|
329
395
|
else if (step.expect_exit !== undefined) {
|
|
330
396
|
const ok = lastExit === step.expect_exit;
|
|
@@ -379,7 +445,10 @@ async function startManifestServer(srv, projectRoot) {
|
|
|
379
445
|
const args = declaredArgs.length === 0 ? parts.slice(1) : declaredArgs;
|
|
380
446
|
const child = spawn(cmd, args, {
|
|
381
447
|
cwd: projectRoot,
|
|
382
|
-
|
|
448
|
+
// SECURITY: manifest servers run project/model code — base the env on the
|
|
449
|
+
// secret-stripped sanitizedEnv() (host credentials must not leak to the
|
|
450
|
+
// child); srv.env overrides still apply on top.
|
|
451
|
+
env: { ...sanitizedEnv(), ...srv.env },
|
|
383
452
|
stdio: 'ignore',
|
|
384
453
|
detached: false,
|
|
385
454
|
});
|
|
@@ -866,14 +935,39 @@ export function buildUserPathsNote(projectRoot) {
|
|
|
866
935
|
}
|
|
867
936
|
try {
|
|
868
937
|
const report = JSON.parse(text);
|
|
938
|
+
// Depth is computed from the LIVE manifest, but the report is pinned to
|
|
939
|
+
// the manifest the sanctioned runner RAN (manifestHash). A manifest
|
|
940
|
+
// edited after the run — e.g. never-executed click steps appended to a
|
|
941
|
+
// passing shallow manifest — must not be able to mint a deep-journeys
|
|
942
|
+
// basis for the evidence gate (correctness-review finding 1): on hash
|
|
943
|
+
// mismatch the depth rollup is withheld and the note says the journey
|
|
944
|
+
// evidence is stale.
|
|
945
|
+
const live = loadUserPaths(projectRoot);
|
|
946
|
+
const manifestFresh = Boolean(live?.ok &&
|
|
947
|
+
live.manifest &&
|
|
948
|
+
report.manifestHash !== null &&
|
|
949
|
+
sha256Text(JSON.stringify(live.manifest)) === report.manifestHash);
|
|
950
|
+
const depth = manifestFresh && live?.manifest ? assessManifestDepth(live.manifest) : undefined;
|
|
951
|
+
const staleManifest = Boolean(live?.ok && live.manifest && !manifestFresh);
|
|
952
|
+
const staleClause = staleManifest
|
|
953
|
+
? ' The manifest CHANGED since this validation ran — the journey evidence is STALE; rerun user validation before trusting it.'
|
|
954
|
+
: '';
|
|
869
955
|
if (report.verdict === 'pass') {
|
|
870
|
-
|
|
956
|
+
const base = `User-path validation ALL PASSED (${report.results.length} real-client journeys) — treat user-facing requirements covered by these paths as objectively verified.${staleClause}`;
|
|
957
|
+
// Journey-depth enforcement (A2): the runner honestly executes whatever
|
|
958
|
+
// the manifest declares, and the manifest is MODEL-AUTHORED — a pass on
|
|
959
|
+
// load-only journeys is not behavioral verification. Read the manifest
|
|
960
|
+
// and say so when nothing deep ran (rubiks-cube-onvukh, 2026-09-24).
|
|
961
|
+
if (depth && depth.total > 0 && depth.deep === 0) {
|
|
962
|
+
return { note: `${base} ${shallowDepthNote(depth)}`, trusted: true, shallow: true, verdict: 'pass', depth };
|
|
963
|
+
}
|
|
964
|
+
return { note: base, trusted: true, verdict: 'pass', ...(depth ? { depth } : {}), ...(staleManifest ? { stale: true } : {}) };
|
|
871
965
|
}
|
|
872
966
|
if (report.verdict === 'fail') {
|
|
873
967
|
const failed = report.results.filter((r) => r.status === 'fail').map((r) => `${r.id} (${r.rule})`).join('; ');
|
|
874
|
-
return { note: `User-path validation FAILED: ${failed} — the artifact does not work for a real user on these journeys
|
|
968
|
+
return { note: `User-path validation FAILED: ${failed} — the artifact does not work for a real user on these journeys.${staleClause}`, trusted: true, verdict: 'fail', ...(depth ? { depth } : {}), ...(staleManifest ? { stale: true } : {}) };
|
|
875
969
|
}
|
|
876
|
-
return { note: `User-path validation: not applicable (${report.naReason ?? 'no user-facing surface'}).`, trusted: true };
|
|
970
|
+
return { note: `User-path validation: not applicable (${report.naReason ?? 'no user-facing surface'}).`, trusted: true, verdict: 'na', ...(depth ? { depth } : {}) };
|
|
877
971
|
}
|
|
878
972
|
catch {
|
|
879
973
|
return null;
|