@deftai/directive-core 0.107.0 → 0.109.0
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/architecture/sor-preflight.js +2 -0
- package/dist/cache/operations.js +1 -1
- package/dist/check/cached-orchestrator.js +28 -3
- package/dist/check/gate-lists.d.ts +14 -0
- package/dist/check/gate-lists.js +26 -3
- package/dist/check/named-cause.js +18 -3
- package/dist/check/session-completed-ac.d.ts +1 -1
- package/dist/check/session-completed-ac.js +1 -1
- package/dist/codebase/provider.js +7 -1
- package/dist/consumer-check-contract/evaluate.d.ts +47 -0
- package/dist/consumer-check-contract/evaluate.js +181 -15
- package/dist/delivery-attempt/evaluate.d.ts +9 -1
- package/dist/delivery-attempt/evaluate.js +69 -0
- package/dist/delivery-attempt/handoff.js +1 -1
- package/dist/delivery-attempt/index.d.ts +1 -1
- package/dist/delivery-attempt/index.js +1 -1
- package/dist/deposit/live-procedure-exclusions.d.ts +18 -0
- package/dist/deposit/live-procedure-exclusions.js +110 -0
- package/dist/deposit/live-procedure-targets.d.ts +45 -0
- package/dist/deposit/live-procedure-targets.js +274 -0
- package/dist/deposit/python-free.d.ts +6 -0
- package/dist/deposit/python-free.js +15 -0
- package/dist/deposit/rewrite-deposit-links.d.ts +42 -0
- package/dist/deposit/rewrite-deposit-links.js +148 -0
- package/dist/deposit/run-stage-content-pack.d.ts +2 -0
- package/dist/deposit/run-stage-content-pack.js +3 -0
- package/dist/deposit/stage-content-pack.d.ts +17 -0
- package/dist/deposit/stage-content-pack.js +91 -0
- package/dist/design-critique/citation-grammar.d.ts +60 -0
- package/dist/design-critique/citation-grammar.js +303 -0
- package/dist/design-critique/completed-arc-record.d.ts +62 -0
- package/dist/design-critique/completed-arc-record.js +277 -0
- package/dist/freshness/bind.d.ts +32 -3
- package/dist/freshness/bind.js +58 -12
- package/dist/hooks/classify/host-session-identity.d.ts +89 -0
- package/dist/hooks/classify/host-session-identity.js +467 -0
- package/dist/hooks/classify/index.d.ts +3 -2
- package/dist/hooks/classify/index.js +3 -2
- package/dist/hooks/classify/paths.d.ts +9 -0
- package/dist/hooks/classify/paths.js +39 -0
- package/dist/hooks/classify/stdin.d.ts +5 -0
- package/dist/hooks/classify/stdin.js +94 -1
- package/dist/hooks/dest-form.d.ts +20 -1
- package/dist/hooks/dest-form.js +158 -21
- package/dist/hooks/dispatcher.d.ts +58 -3
- package/dist/hooks/dispatcher.js +762 -73
- package/dist/hooks/fixtures/cases.d.ts +22 -2
- package/dist/hooks/fixtures/cases.js +228 -0
- package/dist/hooks/git-destructive-log.d.ts +32 -0
- package/dist/hooks/git-destructive-log.js +46 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/scope.js +3 -1
- package/dist/hooks/shell-write-targets.d.ts +10 -0
- package/dist/hooks/shell-write-targets.js +274 -0
- package/dist/hooks/tools.d.ts +20 -2
- package/dist/hooks/tools.js +30 -1
- package/dist/init-deposit/agent-hooks.d.ts +2 -1
- package/dist/init-deposit/agent-hooks.js +8 -1
- package/dist/init-deposit/gitignore.d.ts +7 -0
- package/dist/init-deposit/gitignore.js +24 -0
- package/dist/init-deposit/hook-runtime-travel.d.ts +77 -0
- package/dist/init-deposit/hook-runtime-travel.js +269 -0
- package/dist/init-deposit/init-deposit.js +3 -0
- package/dist/init-deposit/refresh.js +7 -0
- package/dist/init-deposit/runtime-writers.d.ts +14 -0
- package/dist/init-deposit/runtime-writers.js +33 -0
- package/dist/intake/clause-derivation.js +9 -3
- package/dist/intake/issue-ingest.d.ts +6 -1
- package/dist/intake/issue-ingest.js +83 -4
- package/dist/intake/platform-capabilities.d.ts +9 -2
- package/dist/intake/platform-capabilities.js +38 -9
- package/dist/intake/reconcile-issues.js +13 -13
- package/dist/lifecycle/brief-envelope.d.ts +25 -0
- package/dist/lifecycle/brief-envelope.js +42 -0
- package/dist/lifecycle/index.d.ts +1 -0
- package/dist/lifecycle/index.js +1 -0
- package/dist/literal-acceptance/evaluate.js +14 -5
- package/dist/literal-acceptance/index.d.ts +1 -1
- package/dist/literal-acceptance/index.js +1 -1
- package/dist/literal-acceptance/run.d.ts +2 -0
- package/dist/literal-acceptance/run.js +19 -1
- package/dist/orphan-active/candidate-scope.d.ts +53 -0
- package/dist/orphan-active/candidate-scope.js +157 -0
- package/dist/orphan-active/evaluate.d.ts +52 -0
- package/dist/orphan-active/evaluate.js +250 -128
- package/dist/orphan-active/index.d.ts +2 -0
- package/dist/orphan-active/index.js +2 -0
- package/dist/orphan-active/issue-state.d.ts +121 -0
- package/dist/orphan-active/issue-state.js +278 -0
- package/dist/platform/cursor-managed-runtime.d.ts +95 -0
- package/dist/platform/cursor-managed-runtime.js +241 -0
- package/dist/platform/index.d.ts +1 -0
- package/dist/platform/index.js +1 -0
- package/dist/platform/platform-capabilities.d.ts +23 -1
- package/dist/platform/platform-capabilities.js +55 -15
- package/dist/policy/ceremony-dial.js +5 -9
- package/dist/policy/host-hooks.js +4 -9
- package/dist/policy/merge-approval-head.js +7 -6
- package/dist/policy/org-force-on-migration.js +5 -10
- package/dist/policy/plan-extensions.d.ts +14 -2
- package/dist/policy/plan-extensions.js +24 -3
- package/dist/policy/product-signal.js +5 -10
- package/dist/policy/require-human-merge.js +5 -9
- package/dist/policy/resolve.js +77 -16
- package/dist/policy/value-feedback.js +9 -18
- package/dist/pr-closeout-attestable/evaluate.d.ts +80 -0
- package/dist/pr-closeout-attestable/evaluate.js +306 -0
- package/dist/pr-closeout-attestable/index.d.ts +2 -0
- package/dist/pr-closeout-attestable/index.js +2 -0
- package/dist/pr-closing-keywords/gh.js +32 -9
- package/dist/pr-closing-keywords/main.d.ts +1 -0
- package/dist/pr-closing-keywords/main.js +68 -3
- package/dist/pr-closing-keywords/types.d.ts +2 -0
- package/dist/pr-merge-readiness/gh.js +32 -9
- package/dist/pr-protected-issues/gh.d.ts +6 -2
- package/dist/pr-protected-issues/gh.js +42 -11
- package/dist/pr-wait-mergeable/cascade.d.ts +9 -1
- package/dist/pr-wait-mergeable/cascade.js +21 -1
- package/dist/pr-wait-mergeable/types.d.ts +2 -0
- package/dist/pr-wait-mergeable/wrappers.d.ts +6 -0
- package/dist/pr-wait-mergeable/wrappers.js +14 -3
- package/dist/preflight/evaluate.d.ts +15 -0
- package/dist/preflight/evaluate.js +29 -3
- package/dist/product-first-done-gate/acceptance-resolver.d.ts +14 -2
- package/dist/product-first-done-gate/acceptance-resolver.js +13 -2
- package/dist/product-first-done-gate/evaluate.js +23 -9
- package/dist/product-first-done-gate/types.js +2 -0
- package/dist/release/cli-drift-report.d.ts +68 -0
- package/dist/release/cli-drift-report.js +189 -0
- package/dist/release/consumer-hard-stops.d.ts +48 -0
- package/dist/release/consumer-hard-stops.js +140 -0
- package/dist/release/consumer-readiness-disclosure.d.ts +18 -0
- package/dist/release/consumer-readiness-disclosure.js +51 -0
- package/dist/release/index.d.ts +3 -0
- package/dist/release/index.js +3 -0
- package/dist/release/issue-state-fetch.d.ts +5 -3
- package/dist/release/issue-state-fetch.js +86 -21
- package/dist/release/native-steps.js +1 -0
- package/dist/release/pipeline.js +74 -0
- package/dist/release/run-consumer-readiness.d.ts +15 -0
- package/dist/release/run-consumer-readiness.js +24 -0
- package/dist/release/types.d.ts +20 -0
- package/dist/render/constants.d.ts +4 -0
- package/dist/render/constants.js +11 -8
- package/dist/render/export-spec.js +31 -5
- package/dist/render/index.d.ts +1 -1
- package/dist/render/index.js +1 -1
- package/dist/render/prd-render.d.ts +4 -1
- package/dist/render/prd-render.js +82 -23
- package/dist/render/project-render.js +14 -7
- package/dist/render/scope-outlook.d.ts +2 -0
- package/dist/render/scope-outlook.js +3 -0
- package/dist/render/spec-render.js +2 -2
- package/dist/resolution/package-manager.d.ts +33 -4
- package/dist/resolution/package-manager.js +210 -9
- package/dist/review-monitor/constants.d.ts +7 -0
- package/dist/review-monitor/constants.js +7 -0
- package/dist/review-monitor/github-lease.d.ts +98 -1
- package/dist/review-monitor/github-lease.js +186 -4
- package/dist/review-monitor/lease-comment.d.ts +36 -0
- package/dist/review-monitor/lease-comment.js +103 -2
- package/dist/run-summary/types.d.ts +2 -2
- package/dist/scm/build-command.d.ts +2 -2
- package/dist/scm/build-command.js +2 -2
- package/dist/scm/call-shape.d.ts +25 -0
- package/dist/scm/call-shape.js +59 -0
- package/dist/scm/call.d.ts +7 -4
- package/dist/scm/call.js +48 -9
- package/dist/scm/design-critique-chip.d.ts +1 -0
- package/dist/scm/design-critique-chip.js +22 -6
- package/dist/scm/gh-rest.d.ts +34 -13
- package/dist/scm/gh-rest.js +168 -15
- package/dist/scm/index.d.ts +2 -0
- package/dist/scm/index.js +2 -0
- package/dist/scm/readiness.d.ts +2 -0
- package/dist/scm/readiness.js +28 -4
- package/dist/scm/spawn-status.d.ts +33 -0
- package/dist/scm/spawn-status.js +53 -0
- package/dist/scope/acceptance-evidence.d.ts +1 -1
- package/dist/scope/project-definition-sync.js +14 -7
- package/dist/scope/transition.js +4 -14
- package/dist/session/ac-pass-banking.d.ts +2 -2
- package/dist/session/ac-pass-banking.js +2 -2
- package/dist/session/git.d.ts +24 -0
- package/dist/session/git.js +138 -2
- package/dist/session/host-session-owner.d.ts +53 -0
- package/dist/session/host-session-owner.js +89 -0
- package/dist/session/index.d.ts +1 -0
- package/dist/session/index.js +1 -0
- package/dist/session/occupancy.d.ts +259 -13
- package/dist/session/occupancy.js +877 -33
- package/dist/session/ritual-sentinel.d.ts +5 -0
- package/dist/session/ritual-sentinel.js +5 -0
- package/dist/session/session-ready.d.ts +5 -1
- package/dist/session/session-ready.js +98 -8
- package/dist/session/session-start.d.ts +5 -1
- package/dist/session/session-start.js +32 -17
- package/dist/session/toolchain-preflight.d.ts +13 -3
- package/dist/session/toolchain-preflight.js +93 -18
- package/dist/session/verify-ac-session-cache.d.ts +2 -2
- package/dist/session/verify-ac-session-cache.js +2 -2
- package/dist/session/verify-session-ritual.d.ts +11 -0
- package/dist/session/verify-session-ritual.js +60 -15
- package/dist/slice/constants.d.ts +1 -1
- package/dist/spec-authority/constants.d.ts +10 -2
- package/dist/spec-authority/constants.js +53 -8
- package/dist/spec-authority/resolver.d.ts +3 -0
- package/dist/spec-authority/resolver.js +55 -7
- package/dist/subprocess/max-buffer.d.ts +14 -0
- package/dist/subprocess/max-buffer.js +15 -0
- package/dist/swarm/complete-cohort.d.ts +2 -0
- package/dist/swarm/complete-cohort.js +21 -13
- package/dist/swarm/index.d.ts +1 -0
- package/dist/swarm/index.js +1 -0
- package/dist/swarm/launch-cli.js +53 -33
- package/dist/swarm/launch.d.ts +8 -0
- package/dist/swarm/launch.js +63 -43
- package/dist/swarm/pre-dispatch-cli.js +2 -1
- package/dist/swarm/pre-dispatch.js +10 -1
- package/dist/swarm/subagent-status-dir.d.ts +27 -0
- package/dist/swarm/subagent-status-dir.js +42 -0
- package/dist/swarm/worktrees.d.ts +17 -3
- package/dist/swarm/worktrees.js +48 -4
- package/dist/triage/evaluate/worktrees.js +153 -6
- package/dist/triage/scope/mutations-core.d.ts +2 -6
- package/dist/triage/scope/mutations-core.js +23 -55
- package/dist/triage/scope-drift/add-ignore.js +5 -39
- package/dist/triage/subscribe/index.d.ts +2 -6
- package/dist/triage/subscribe/index.js +15 -65
- package/dist/triage/welcome/writers.js +15 -74
- package/dist/umbrella-current-shape/index.d.ts +51 -3
- package/dist/umbrella-current-shape/index.js +106 -18
- package/dist/validate-content/deposit-required.d.ts +39 -0
- package/dist/validate-content/deposit-required.js +147 -0
- package/dist/validate-content/index.d.ts +1 -0
- package/dist/validate-content/index.js +1 -0
- package/dist/validate-content/validate-links.d.ts +2 -3
- package/dist/validate-content/validate-links.js +29 -2
- package/dist/vbrief-activate/activate.d.ts +7 -2
- package/dist/vbrief-activate/activate.js +26 -13
- package/dist/vbrief-build/index.d.ts +2 -1
- package/dist/vbrief-build/index.js +2 -1
- package/dist/vbrief-build/parity-scenarios.js +5 -5
- package/dist/vbrief-build/project-definition-io.d.ts +63 -3
- package/dist/vbrief-build/project-definition-io.js +357 -31
- package/dist/vbrief-build/project-definition-mutation.d.ts +32 -0
- package/dist/vbrief-build/project-definition-mutation.js +43 -0
- package/dist/vbrief-validate/conformance.d.ts +1 -0
- package/dist/vbrief-validate/conformance.js +85 -8
- package/dist/vbrief-validate/main.js +2 -0
- package/dist/vbrief-validate/precutover.js +5 -10
- package/dist/verify-ac/clauses.d.ts +62 -2
- package/dist/verify-ac/clauses.js +183 -111
- package/dist/verify-ac/evaluate.d.ts +9 -0
- package/dist/verify-ac/evaluate.js +32 -9
- package/dist/verify-ac/index.d.ts +1 -1
- package/dist/verify-ac/index.js +1 -1
- package/dist/verify-env/node-runtime.d.ts +8 -4
- package/dist/verify-env/node-runtime.js +9 -6
- package/dist/verify-env/toolchain-check.d.ts +35 -3
- package/dist/verify-env/toolchain-check.js +155 -36
- package/dist/verify-source/deposit-closure.d.ts +23 -0
- package/dist/verify-source/deposit-closure.js +162 -0
- package/dist/verify-source/index.d.ts +2 -0
- package/dist/verify-source/index.js +2 -0
- package/dist/verify-source/project-definition-mutation-boundary.d.ts +104 -0
- package/dist/verify-source/project-definition-mutation-boundary.js +326 -0
- package/dist/verify-source/semantic-single-source.d.ts +36 -0
- package/dist/verify-source/semantic-single-source.js +349 -0
- package/package.json +7 -3
package/dist/scm/gh-rest.js
CHANGED
|
@@ -3,8 +3,10 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { SUBPROCESS_MAX_BUFFER } from "../subprocess/max-buffer.js";
|
|
6
|
-
import {
|
|
6
|
+
import { defaultWhich } from "./binary.js";
|
|
7
|
+
import { classifyScmArgv, resolveBinaryForRole } from "./call-shape.js";
|
|
7
8
|
import { pyRepr } from "./py-format.js";
|
|
9
|
+
import { classifySpawnStatus, formatScmSpawnDiagnostic, isAvailabilitySpawnFailure, } from "./spawn-status.js";
|
|
8
10
|
export const DEFAULT_TIMEOUT_S = 60;
|
|
9
11
|
/** Raised when the `"owner/repo"` argument is malformed. */
|
|
10
12
|
export class InvalidRepoError extends Error {
|
|
@@ -23,10 +25,16 @@ export class GhRestError extends Error {
|
|
|
23
25
|
endpoint;
|
|
24
26
|
payload;
|
|
25
27
|
hint;
|
|
28
|
+
binary;
|
|
26
29
|
constructor(options) {
|
|
27
30
|
const hint = options.hint ?? "";
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
const binary = options.binary ?? "gh";
|
|
32
|
+
const statusClass = classifySpawnStatus(options.exitCode);
|
|
33
|
+
let msg = `${binary} api failed: endpoint=${pyRepr(options.endpoint)} ` + `exit=${options.exitCode}`;
|
|
34
|
+
if (statusClass !== `exit ${options.exitCode}`) {
|
|
35
|
+
msg += ` (${statusClass})`;
|
|
36
|
+
}
|
|
37
|
+
msg += ` stderr=${pyRepr(options.stderr)}`;
|
|
30
38
|
if (hint.length > 0) {
|
|
31
39
|
msg += `; hint: ${hint}`;
|
|
32
40
|
}
|
|
@@ -37,30 +45,70 @@ export class GhRestError extends Error {
|
|
|
37
45
|
this.endpoint = options.endpoint;
|
|
38
46
|
this.payload = options.payload;
|
|
39
47
|
this.hint = hint;
|
|
48
|
+
this.binary = binary;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function defaultGhSpawn(command, args, options) {
|
|
52
|
+
return spawnSync(command, [...args], options);
|
|
53
|
+
}
|
|
54
|
+
function finalizeGhApiResult(binary, result) {
|
|
55
|
+
const rawStderr = typeof result.stderr === "string" ? result.stderr : "";
|
|
56
|
+
let stderr = rawStderr;
|
|
57
|
+
if (result.status === null && result.error && stderr.trim().length === 0) {
|
|
58
|
+
stderr = result.error.message ?? "";
|
|
40
59
|
}
|
|
60
|
+
if (isAvailabilitySpawnFailure({
|
|
61
|
+
status: result.status,
|
|
62
|
+
error: result.error,
|
|
63
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
64
|
+
stderr: rawStderr,
|
|
65
|
+
}) &&
|
|
66
|
+
stderr.trim().length === 0) {
|
|
67
|
+
stderr = formatScmSpawnDiagnostic(binary, result.status, stderr, result.error);
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
returncode: result.status ?? 1,
|
|
71
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
72
|
+
stderr,
|
|
73
|
+
binary,
|
|
74
|
+
rawStderr,
|
|
75
|
+
rawStatus: result.status,
|
|
76
|
+
error: result.error,
|
|
77
|
+
};
|
|
41
78
|
}
|
|
42
79
|
/** Single subprocess seam invoked by every helper. */
|
|
43
80
|
export function runGhApi(args, options = {}) {
|
|
44
|
-
const
|
|
81
|
+
const whichFn = options.whichFn ?? defaultWhich;
|
|
82
|
+
const spawnFn = options.spawnFn ?? defaultGhSpawn;
|
|
83
|
+
const role = classifyScmArgv("api", args);
|
|
84
|
+
let binary = resolveBinaryForRole(role, whichFn);
|
|
45
85
|
const timeoutMs = options.timeout !== undefined ? Math.round(options.timeout * 1000) : DEFAULT_TIMEOUT_S * 1000;
|
|
46
|
-
const
|
|
86
|
+
const spawnOpts = {
|
|
47
87
|
encoding: "utf8",
|
|
48
88
|
timeout: timeoutMs,
|
|
49
89
|
env: process.env,
|
|
50
90
|
maxBuffer: SUBPROCESS_MAX_BUFFER,
|
|
51
91
|
stdio: ["ignore", "pipe", "pipe"],
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
92
|
+
};
|
|
93
|
+
const spawnOnce = (bin) => finalizeGhApiResult(bin, spawnFn(bin, ["api", ...args], spawnOpts));
|
|
94
|
+
let first = spawnOnce(binary);
|
|
95
|
+
if (role === "cached-get" &&
|
|
96
|
+
binary === "ghx" &&
|
|
97
|
+
isAvailabilitySpawnFailure({
|
|
98
|
+
status: first.rawStatus,
|
|
99
|
+
error: first.error,
|
|
100
|
+
stdout: first.stdout,
|
|
101
|
+
stderr: first.rawStderr,
|
|
102
|
+
}) &&
|
|
103
|
+
whichFn("gh") !== null) {
|
|
104
|
+
binary = "gh";
|
|
105
|
+
first = spawnOnce(binary);
|
|
59
106
|
}
|
|
60
107
|
return {
|
|
61
|
-
returncode:
|
|
62
|
-
stdout:
|
|
63
|
-
stderr,
|
|
108
|
+
returncode: first.returncode,
|
|
109
|
+
stdout: first.stdout,
|
|
110
|
+
stderr: first.stderr,
|
|
111
|
+
binary,
|
|
64
112
|
};
|
|
65
113
|
}
|
|
66
114
|
export function splitRepo(repo) {
|
|
@@ -83,6 +131,7 @@ function execApi(args, options) {
|
|
|
83
131
|
endpoint: options.endpoint,
|
|
84
132
|
payload: options.payload,
|
|
85
133
|
hint: options.hint ?? "",
|
|
134
|
+
binary: result.binary ?? "gh",
|
|
86
135
|
});
|
|
87
136
|
}
|
|
88
137
|
const stdout = result.stdout.trim();
|
|
@@ -183,6 +232,7 @@ export const PUBLIC_HELPERS = [
|
|
|
183
232
|
"restPrView",
|
|
184
233
|
"restIssueList",
|
|
185
234
|
"restIssueListPaginated",
|
|
235
|
+
"restIssueListOpenInventory",
|
|
186
236
|
];
|
|
187
237
|
function writeJsonPayload(payload) {
|
|
188
238
|
const dir = mkdtempSync(join(tmpdir(), "gh_rest_payload_"));
|
|
@@ -331,6 +381,109 @@ export function restPrView(repo, n, seams = {}) {
|
|
|
331
381
|
whichFn: seams.whichFn,
|
|
332
382
|
});
|
|
333
383
|
}
|
|
384
|
+
const OPEN_INVENTORY_MAX_ISSUES = REST_PAGINATION_MAX_PAGES * REST_MAX_PER_PAGE;
|
|
385
|
+
function issueRowOrThrow(item, endpoint) {
|
|
386
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
387
|
+
throw new GhRestError({
|
|
388
|
+
stderr: "open-issue inventory row is not an object",
|
|
389
|
+
exitCode: 0,
|
|
390
|
+
endpoint,
|
|
391
|
+
payload: null,
|
|
392
|
+
hint: "REST issue list rows must be objects",
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
return item;
|
|
396
|
+
}
|
|
397
|
+
/** Flatten `gh api --paginate --slurp` issue-list output (pages or single page). */
|
|
398
|
+
export function flattenOpenInventoryPayload(parsed, endpoint) {
|
|
399
|
+
if (parsed.length === 0) {
|
|
400
|
+
return [];
|
|
401
|
+
}
|
|
402
|
+
const out = [];
|
|
403
|
+
const allPages = parsed.every((item) => Array.isArray(item));
|
|
404
|
+
if (allPages) {
|
|
405
|
+
for (const page of parsed) {
|
|
406
|
+
if (!Array.isArray(page)) {
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
for (const item of page) {
|
|
410
|
+
const row = issueRowOrThrow(item, endpoint);
|
|
411
|
+
if ("pull_request" in row) {
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
out.push(row);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return out;
|
|
418
|
+
}
|
|
419
|
+
for (const item of parsed) {
|
|
420
|
+
const row = issueRowOrThrow(item, endpoint);
|
|
421
|
+
if ("pull_request" in row) {
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
out.push(row);
|
|
425
|
+
}
|
|
426
|
+
return out;
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Complete open-issue inventory in one `gh api --paginate --slurp` subprocess (#3752).
|
|
430
|
+
* Fail-closed on command failure, non-array JSON, buffer exhaustion, or cap hit.
|
|
431
|
+
* Pull-request rows are excluded.
|
|
432
|
+
*/
|
|
433
|
+
export function restIssueListOpenInventory(repo, seams = {}) {
|
|
434
|
+
const [owner, name] = splitRepo(repo);
|
|
435
|
+
const endpoint = `repos/${owner}/${name}/issues?state=open&per_page=${REST_MAX_PER_PAGE}`;
|
|
436
|
+
const runner = seams.runGhApiFn ?? runGhApi;
|
|
437
|
+
const result = runner(["--paginate", "--slurp", endpoint], { timeout: 120 });
|
|
438
|
+
if (result.returncode !== 0) {
|
|
439
|
+
throw new GhRestError({
|
|
440
|
+
stderr: result.stderr.trim(),
|
|
441
|
+
exitCode: result.returncode,
|
|
442
|
+
endpoint,
|
|
443
|
+
payload: null,
|
|
444
|
+
hint: "verify gh auth and core REST quota; open-issue inventory must be complete",
|
|
445
|
+
binary: result.binary ?? "gh",
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
const stdout = result.stdout.trim();
|
|
449
|
+
if (stdout.length === 0) {
|
|
450
|
+
return [];
|
|
451
|
+
}
|
|
452
|
+
let parsed;
|
|
453
|
+
try {
|
|
454
|
+
parsed = JSON.parse(stdout);
|
|
455
|
+
}
|
|
456
|
+
catch (exc) {
|
|
457
|
+
const message = exc instanceof Error ? exc.message : String(exc);
|
|
458
|
+
throw new GhRestError({
|
|
459
|
+
stderr: `non-JSON open-issue inventory: ${message}`,
|
|
460
|
+
exitCode: 0,
|
|
461
|
+
endpoint,
|
|
462
|
+
payload: null,
|
|
463
|
+
hint: "gh api --paginate --slurp must return a JSON array",
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
if (!Array.isArray(parsed)) {
|
|
467
|
+
throw new GhRestError({
|
|
468
|
+
stderr: `unexpected top-level type ${typeof parsed}`,
|
|
469
|
+
exitCode: 0,
|
|
470
|
+
endpoint,
|
|
471
|
+
payload: null,
|
|
472
|
+
hint: "open-issue inventory must be a JSON array",
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
const out = flattenOpenInventoryPayload(parsed, endpoint);
|
|
476
|
+
if (out.length >= OPEN_INVENTORY_MAX_ISSUES) {
|
|
477
|
+
throw new GhRestError({
|
|
478
|
+
stderr: `open-issue inventory reached cap ${OPEN_INVENTORY_MAX_ISSUES}; pagination may be incomplete`,
|
|
479
|
+
exitCode: 0,
|
|
480
|
+
endpoint,
|
|
481
|
+
payload: null,
|
|
482
|
+
hint: "repo may exceed supported open-issue count; fail closed rather than truncate",
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
return out;
|
|
486
|
+
}
|
|
334
487
|
export function restIssueListPaginated(repo, options = {}, seams = {}) {
|
|
335
488
|
const cappedPerPage = Math.min(Math.max(1, options.perPage ?? REST_MAX_PER_PAGE), REST_MAX_PER_PAGE);
|
|
336
489
|
const [owner, name] = splitRepo(repo);
|
package/dist/scm/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./argv.js";
|
|
|
2
2
|
export * from "./binary.js";
|
|
3
3
|
export * from "./build-command.js";
|
|
4
4
|
export * from "./call.js";
|
|
5
|
+
export * from "./call-shape.js";
|
|
5
6
|
export * from "./constants.js";
|
|
6
7
|
export * from "./design-critique-chip.js";
|
|
7
8
|
export * from "./errors.js";
|
|
@@ -10,4 +11,5 @@ export * from "./main.js";
|
|
|
10
11
|
export * from "./py-format.js";
|
|
11
12
|
export * from "./readiness.js";
|
|
12
13
|
export * from "./rest-dispatch.js";
|
|
14
|
+
export * from "./spawn-status.js";
|
|
13
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/scm/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./argv.js";
|
|
|
2
2
|
export * from "./binary.js";
|
|
3
3
|
export * from "./build-command.js";
|
|
4
4
|
export * from "./call.js";
|
|
5
|
+
export * from "./call-shape.js";
|
|
5
6
|
export * from "./constants.js";
|
|
6
7
|
export * from "./design-critique-chip.js";
|
|
7
8
|
export * from "./errors.js";
|
|
@@ -10,4 +11,5 @@ export * from "./main.js";
|
|
|
10
11
|
export * from "./py-format.js";
|
|
11
12
|
export * from "./readiness.js";
|
|
12
13
|
export * from "./rest-dispatch.js";
|
|
14
|
+
export * from "./spawn-status.js";
|
|
13
15
|
//# sourceMappingURL=index.js.map
|
package/dist/scm/readiness.d.ts
CHANGED
|
@@ -41,6 +41,8 @@ export interface ScmReadinessReport {
|
|
|
41
41
|
readonly githubAuthMode: string;
|
|
42
42
|
/** Runtime mode from the #1557a probe. */
|
|
43
43
|
readonly runtimeMode: string;
|
|
44
|
+
/** Stable id naming why the runtime was classified that way (#3859). */
|
|
45
|
+
readonly runtimeModeReason: string | null;
|
|
44
46
|
/** Whether an injected token env var is present (value never reported). */
|
|
45
47
|
readonly injectedTokenPresent: boolean;
|
|
46
48
|
/** Probe depth used for this report. */
|
package/dist/scm/readiness.js
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import { spawnSync } from "node:child_process";
|
|
22
22
|
import { findInjectedToken, GITHUB_AUTH_MODE_HOST_GH, GITHUB_AUTH_MODE_INJECTED_TOKEN, inferGithubAuthMode, validateGithubAuthForWorker, } from "../intake/github-auth-modes.js";
|
|
23
23
|
import { getPlatformCapabilities, probeRuntimeCapabilities, } from "../intake/platform-capabilities.js";
|
|
24
|
+
import { EXPLICIT_SELECTION_REMEDIATION, GITHUB_AUTH_MODE_ENV, RUNTIME_REASON_CURSOR_MARKER_AMBIGUOUS, } from "../platform/cursor-managed-runtime.js";
|
|
24
25
|
import { defaultWhich } from "./binary.js";
|
|
25
26
|
import { BINARY_PREFERENCE } from "./constants.js";
|
|
26
27
|
import { ScmStubError } from "./errors.js";
|
|
@@ -138,6 +139,7 @@ export function probeScmReadiness(options = {}) {
|
|
|
138
139
|
authState: "binary-absent",
|
|
139
140
|
githubAuthMode,
|
|
140
141
|
runtimeMode: runtimeReport.runtimeMode,
|
|
142
|
+
runtimeModeReason: runtimeReport.runtimeModeReason ?? null,
|
|
141
143
|
injectedTokenPresent,
|
|
142
144
|
depth,
|
|
143
145
|
detail,
|
|
@@ -149,9 +151,11 @@ export function probeScmReadiness(options = {}) {
|
|
|
149
151
|
}
|
|
150
152
|
// Injected-token mode without a token is a hard not-ready even before auth status.
|
|
151
153
|
if (githubAuthMode === GITHUB_AUTH_MODE_INJECTED_TOKEN && !injectedTokenPresent) {
|
|
154
|
+
const ambiguousRuntime = runtimeReport.runtimeModeReason === RUNTIME_REASON_CURSOR_MARKER_AMBIGUOUS;
|
|
152
155
|
const detail = "injected-token mode requires GH_TOKEN, GITHUB_TOKEN, or GH_ENTERPRISE_TOKEN; " +
|
|
153
156
|
`binary=${binary} present but SCM-dependent gates skipped ` +
|
|
154
|
-
`(runtime_mode=${runtimeReport.runtimeMode}
|
|
157
|
+
`(runtime_mode=${runtimeReport.runtimeMode}` +
|
|
158
|
+
`${runtimeReport.runtimeModeReason ? `, reason=${runtimeReport.runtimeModeReason}` : ""})`;
|
|
155
159
|
return {
|
|
156
160
|
ready: false,
|
|
157
161
|
binary,
|
|
@@ -159,10 +163,15 @@ export function probeScmReadiness(options = {}) {
|
|
|
159
163
|
authState: "missing-token",
|
|
160
164
|
githubAuthMode,
|
|
161
165
|
runtimeMode: runtimeReport.runtimeMode,
|
|
166
|
+
runtimeModeReason: runtimeReport.runtimeModeReason ?? null,
|
|
162
167
|
injectedTokenPresent: false,
|
|
163
168
|
depth,
|
|
164
169
|
detail,
|
|
165
|
-
|
|
170
|
+
// An ambiguous Cursor runtime is the #3859 case: name the explicit opt-in
|
|
171
|
+
// here, because this is where the operator actually meets the block.
|
|
172
|
+
remediation: ambiguousRuntime
|
|
173
|
+
? `${EXPLICIT_SELECTION_REMEDIATION}\n\n${REMEDIATION_MISSING_TOKEN}`
|
|
174
|
+
: REMEDIATION_MISSING_TOKEN,
|
|
166
175
|
skippedGates: [...SCM_DEPENDENT_GATES],
|
|
167
176
|
login: null,
|
|
168
177
|
failureKind: "missing_injected_token",
|
|
@@ -209,6 +218,7 @@ export function probeScmReadiness(options = {}) {
|
|
|
209
218
|
authState: "authenticated",
|
|
210
219
|
githubAuthMode: deep.githubAuthMode,
|
|
211
220
|
runtimeMode: runtimeReport.runtimeMode,
|
|
221
|
+
runtimeModeReason: runtimeReport.runtimeModeReason ?? null,
|
|
212
222
|
injectedTokenPresent,
|
|
213
223
|
depth,
|
|
214
224
|
detail: `SCM ready: ${binary} present, ${deep.githubAuthMode} authenticated${loginPart} (deep)`,
|
|
@@ -226,6 +236,7 @@ export function probeScmReadiness(options = {}) {
|
|
|
226
236
|
authState,
|
|
227
237
|
githubAuthMode: deep.githubAuthMode,
|
|
228
238
|
runtimeMode: runtimeReport.runtimeMode,
|
|
239
|
+
runtimeModeReason: runtimeReport.runtimeModeReason ?? null,
|
|
229
240
|
injectedTokenPresent,
|
|
230
241
|
depth,
|
|
231
242
|
detail: `SCM not ready: ${deep.detail}`,
|
|
@@ -247,6 +258,7 @@ export function probeScmReadiness(options = {}) {
|
|
|
247
258
|
authState: "unknown",
|
|
248
259
|
githubAuthMode,
|
|
249
260
|
runtimeMode: runtimeReport.runtimeMode,
|
|
261
|
+
runtimeModeReason: runtimeReport.runtimeModeReason ?? null,
|
|
250
262
|
injectedTokenPresent,
|
|
251
263
|
depth,
|
|
252
264
|
detail,
|
|
@@ -268,6 +280,7 @@ export function probeScmReadiness(options = {}) {
|
|
|
268
280
|
authState: "unauthenticated",
|
|
269
281
|
githubAuthMode,
|
|
270
282
|
runtimeMode: runtimeReport.runtimeMode,
|
|
283
|
+
runtimeModeReason: runtimeReport.runtimeModeReason ?? null,
|
|
271
284
|
injectedTokenPresent,
|
|
272
285
|
depth,
|
|
273
286
|
detail,
|
|
@@ -284,6 +297,7 @@ export function probeScmReadiness(options = {}) {
|
|
|
284
297
|
authState: "authenticated",
|
|
285
298
|
githubAuthMode,
|
|
286
299
|
runtimeMode: runtimeReport.runtimeMode,
|
|
300
|
+
runtimeModeReason: runtimeReport.runtimeModeReason ?? null,
|
|
287
301
|
injectedTokenPresent,
|
|
288
302
|
depth,
|
|
289
303
|
detail: `SCM ready: ${binary} present, ${githubAuthMode} authenticated (shallow)`,
|
|
@@ -302,6 +316,7 @@ export function scmReadinessToDict(report) {
|
|
|
302
316
|
auth_state: report.authState,
|
|
303
317
|
github_auth_mode: report.githubAuthMode,
|
|
304
318
|
runtime_mode: report.runtimeMode,
|
|
319
|
+
runtime_mode_reason: report.runtimeModeReason,
|
|
305
320
|
injected_token_present: report.injectedTokenPresent,
|
|
306
321
|
depth: report.depth,
|
|
307
322
|
detail: report.detail,
|
|
@@ -324,7 +339,14 @@ export function formatScmReadinessLines(report) {
|
|
|
324
339
|
}
|
|
325
340
|
lines.push(`[deft scm] ${report.detail}`);
|
|
326
341
|
if (report.skippedGates.length > 0) {
|
|
327
|
-
|
|
342
|
+
// Name the classification reason next to the skip: a silent skip is what
|
|
343
|
+
// makes this failure costly, because work-selection surfaces go dark (#3859).
|
|
344
|
+
const reason = report.runtimeModeReason ? ` (reason: ${report.runtimeModeReason})` : "";
|
|
345
|
+
lines.push(`[deft scm] skipped gates: ${report.skippedGates.join(", ")}${reason}`);
|
|
346
|
+
if (report.runtimeModeReason === RUNTIME_REASON_CURSOR_MARKER_AMBIGUOUS) {
|
|
347
|
+
lines.push(`[deft scm] runtime is ambiguous; set ${GITHUB_AUTH_MODE_ENV}=host-gh to authorize ` +
|
|
348
|
+
"the host gh credential store on a machine you control (#3859)");
|
|
349
|
+
}
|
|
328
350
|
}
|
|
329
351
|
lines.push("[deft scm] run SCM-dependent gates only after auth is ready, or from a matched env; " +
|
|
330
352
|
"see content/scm/github.md § Mismatched/headless SCM readiness (#2275)");
|
|
@@ -387,13 +409,15 @@ export function requireScmReady(options = {}) {
|
|
|
387
409
|
if (hermeticAuthSkip) {
|
|
388
410
|
// Production path uses assertScmBinaryPresent (not test-only).
|
|
389
411
|
const binary = assertScmBinaryPresent(options.whichFn);
|
|
412
|
+
const hermeticRuntime = options.runtimeReport ?? getPlatformCapabilities();
|
|
390
413
|
const report = {
|
|
391
414
|
ready: true,
|
|
392
415
|
binary,
|
|
393
416
|
binaryPath: options.whichFn?.(binary) ?? null,
|
|
394
417
|
authState: "unknown",
|
|
395
418
|
githubAuthMode: GITHUB_AUTH_MODE_HOST_GH,
|
|
396
|
-
runtimeMode:
|
|
419
|
+
runtimeMode: hermeticRuntime.runtimeMode,
|
|
420
|
+
runtimeModeReason: hermeticRuntime.runtimeModeReason ?? null,
|
|
397
421
|
injectedTokenPresent: findInjectedToken(options.env ?? process.env) !== null,
|
|
398
422
|
depth: "shallow",
|
|
399
423
|
detail: `SCM binary present (${binary}); auth status not checked (hermetic)`,
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { WhichFn } from "./binary.js";
|
|
2
|
+
import type { ScmBinaryRole } from "./call-shape.js";
|
|
3
|
+
/** Windows NTSTATUS STATUS_DLL_INIT_FAILED (#3737). Unsigned and signed 32-bit. */
|
|
4
|
+
export declare const STATUS_DLL_INIT_FAILED = 3221225794;
|
|
5
|
+
export declare function unsignedExitStatus(status: number): number;
|
|
6
|
+
export declare function classifySpawnStatus(status: number | null | undefined, error?: {
|
|
7
|
+
readonly message?: string;
|
|
8
|
+
readonly code?: string;
|
|
9
|
+
}): string;
|
|
10
|
+
export declare function isAvailabilitySpawnFailure(result: {
|
|
11
|
+
readonly status: number | null | undefined;
|
|
12
|
+
readonly error?: {
|
|
13
|
+
readonly message?: string;
|
|
14
|
+
readonly code?: string;
|
|
15
|
+
};
|
|
16
|
+
readonly stdout?: string;
|
|
17
|
+
readonly stderr?: string;
|
|
18
|
+
}): boolean;
|
|
19
|
+
export declare function formatScmSpawnDiagnostic(binary: string, status: number | null | undefined, stderr: string, error?: {
|
|
20
|
+
readonly message?: string;
|
|
21
|
+
readonly code?: string;
|
|
22
|
+
}): string;
|
|
23
|
+
/** Return `gh` when a cached-get ghx spawn failed and live gh is on PATH. */
|
|
24
|
+
export declare function ghxSpawnFallbackBinary(role: ScmBinaryRole, invoked: string, whichFn: WhichFn, failure: {
|
|
25
|
+
readonly status: number | null | undefined;
|
|
26
|
+
readonly error?: {
|
|
27
|
+
readonly message?: string;
|
|
28
|
+
readonly code?: string;
|
|
29
|
+
};
|
|
30
|
+
readonly stdout?: string;
|
|
31
|
+
readonly stderr?: string;
|
|
32
|
+
}): string | null;
|
|
33
|
+
//# sourceMappingURL=spawn-status.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** Windows NTSTATUS STATUS_DLL_INIT_FAILED (#3737). Unsigned and signed 32-bit. */
|
|
2
|
+
export const STATUS_DLL_INIT_FAILED = 0xc0000142;
|
|
3
|
+
const STATUS_DLL_INIT_FAILED_SIGNED = -1073741502;
|
|
4
|
+
export function unsignedExitStatus(status) {
|
|
5
|
+
return status >>> 0;
|
|
6
|
+
}
|
|
7
|
+
export function classifySpawnStatus(status, error) {
|
|
8
|
+
if (typeof status !== "number") {
|
|
9
|
+
if (typeof error?.code === "string" && error.code.length > 0) {
|
|
10
|
+
return error.code;
|
|
11
|
+
}
|
|
12
|
+
if (typeof error?.message === "string" && error.message.trim().length > 0) {
|
|
13
|
+
return error.message.trim();
|
|
14
|
+
}
|
|
15
|
+
return "spawn-failed";
|
|
16
|
+
}
|
|
17
|
+
const unsigned = unsignedExitStatus(status);
|
|
18
|
+
if (unsigned === STATUS_DLL_INIT_FAILED || status === STATUS_DLL_INIT_FAILED_SIGNED) {
|
|
19
|
+
return "0xC0000142 STATUS_DLL_INIT_FAILED";
|
|
20
|
+
}
|
|
21
|
+
if (unsigned >= 0xc0000000) {
|
|
22
|
+
return `0x${unsigned.toString(16).toUpperCase()}`;
|
|
23
|
+
}
|
|
24
|
+
return `exit ${status}`;
|
|
25
|
+
}
|
|
26
|
+
export function isAvailabilitySpawnFailure(result) {
|
|
27
|
+
if (result.error !== undefined) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
if (typeof result.status !== "number") {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
const unsigned = unsignedExitStatus(result.status);
|
|
34
|
+
const emptyOut = (result.stdout ?? "").trim().length === 0 && (result.stderr ?? "").trim().length === 0;
|
|
35
|
+
return (emptyOut &&
|
|
36
|
+
(unsigned === STATUS_DLL_INIT_FAILED || result.status === STATUS_DLL_INIT_FAILED_SIGNED));
|
|
37
|
+
}
|
|
38
|
+
export function formatScmSpawnDiagnostic(binary, status, stderr, error) {
|
|
39
|
+
const cls = classifySpawnStatus(status, error);
|
|
40
|
+
const err = stderr.trim();
|
|
41
|
+
if (err.length > 0) {
|
|
42
|
+
return `${binary} failed (${cls}): ${err}`;
|
|
43
|
+
}
|
|
44
|
+
return `${binary} failed (${cls}); stderr empty`;
|
|
45
|
+
}
|
|
46
|
+
/** Return `gh` when a cached-get ghx spawn failed and live gh is on PATH. */
|
|
47
|
+
export function ghxSpawnFallbackBinary(role, invoked, whichFn, failure) {
|
|
48
|
+
if (role !== "cached-get" || invoked !== "ghx" || whichFn("gh") === null) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return isAvailabilitySpawnFailure(failure) ? "gh" : null;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=spawn-status.js.map
|
|
@@ -58,7 +58,7 @@ export interface AcceptanceEvidenceGateResult {
|
|
|
58
58
|
readonly message: string;
|
|
59
59
|
readonly reports: readonly CriterionAcceptanceReport[];
|
|
60
60
|
/** How the #3357 walk obtained AC (#3387). */
|
|
61
|
-
readonly servedFrom?: "bank" | "cache" | "executed";
|
|
61
|
+
readonly servedFrom?: "bank" | "cache" | "executed" | "refused";
|
|
62
62
|
/** Which acceptance check decided the walk (#3497). Undefined when no walk ran. */
|
|
63
63
|
readonly predicate?: AcceptancePredicate;
|
|
64
64
|
}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { dirname, resolve } from "node:path";
|
|
2
|
-
import {
|
|
3
|
-
import { atomicWriteProjectDefinition, loadProjectDefinitionForMutation, projectDefinitionMutationLock, } from "../vbrief-build/project-definition-io.js";
|
|
2
|
+
import { withProjectDefinitionMutation } from "../vbrief-build/project-definition-mutation.js";
|
|
4
3
|
import { syncRegistryArtifactAfterScopeMove } from "./registry-artifact-sync.js";
|
|
5
4
|
/** Fail-closed sync of PROJECT-DEFINITION after a lifecycle move (#1527 / #2131). */
|
|
6
5
|
export function syncProjectDefinitionAfterScopeMove(scopeData, oldPath, newPath, vbriefRoot, targetStatus) {
|
|
7
6
|
const projectRoot = dirname(resolve(vbriefRoot));
|
|
8
7
|
try {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
withProjectDefinitionMutation(projectRoot, (mutation) => {
|
|
9
|
+
syncRegistryArtifactAfterScopeMove(
|
|
10
|
+
// The artifact the lock captured, not an independent re-resolution (#3796).
|
|
11
|
+
mutation.artifactPath, scopeData, oldPath, newPath, vbriefRoot, targetStatus, {
|
|
12
|
+
loadForMutation: () => [mutation.load(), mutation.artifactPath],
|
|
13
|
+
persist: (path, data) => {
|
|
14
|
+
// The registry sync echoes back the path it was handed, so a
|
|
15
|
+
// mismatch means something re-resolved the artifact mid-section.
|
|
16
|
+
if (resolve(path) !== resolve(mutation.artifactPath)) {
|
|
17
|
+
throw new Error("refusing to persist PROJECT-DEFINITION to a path other than the locked artifact");
|
|
18
|
+
}
|
|
19
|
+
mutation.persist(data);
|
|
20
|
+
},
|
|
14
21
|
});
|
|
15
22
|
});
|
|
16
23
|
return null;
|
package/dist/scope/transition.js
CHANGED
|
@@ -5,6 +5,7 @@ import { InstrumentedVbriefCrud, persistCrudMetrics } from "../eval/crud-telemet
|
|
|
5
5
|
import { assertProjectionContained, ProjectionContainmentError, } from "../fs/projection-containment.js";
|
|
6
6
|
import { applyClauseDerivationToPlan, maybeEmitAcceptanceStampFromChange, } from "../intake/clause-derivation.js";
|
|
7
7
|
import { hasArtifactSuffix } from "../layout/resolve.js";
|
|
8
|
+
import { stampExistingEnvelopes } from "../lifecycle/brief-envelope.js";
|
|
8
9
|
import { evaluateCompletedPlanConsistency } from "../lifecycle/completed-consistency.js";
|
|
9
10
|
import { evaluateLiteralAcceptanceFromPlan } from "../literal-acceptance/index.js";
|
|
10
11
|
import { evaluateAcceptanceActivateGate } from "./acceptance-activate-gate.js";
|
|
@@ -45,18 +46,6 @@ function advanceNonTerminalOwnItems(items, targetStatus) {
|
|
|
45
46
|
advanceNonTerminalOwnItems(obj.items, targetStatus);
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
/**
|
|
49
|
-
* Refresh the document envelope `updated` stamp to match `plan.updated`.
|
|
50
|
-
* Stamps whichever of xBRIEFInfo (v0.8) / vBRIEFInfo (v0.6) is present — never creates one (#2862 / #2346).
|
|
51
|
-
*/
|
|
52
|
-
function stampEnvelopeUpdated(data, nowIso) {
|
|
53
|
-
for (const key of ["xBRIEFInfo", "vBRIEFInfo"]) {
|
|
54
|
-
const env = data[key];
|
|
55
|
-
if (typeof env === "object" && env !== null && !Array.isArray(env)) {
|
|
56
|
-
env.updated = nowIso;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
49
|
export function runTransition(action, filePath, now = new Date(), options = {}) {
|
|
61
50
|
if (!(action in TRANSITIONS)) {
|
|
62
51
|
const valid = Object.keys(TRANSITIONS).sort().join(", ");
|
|
@@ -255,7 +244,8 @@ export function runTransition(action, filePath, now = new Date(), options = {})
|
|
|
255
244
|
planObj.status = targetStatus;
|
|
256
245
|
planObj.updated = nowIso;
|
|
257
246
|
// Keep the envelope clock aligned with plan.updated on every mutating transition (#2862).
|
|
258
|
-
|
|
247
|
+
// Stamps whichever envelope is present, never creates one (#3933 / #2346).
|
|
248
|
+
stampExistingEnvelopes(data, nowIso);
|
|
259
249
|
// Reconcile the completing brief's own plan.items (mirrors #1527 / #2566 registry sync) (#2862).
|
|
260
250
|
// On complete, items only reach here when #3240 evidence/disposition gate passed.
|
|
261
251
|
if (OWN_ITEMS_RECONCILE_ACTIONS.has(act)) {
|
|
@@ -412,7 +402,7 @@ function restampCompletedBrief(args) {
|
|
|
412
402
|
}
|
|
413
403
|
planObj.status = "completed";
|
|
414
404
|
planObj.updated = nowIso;
|
|
415
|
-
|
|
405
|
+
stampExistingEnvelopes(data, nowIso);
|
|
416
406
|
stampCompletionMetadata(planObj, projectRoot, nowIso, {
|
|
417
407
|
completedSessionId: resolveCompletionSessionId(projectRoot),
|
|
418
408
|
});
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { type AcPassBankingConfig } from "../policy/ac-pass-banking.js";
|
|
14
14
|
import type { HardEffortBudget, VerificationDepthPolicy } from "./effort-budget.js";
|
|
15
|
-
/** Durable bank ledger directory (
|
|
16
|
-
export declare const AC_PASS_BANK_DIR = ".deft/ac-pass-banks";
|
|
15
|
+
/** Durable bank ledger directory (under already-ignored `.deft/cache/`). */
|
|
16
|
+
export declare const AC_PASS_BANK_DIR = ".deft/cache/ac-pass-banks";
|
|
17
17
|
export declare const AC_PASS_BANK_SCHEMA_VERSION: 1;
|
|
18
18
|
/** Env path for optional JSONL run summary (#3282). Unset = silent. */
|
|
19
19
|
export declare const ENV_RUN_SUMMARY_PATH = "DEFT_RUN_SUMMARY_PATH";
|
|
@@ -18,8 +18,8 @@ import { DEFAULT_SURPLUS_THRESHOLD, resolveAcPassBanking, } from "../policy/ac-p
|
|
|
18
18
|
import { RunSummaryEmitter } from "../run-summary/emit.js";
|
|
19
19
|
import { detectHardEffortBudget, formatDeepeningSkippedNote, recommendVerificationDepth, } from "./effort-budget.js";
|
|
20
20
|
import { gitHead } from "./git.js";
|
|
21
|
-
/** Durable bank ledger directory (
|
|
22
|
-
export const AC_PASS_BANK_DIR = ".deft/ac-pass-banks";
|
|
21
|
+
/** Durable bank ledger directory (under already-ignored `.deft/cache/`). */
|
|
22
|
+
export const AC_PASS_BANK_DIR = ".deft/cache/ac-pass-banks";
|
|
23
23
|
export const AC_PASS_BANK_SCHEMA_VERSION = 1;
|
|
24
24
|
/** Env path for optional JSONL run summary (#3282). Unset = silent. */
|
|
25
25
|
export const ENV_RUN_SUMMARY_PATH = "DEFT_RUN_SUMMARY_PATH";
|
package/dist/session/git.d.ts
CHANGED
|
@@ -5,11 +5,35 @@ export interface GitRunResult {
|
|
|
5
5
|
}
|
|
6
6
|
export type GitRunner = (projectRoot: string, args: readonly string[]) => GitRunResult;
|
|
7
7
|
export declare const defaultGitRunner: GitRunner;
|
|
8
|
+
/**
|
|
9
|
+
* Serve a dispatch's repeated ref reads from one `git` child (#3736).
|
|
10
|
+
*
|
|
11
|
+
* The host mutation gate resolved HEAD, the worktree root, and the branch with
|
|
12
|
+
* a separate spawn each, twice over; on a loaded Windows box a spawn measured a
|
|
13
|
+
* 2.2s p50, so every concurrent agent's hook slowed every other agent's hook.
|
|
14
|
+
* The probe is lazy on purpose: it only fires for a read it can actually
|
|
15
|
+
* answer, so a caller that never asks for context never pays for it.
|
|
16
|
+
*/
|
|
17
|
+
export declare function memoizeGitRunner(runGit?: GitRunner): GitRunner;
|
|
8
18
|
export declare function gitHead(projectRoot: string, runGit?: GitRunner): {
|
|
9
19
|
head: string | null;
|
|
10
20
|
error: string | null;
|
|
11
21
|
};
|
|
12
22
|
export declare function worktreePath(projectRoot: string, runGit?: GitRunner): string;
|
|
23
|
+
/**
|
|
24
|
+
* Walk from `targetPath` to the nearest existing directory. A write that
|
|
25
|
+
* creates a missing nested file is the common case; git cannot use a
|
|
26
|
+
* nonexistent cwd.
|
|
27
|
+
*/
|
|
28
|
+
export declare function existingAncestorDir(targetPath: string): string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Failure-expressing sibling of {@link worktreePath}. Returns null instead of
|
|
31
|
+
* falling back to `startDir` so a missing git tree is distinguishable from
|
|
32
|
+
* success (#3794).
|
|
33
|
+
*/
|
|
34
|
+
export declare function worktreePathOrNull(startDir: string, runGit?: GitRunner): string | null;
|
|
35
|
+
/** Absolute `--git-common-dir` for `projectRoot`, or null on failure. */
|
|
36
|
+
export declare function gitCommonDir(projectRoot: string, runGit?: GitRunner): string | null;
|
|
13
37
|
/** True when `ancestor` is reachable from `descendant` (same commit counts). */
|
|
14
38
|
export declare function gitIsAncestor(projectRoot: string, ancestor: string, descendant: string, runGit?: GitRunner): boolean | null;
|
|
15
39
|
/**
|