@deftai/directive-core 0.108.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/cache/operations.js +1 -1
- package/dist/check/gate-lists.d.ts +14 -0
- package/dist/check/gate-lists.js +26 -3
- package/dist/check/session-completed-ac.d.ts +1 -1
- package/dist/check/session-completed-ac.js +1 -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/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 +7 -0
- package/dist/design-critique/citation-grammar.js +1 -1
- package/dist/design-critique/completed-arc-record.d.ts +1 -1
- package/dist/design-critique/completed-arc-record.js +59 -14
- package/dist/hooks/classify/host-session-identity.d.ts +24 -11
- package/dist/hooks/classify/host-session-identity.js +46 -49
- package/dist/hooks/classify/index.d.ts +2 -2
- package/dist/hooks/classify/index.js +2 -2
- package/dist/hooks/classify/paths.d.ts +2 -0
- package/dist/hooks/classify/paths.js +8 -4
- package/dist/hooks/classify/stdin.js +69 -3
- package/dist/hooks/dest-form.d.ts +20 -1
- package/dist/hooks/dest-form.js +158 -21
- package/dist/hooks/dispatcher.d.ts +6 -2
- package/dist/hooks/dispatcher.js +258 -62
- package/dist/hooks/fixtures/cases.d.ts +6 -0
- package/dist/hooks/fixtures/cases.js +53 -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/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/gitignore.d.ts +7 -0
- package/dist/init-deposit/gitignore.js +24 -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/issue-ingest.d.ts +6 -1
- package/dist/intake/issue-ingest.js +21 -2
- 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 +27 -0
- package/dist/orphan-active/evaluate.js +63 -6
- package/dist/orphan-active/index.d.ts +1 -0
- package/dist/orphan-active/index.js +1 -0
- package/dist/policy/merge-approval-head.js +7 -6
- 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.js +36 -9
- package/dist/pr-wait-mergeable/wrappers.js +3 -3
- package/dist/product-first-done-gate/evaluate.js +6 -2
- package/dist/product-first-done-gate/types.js +2 -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 +2 -0
- package/dist/release/index.js +2 -0
- package/dist/release/pipeline.js +55 -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 +6 -0
- package/dist/review-monitor/github-lease.js +4 -3
- 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 +41 -11
- package/dist/scm/gh-rest.d.ts +25 -12
- package/dist/scm/gh-rest.js +65 -15
- package/dist/scm/index.d.ts +2 -0
- package/dist/scm/index.js +2 -0
- 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/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/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 +21 -1
- package/dist/session/occupancy.js +70 -12
- package/dist/session/verify-ac-session-cache.d.ts +2 -2
- package/dist/session/verify-ac-session-cache.js +2 -2
- package/dist/triage/evaluate/worktrees.js +153 -6
- 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/verify-ac/evaluate.d.ts +9 -0
- package/dist/verify-ac/evaluate.js +32 -9
- 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/semantic-single-source.d.ts +36 -0
- package/dist/verify-source/semantic-single-source.js +349 -0
- package/package.json +3 -3
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* C1 declared deposit closure (#3601 / #3899).
|
|
5
|
+
*
|
|
6
|
+
* Required consumer-deposit paths are a closed typed declaration, not a
|
|
7
|
+
* regex over AGENTS.md RFC2119 prose. Existence checks reuse existsSync
|
|
8
|
+
* the same way validate-links.ts does, against a staged pack root (the
|
|
9
|
+
* prepack flatten), not the source checkout.
|
|
10
|
+
*/
|
|
11
|
+
export const DEPOSIT_REQUIRED_SCHEMA = "deft.deposit-required-paths.v1";
|
|
12
|
+
export const DEPOSIT_REQUIRED_REL = "contracts/deposit-required-paths.json";
|
|
13
|
+
export const DEPOSIT_PREFIX = ".deft/core/";
|
|
14
|
+
/** Parser-visible field. Not a scan of ! / backtick paths. */
|
|
15
|
+
const DEPOSIT_REQUIRED_COMMENT = /<!--\s*deposit-required:\s+(\S+)\s*-->/g;
|
|
16
|
+
export function extractDepositRequiredComments(source) {
|
|
17
|
+
const out = [];
|
|
18
|
+
const re = new RegExp(DEPOSIT_REQUIRED_COMMENT.source, "g");
|
|
19
|
+
let match = re.exec(source);
|
|
20
|
+
while (match !== null) {
|
|
21
|
+
const path = match[1];
|
|
22
|
+
if (path !== undefined) {
|
|
23
|
+
out.push(path);
|
|
24
|
+
}
|
|
25
|
+
match = re.exec(source);
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
export function parseDepositRequiredDeclaration(jsonText) {
|
|
30
|
+
let _data;
|
|
31
|
+
let parsed;
|
|
32
|
+
try {
|
|
33
|
+
parsed = JSON.parse(jsonText);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
37
|
+
throw new Error(`deposit-required: invalid JSON (${reason})`);
|
|
38
|
+
}
|
|
39
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
40
|
+
throw new Error("deposit-required: expected an object");
|
|
41
|
+
}
|
|
42
|
+
const data = parsed;
|
|
43
|
+
if (data.schema !== DEPOSIT_REQUIRED_SCHEMA) {
|
|
44
|
+
throw new Error("deposit-required: expected schema " +
|
|
45
|
+
DEPOSIT_REQUIRED_SCHEMA +
|
|
46
|
+
", got " +
|
|
47
|
+
String(data.schema));
|
|
48
|
+
}
|
|
49
|
+
if (!Array.isArray(data.paths) || data.paths.length === 0) {
|
|
50
|
+
throw new Error("deposit-required: paths must be a non-empty array of strings");
|
|
51
|
+
}
|
|
52
|
+
const paths = [];
|
|
53
|
+
for (const item of data.paths) {
|
|
54
|
+
if (typeof item !== "string" ||
|
|
55
|
+
!item.startsWith(DEPOSIT_PREFIX) ||
|
|
56
|
+
item.includes("\\") ||
|
|
57
|
+
item.includes("..")) {
|
|
58
|
+
throw new Error(`deposit-required: invalid path ${String(item)}`);
|
|
59
|
+
}
|
|
60
|
+
paths.push(item);
|
|
61
|
+
}
|
|
62
|
+
return { schema: DEPOSIT_REQUIRED_SCHEMA, paths };
|
|
63
|
+
}
|
|
64
|
+
export function packRelativeFromDepositPath(declared) {
|
|
65
|
+
if (!declared.startsWith(DEPOSIT_PREFIX)) {
|
|
66
|
+
throw new Error(`deposit-required: not a deposit path: ${declared}`);
|
|
67
|
+
}
|
|
68
|
+
return declared.slice(DEPOSIT_PREFIX.length);
|
|
69
|
+
}
|
|
70
|
+
/** Prepack mapping used by @deftai/directive-content. */
|
|
71
|
+
export function sourcePathForPackRelative(repoRoot, packRelative) {
|
|
72
|
+
const rel = packRelative.replace(/\\/g, "/");
|
|
73
|
+
if (rel === "main.md" ||
|
|
74
|
+
rel === "SKILL.md" ||
|
|
75
|
+
rel === "Taskfile.yml" ||
|
|
76
|
+
rel.startsWith("tasks/") ||
|
|
77
|
+
rel.startsWith(".githooks/")) {
|
|
78
|
+
return join(repoRoot, ...rel.split("/"));
|
|
79
|
+
}
|
|
80
|
+
return join(repoRoot, "content", ...rel.split("/"));
|
|
81
|
+
}
|
|
82
|
+
export function evaluateDepositClosure(options) {
|
|
83
|
+
const missing = [];
|
|
84
|
+
for (const declared of options.paths) {
|
|
85
|
+
const rel = packRelativeFromDepositPath(declared);
|
|
86
|
+
const target = join(options.packRoot, ...rel.split("/"));
|
|
87
|
+
if (!existsSync(target)) {
|
|
88
|
+
missing.push(declared);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return { ok: missing.length === 0, missing, checked: options.paths.length };
|
|
92
|
+
}
|
|
93
|
+
export function loadDepositRequiredDeclaration(filePath) {
|
|
94
|
+
return parseDepositRequiredDeclaration(readFileSync(filePath, "utf8"));
|
|
95
|
+
}
|
|
96
|
+
export function resolveDeclarationFile(root) {
|
|
97
|
+
const underContent = join(root, "content", DEPOSIT_REQUIRED_REL);
|
|
98
|
+
if (existsSync(underContent)) {
|
|
99
|
+
return underContent;
|
|
100
|
+
}
|
|
101
|
+
const underRoot = join(root, DEPOSIT_REQUIRED_REL);
|
|
102
|
+
if (existsSync(underRoot)) {
|
|
103
|
+
return underRoot;
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
export function evaluateInstalledDepositClosure(projectRoot) {
|
|
108
|
+
const deftDir = join(projectRoot, ".deft", "core");
|
|
109
|
+
const declarationPath = resolveDeclarationFile(deftDir) ?? resolveDeclarationFile(projectRoot);
|
|
110
|
+
if (declarationPath === null) {
|
|
111
|
+
return { skipped: true, missing: [], declarationPath: null, error: null };
|
|
112
|
+
}
|
|
113
|
+
if (!existsSync(deftDir)) {
|
|
114
|
+
return { skipped: true, missing: [], declarationPath, error: null };
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const declaration = loadDepositRequiredDeclaration(declarationPath);
|
|
118
|
+
const result = evaluateDepositClosure({ packRoot: deftDir, paths: declaration.paths });
|
|
119
|
+
return { skipped: false, missing: result.missing, declarationPath, error: null };
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
123
|
+
return { skipped: false, missing: [], declarationPath, error: reason };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
export function renderDeclaredDepositClosureLine(result) {
|
|
127
|
+
if (result.skipped) {
|
|
128
|
+
return "Deposit required-paths: skip -- no C1 declaration in this tree.";
|
|
129
|
+
}
|
|
130
|
+
if (result.error) {
|
|
131
|
+
return ("Deposit required-paths: fail -- could not read C1 declaration (" +
|
|
132
|
+
result.error +
|
|
133
|
+
"). Run directive update to refresh the deposit (#3601 C1).");
|
|
134
|
+
}
|
|
135
|
+
if (result.missing.length === 0) {
|
|
136
|
+
return "Deposit required-paths: ok -- declared C1 paths exist in .deft/core.";
|
|
137
|
+
}
|
|
138
|
+
const sample = result.missing.slice(0, 5).join(", ");
|
|
139
|
+
const extra = result.missing.length > 5 ? ` (+${String(result.missing.length - 5)} more)` : "";
|
|
140
|
+
return ("Deposit required-paths: fail -- " +
|
|
141
|
+
String(result.missing.length) +
|
|
142
|
+
" declared path(s) missing from .deft/core. Examples: " +
|
|
143
|
+
sample +
|
|
144
|
+
extra +
|
|
145
|
+
". Run directive update to refresh the deposit (#3601 C1).");
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=deposit-required.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { resolveCapacityAllocation } from "./capacity-policy.js";
|
|
2
2
|
export { computeReport, renderReport } from "./capacity-show.js";
|
|
3
|
+
export * as depositRequired from "./deposit-required.js";
|
|
3
4
|
export { isDatePrefixedVbriefFilename } from "./filename.js";
|
|
4
5
|
export { extractLinkTargets, shouldSkipLinkTarget } from "./link-parser.js";
|
|
5
6
|
export * from "./types.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { resolveCapacityAllocation } from "./capacity-policy.js";
|
|
2
2
|
export { computeReport, renderReport } from "./capacity-show.js";
|
|
3
|
+
export * as depositRequired from "./deposit-required.js";
|
|
3
4
|
export { isDatePrefixedVbriefFilename } from "./filename.js";
|
|
4
5
|
export { extractLinkTargets, shouldSkipLinkTarget } from "./link-parser.js";
|
|
5
6
|
export * from "./types.js";
|
|
@@ -18,8 +18,7 @@ export interface ValidateLinksOptions {
|
|
|
18
18
|
readonly linkCheckStrict?: boolean;
|
|
19
19
|
readonly argv?: readonly string[];
|
|
20
20
|
}
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
*/
|
|
21
|
+
/** Collect broken internal markdown links under cwd. Used by packed-fixture tests (#3937). */
|
|
22
|
+
export declare function collectBrokenLinks(cwd: string): BrokenLink[];
|
|
24
23
|
export declare function evaluate(options?: ValidateLinksOptions): EvaluateResult;
|
|
25
24
|
//# sourceMappingURL=validate-links.d.ts.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
2
|
import { join, relative, resolve, sep } from "node:path";
|
|
3
|
+
import { evaluateLiveProcedureTargets, formatLiveProcedureFailure, } from "../deposit/live-procedure-targets.js";
|
|
3
4
|
import { NON_PRODUCT_DIRS } from "../fs/non-product-dirs.js";
|
|
4
5
|
import { extractLinkTargets, shouldSkipLinkTarget } from "./link-parser.js";
|
|
5
6
|
/**
|
|
@@ -43,7 +44,8 @@ function collectMarkdownFiles(root) {
|
|
|
43
44
|
walk(root, []);
|
|
44
45
|
return out.sort();
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
+
/** Collect broken internal markdown links under cwd. Used by packed-fixture tests (#3937). */
|
|
48
|
+
export function collectBrokenLinks(cwd) {
|
|
47
49
|
const broken = [];
|
|
48
50
|
const root = resolve(cwd);
|
|
49
51
|
for (const md of collectMarkdownFiles(root)) {
|
|
@@ -82,13 +84,38 @@ function findBrokenLinks(cwd) {
|
|
|
82
84
|
/**
|
|
83
85
|
* Validate internal markdown links. Faithful to `scripts/validate-links.py`.
|
|
84
86
|
*/
|
|
87
|
+
function contentRootForC3(cwd) {
|
|
88
|
+
const underContent = join(cwd, "content");
|
|
89
|
+
return existsSync(underContent) ? underContent : cwd;
|
|
90
|
+
}
|
|
91
|
+
function extraMarkdownForC3(cwd) {
|
|
92
|
+
const extras = [];
|
|
93
|
+
for (const name of ["main.md", "SKILL.md"]) {
|
|
94
|
+
const absolutePath = join(cwd, name);
|
|
95
|
+
if (existsSync(absolutePath)) {
|
|
96
|
+
extras.push({ relativePath: name, absolutePath });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return extras;
|
|
100
|
+
}
|
|
85
101
|
export function evaluate(options = {}) {
|
|
86
102
|
const cwd = resolve(options.cwd ?? ".");
|
|
87
103
|
const strict = options.strict === true ||
|
|
88
104
|
options.linkCheckStrict === true ||
|
|
89
105
|
(options.argv ?? []).includes("--strict") ||
|
|
90
106
|
process.env.LINK_CHECK_STRICT === "1";
|
|
91
|
-
const
|
|
107
|
+
const c3 = evaluateLiveProcedureTargets({
|
|
108
|
+
stagedRoot: contentRootForC3(cwd),
|
|
109
|
+
extraFiles: extraMarkdownForC3(cwd),
|
|
110
|
+
});
|
|
111
|
+
if (c3.uniqueTargets.length > 0) {
|
|
112
|
+
return {
|
|
113
|
+
code: 1,
|
|
114
|
+
message: formatLiveProcedureFailure(c3),
|
|
115
|
+
stream: "stdout",
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const broken = collectBrokenLinks(cwd);
|
|
92
119
|
if (broken.length === 0) {
|
|
93
120
|
return {
|
|
94
121
|
code: 0,
|
|
@@ -6,8 +6,13 @@ export interface ActivateOptions {
|
|
|
6
6
|
readonly now?: Date;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Pure activator
|
|
10
|
-
* ``scripts/vbrief_activate.py::activate
|
|
9
|
+
* Pure activator -- returns ``{ exitCode, message }``. Ported from
|
|
10
|
+
* ``scripts/vbrief_activate.py::activate`` under the #1782 byte-identical
|
|
11
|
+
* parity contract, with one deliberate divergence: the Python oracle created a
|
|
12
|
+
* ``vBRIEFInfo`` when the artifact carried no envelope, and that behaviour is
|
|
13
|
+
* NOT preserved (#3933). Envelope handling now follows the shared lifecycle
|
|
14
|
+
* policy -- stamp whichever envelope exists, refuse an envelope-less artifact
|
|
15
|
+
* by name.
|
|
11
16
|
*/
|
|
12
17
|
export declare function activate(vbriefPath: string, options?: ActivateOptions): ActivateResult;
|
|
13
18
|
//# sourceMappingURL=activate.d.ts.map
|
|
@@ -2,6 +2,7 @@ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, unli
|
|
|
2
2
|
import { basename, dirname, resolve } from "node:path";
|
|
3
3
|
import { containedWrite } from "../fs/contained-write.js";
|
|
4
4
|
import { assertProjectionContained, ProjectionContainmentError, } from "../fs/projection-containment.js";
|
|
5
|
+
import { BRIEF_ENVELOPE_KEYS, missingEnvelopeMessage, stampExistingEnvelopes, } from "../lifecycle/brief-envelope.js";
|
|
5
6
|
import { evaluateEffortActivateGate } from "../scope/effort-activate-gate.js";
|
|
6
7
|
import { utcNowIso } from "../scope/vbrief-json.js";
|
|
7
8
|
import { pythonJsonPretty } from "../vbrief-build/json.js";
|
|
@@ -57,8 +58,13 @@ function loadVbrief(vbriefPath) {
|
|
|
57
58
|
return { payload: payload, error: null };
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
60
|
-
* Pure activator
|
|
61
|
-
* ``scripts/vbrief_activate.py::activate
|
|
61
|
+
* Pure activator -- returns ``{ exitCode, message }``. Ported from
|
|
62
|
+
* ``scripts/vbrief_activate.py::activate`` under the #1782 byte-identical
|
|
63
|
+
* parity contract, with one deliberate divergence: the Python oracle created a
|
|
64
|
+
* ``vBRIEFInfo`` when the artifact carried no envelope, and that behaviour is
|
|
65
|
+
* NOT preserved (#3933). Envelope handling now follows the shared lifecycle
|
|
66
|
+
* policy -- stamp whichever envelope exists, refuse an envelope-less artifact
|
|
67
|
+
* by name.
|
|
62
68
|
*/
|
|
63
69
|
export function activate(vbriefPath, options = {}) {
|
|
64
70
|
const now = options.now ?? new Date();
|
|
@@ -143,19 +149,26 @@ export function activate(vbriefPath, options = {}) {
|
|
|
143
149
|
}
|
|
144
150
|
throw err;
|
|
145
151
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
152
|
+
for (const key of BRIEF_ENVELOPE_KEYS) {
|
|
153
|
+
if (!(key in payload)) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const env = payload[key];
|
|
157
|
+
if (env === null || typeof env !== "object" || Array.isArray(env)) {
|
|
158
|
+
return {
|
|
159
|
+
exitCode: 1,
|
|
160
|
+
message: `vBRIEF at ${vbriefPath} has a non-object \`${key}\` -- malformed.`,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
151
163
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
164
|
+
// #3933: stamp the envelope the brief already carries; never create one. A
|
|
165
|
+
// manufactured version-less `vBRIEFInfo` wins schema resolution over a valid
|
|
166
|
+
// `xBRIEFInfo`, so the brief this verb just moved would fail validation.
|
|
167
|
+
const stampedEnvelopes = stampExistingEnvelopes(payload, utcNowIso(now));
|
|
168
|
+
if (stampedEnvelopes.length === 0) {
|
|
169
|
+
return { exitCode: 1, message: missingEnvelopeMessage(`vBRIEF at ${vbriefPath}`) };
|
|
157
170
|
}
|
|
158
|
-
|
|
171
|
+
planObj.status = TARGET_STATUS;
|
|
159
172
|
try {
|
|
160
173
|
mkdirSync(activeDir, { recursive: true });
|
|
161
174
|
}
|
|
@@ -44,6 +44,15 @@ export declare const VERIFY_AC_CHECK_ID_PREFIX = "verify:ac";
|
|
|
44
44
|
export declare function verifyAcCheckId(scopeKey?: string | null): string;
|
|
45
45
|
/** Test seam: isolate stdout-dest buffer across cases. */
|
|
46
46
|
export declare function resetInProcessVerificationBuffer(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Product-oracle outcome for one acceptance walk (#3615).
|
|
49
|
+
*
|
|
50
|
+
* A safety refusal is not a measurement. All-refused walks emit nothing.
|
|
51
|
+
* Mixed refused + executed-pass walks emit nothing (filtering refusals then
|
|
52
|
+
* classifying the remainder would be a false green). Any executed fail still
|
|
53
|
+
* emits fail. flag.ts is unchanged.
|
|
54
|
+
*/
|
|
55
|
+
export declare function productOracleOutcomeForWalk(runs: readonly LiteralAcceptanceRunResult[]): "pass" | "fail" | null;
|
|
47
56
|
/**
|
|
48
57
|
* Record one walk-level verification event for the executed command set (#3322 / #3397).
|
|
49
58
|
* Fail and pass use the same method_fingerprint shape (command list + cwd hash).
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
11
|
import { existsSync, readFileSync } from "node:fs";
|
|
12
12
|
import { resolve } from "node:path";
|
|
13
|
+
import { isSafetyRefusalRun } from "../literal-acceptance/run.js";
|
|
13
14
|
import { parseRunSummaryJsonl, RunSummaryEmitter, resolveRunSummaryDestination, } from "../run-summary/index.js";
|
|
14
15
|
import { flagPassAfterFailWithMethodChange, readVerificationAttempts, unresolvedMethodChangePasses, } from "./flag.js";
|
|
15
16
|
function formatUnresolved(flag) {
|
|
@@ -57,6 +58,25 @@ function inProcessVerificationText() {
|
|
|
57
58
|
}
|
|
58
59
|
return inProcessVerificationLines.join("\n");
|
|
59
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Product-oracle outcome for one acceptance walk (#3615).
|
|
63
|
+
*
|
|
64
|
+
* A safety refusal is not a measurement. All-refused walks emit nothing.
|
|
65
|
+
* Mixed refused + executed-pass walks emit nothing (filtering refusals then
|
|
66
|
+
* classifying the remainder would be a false green). Any executed fail still
|
|
67
|
+
* emits fail. flag.ts is unchanged.
|
|
68
|
+
*/
|
|
69
|
+
export function productOracleOutcomeForWalk(runs) {
|
|
70
|
+
const refused = runs.filter(isSafetyRefusalRun);
|
|
71
|
+
const executed = runs.filter((run) => !isSafetyRefusalRun(run));
|
|
72
|
+
if (executed.length === 0) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
if (refused.length > 0 && executed.every((run) => run.ok)) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return executed.every((run) => run.ok) ? "pass" : "fail";
|
|
79
|
+
}
|
|
60
80
|
/**
|
|
61
81
|
* Record one walk-level verification event for the executed command set (#3322 / #3397).
|
|
62
82
|
* Fail and pass use the same method_fingerprint shape (command list + cwd hash).
|
|
@@ -69,6 +89,10 @@ export function emitVerifyAcAttempts(options) {
|
|
|
69
89
|
if (options.runs.length === 0) {
|
|
70
90
|
return;
|
|
71
91
|
}
|
|
92
|
+
const outcome = productOracleOutcomeForWalk(options.runs);
|
|
93
|
+
if (outcome === null) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
72
96
|
try {
|
|
73
97
|
const env = options.env ?? process.env;
|
|
74
98
|
const projectRoot = resolve(options.projectRoot);
|
|
@@ -85,16 +109,15 @@ export function emitVerifyAcAttempts(options) {
|
|
|
85
109
|
component: "verify-ac",
|
|
86
110
|
writeStdout: options.writeStdout,
|
|
87
111
|
});
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const cwdKey =
|
|
112
|
+
// Method identity is the executed command set. Refused rows are not
|
|
113
|
+
// measurements; including them would make a later same-command product
|
|
114
|
+
// fix look like a method change (#3615 Greptile P1).
|
|
115
|
+
const executed = options.runs.filter((run) => !isSafetyRefusalRun(run));
|
|
116
|
+
const commands = executed.map((run) => run.command);
|
|
117
|
+
const firstCwd = executed[0]?.cwd ?? "";
|
|
118
|
+
const cwdKey = executed.every((run) => run.cwd === firstCwd)
|
|
95
119
|
? firstCwd
|
|
96
|
-
:
|
|
97
|
-
const outcome = options.runs.every((run) => run.ok) ? "pass" : "fail";
|
|
120
|
+
: executed.map((run) => run.cwd).join("\0");
|
|
98
121
|
const emitted = emitter.emitVerification({
|
|
99
122
|
check_id: checkId,
|
|
100
123
|
method_fingerprint: methodFingerprintForWalk(commands, cwdKey),
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check 1 -- staged-pack deposit closure (#3900 / #3601 C1).
|
|
3
|
+
*
|
|
4
|
+
* Resolves the C1 declaration against a staged pack root. Does not infer
|
|
5
|
+
* required paths from AGENTS.md prose. Reuses evaluateDepositClosure.
|
|
6
|
+
*
|
|
7
|
+
* Three-state: 0 clean / 1 missing declared paths / 2 config.
|
|
8
|
+
*/
|
|
9
|
+
import { type DepositClosureResult, type DepositRequiredDeclaration } from "../validate-content/deposit-required.js";
|
|
10
|
+
export interface StagedDepositClosureResult {
|
|
11
|
+
readonly code: 0 | 1 | 2;
|
|
12
|
+
readonly message: string;
|
|
13
|
+
readonly stream: "stdout" | "stderr";
|
|
14
|
+
readonly missing: readonly string[];
|
|
15
|
+
readonly checked: number;
|
|
16
|
+
}
|
|
17
|
+
/** Copy declared C1 paths into dest using the content-package mapping. */
|
|
18
|
+
export declare function stageDeclaredPack(repoRoot: string, destPackRoot: string): DepositRequiredDeclaration;
|
|
19
|
+
export declare function formatStagedDepositClosureLine(result: DepositClosureResult): string;
|
|
20
|
+
export declare function evaluateStagedDepositClosure(packRoot: string, paths: readonly string[]): StagedDepositClosureResult;
|
|
21
|
+
export declare function evaluateDepositClosureFromRepo(repoRoot: string): StagedDepositClosureResult;
|
|
22
|
+
export declare function evaluateDepositClosureAtRoot(root: string, packRootExplicit: boolean): StagedDepositClosureResult;
|
|
23
|
+
//# sourceMappingURL=deposit-closure.d.ts.map
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check 1 -- staged-pack deposit closure (#3900 / #3601 C1).
|
|
3
|
+
*
|
|
4
|
+
* Resolves the C1 declaration against a staged pack root. Does not infer
|
|
5
|
+
* required paths from AGENTS.md prose. Reuses evaluateDepositClosure.
|
|
6
|
+
*
|
|
7
|
+
* Three-state: 0 clean / 1 missing declared paths / 2 config.
|
|
8
|
+
*/
|
|
9
|
+
import { cpSync, existsSync, mkdirSync, mkdtempSync, rmSync, statSync } from "node:fs";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { dirname, join, resolve } from "node:path";
|
|
12
|
+
import { evaluateDepositClosure, loadDepositRequiredDeclaration, packRelativeFromDepositPath, resolveDeclarationFile, sourcePathForPackRelative, } from "../validate-content/deposit-required.js";
|
|
13
|
+
const EXIT_OK = 0;
|
|
14
|
+
const EXIT_MISSING = 1;
|
|
15
|
+
const EXIT_CONFIG = 2;
|
|
16
|
+
const REMEDIATION = "Recovery: restore the declared files in content/ (or root harness files) so they survive content-package prepack. Do not infer paths from AGENTS.md prose (#3601 C1 / #3900).";
|
|
17
|
+
function keepPackFile(src) {
|
|
18
|
+
const posix = src.replace(/\\/g, "/");
|
|
19
|
+
if (posix.includes("__pycache__"))
|
|
20
|
+
return false;
|
|
21
|
+
if (posix.endsWith(".pyc") || posix.endsWith(".py"))
|
|
22
|
+
return false;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
/** Copy declared C1 paths into dest using the content-package mapping. */
|
|
26
|
+
export function stageDeclaredPack(repoRoot, destPackRoot) {
|
|
27
|
+
const declarationPath = resolveDeclarationFile(repoRoot);
|
|
28
|
+
if (declarationPath === null) {
|
|
29
|
+
throw new Error("deposit-closure: C1 declaration missing (contracts/deposit-required-paths.json).");
|
|
30
|
+
}
|
|
31
|
+
const declaration = loadDepositRequiredDeclaration(declarationPath);
|
|
32
|
+
mkdirSync(destPackRoot, { recursive: true });
|
|
33
|
+
for (const declared of declaration.paths) {
|
|
34
|
+
const rel = packRelativeFromDepositPath(declared);
|
|
35
|
+
const from = sourcePathForPackRelative(repoRoot, rel);
|
|
36
|
+
if (!existsSync(from)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (!keepPackFile(from)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const to = join(destPackRoot, ...rel.split("/"));
|
|
43
|
+
mkdirSync(dirname(to), { recursive: true });
|
|
44
|
+
cpSync(from, to);
|
|
45
|
+
}
|
|
46
|
+
return declaration;
|
|
47
|
+
}
|
|
48
|
+
export function formatStagedDepositClosureLine(result) {
|
|
49
|
+
if (result.ok) {
|
|
50
|
+
return ("Deposit required-paths: ok -- " +
|
|
51
|
+
String(result.checked) +
|
|
52
|
+
" declared C1 path(s) exist in the staged pack.");
|
|
53
|
+
}
|
|
54
|
+
const sample = result.missing.slice(0, 5).join(", ");
|
|
55
|
+
const extra = result.missing.length > 5 ? " (+" + String(result.missing.length - 5) + " more)" : "";
|
|
56
|
+
return ("Deposit required-paths: fail -- " +
|
|
57
|
+
String(result.missing.length) +
|
|
58
|
+
" declared path(s) missing from staged pack. Examples: " +
|
|
59
|
+
sample +
|
|
60
|
+
extra +
|
|
61
|
+
". " +
|
|
62
|
+
REMEDIATION);
|
|
63
|
+
}
|
|
64
|
+
export function evaluateStagedDepositClosure(packRoot, paths) {
|
|
65
|
+
const root = resolve(packRoot);
|
|
66
|
+
let isDir = false;
|
|
67
|
+
try {
|
|
68
|
+
isDir = statSync(root).isDirectory();
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
isDir = false;
|
|
72
|
+
}
|
|
73
|
+
if (!isDir) {
|
|
74
|
+
return {
|
|
75
|
+
code: EXIT_CONFIG,
|
|
76
|
+
message: "verify_deposit_closure: --pack-root is not a directory: " +
|
|
77
|
+
root +
|
|
78
|
+
"\n Recovery: pass a staged pack root or framework checkout.",
|
|
79
|
+
stream: "stderr",
|
|
80
|
+
missing: [],
|
|
81
|
+
checked: 0,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const result = evaluateDepositClosure({ packRoot: root, paths });
|
|
85
|
+
if (result.ok) {
|
|
86
|
+
return {
|
|
87
|
+
code: EXIT_OK,
|
|
88
|
+
message: formatStagedDepositClosureLine(result),
|
|
89
|
+
stream: "stdout",
|
|
90
|
+
missing: result.missing,
|
|
91
|
+
checked: result.checked,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
code: EXIT_MISSING,
|
|
96
|
+
message: formatStagedDepositClosureLine(result),
|
|
97
|
+
stream: "stderr",
|
|
98
|
+
missing: result.missing,
|
|
99
|
+
checked: result.checked,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export function evaluateDepositClosureFromRepo(repoRoot) {
|
|
103
|
+
const root = resolve(repoRoot);
|
|
104
|
+
const declarationPath = resolveDeclarationFile(root);
|
|
105
|
+
if (declarationPath === null) {
|
|
106
|
+
return {
|
|
107
|
+
code: EXIT_CONFIG,
|
|
108
|
+
message: "verify_deposit_closure: C1 declaration missing.\n Recovery: add content/contracts/deposit-required-paths.json (#3601 C1).",
|
|
109
|
+
stream: "stderr",
|
|
110
|
+
missing: [],
|
|
111
|
+
checked: 0,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
const tmp = mkdtempSync(join(tmpdir(), "deft-3900-pack-"));
|
|
115
|
+
try {
|
|
116
|
+
const declaration = stageDeclaredPack(root, tmp);
|
|
117
|
+
return evaluateStagedDepositClosure(tmp, declaration.paths);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
121
|
+
return {
|
|
122
|
+
code: EXIT_CONFIG,
|
|
123
|
+
message: "verify_deposit_closure: " + reason + "\n " + REMEDIATION,
|
|
124
|
+
stream: "stderr",
|
|
125
|
+
missing: [],
|
|
126
|
+
checked: 0,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export function evaluateDepositClosureAtRoot(root, packRootExplicit) {
|
|
134
|
+
if (packRootExplicit) {
|
|
135
|
+
const declarationPath = resolveDeclarationFile(root);
|
|
136
|
+
if (declarationPath === null) {
|
|
137
|
+
return {
|
|
138
|
+
code: EXIT_CONFIG,
|
|
139
|
+
message: "verify_deposit_closure: C1 declaration missing under the given pack root.\n Recovery: stage contracts/deposit-required-paths.json with the pack (#3601 C1).",
|
|
140
|
+
stream: "stderr",
|
|
141
|
+
missing: [],
|
|
142
|
+
checked: 0,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const declaration = loadDepositRequiredDeclaration(declarationPath);
|
|
147
|
+
return evaluateStagedDepositClosure(root, declaration.paths);
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
151
|
+
return {
|
|
152
|
+
code: EXIT_CONFIG,
|
|
153
|
+
message: "verify_deposit_closure: " + reason + "\n " + REMEDIATION,
|
|
154
|
+
stream: "stderr",
|
|
155
|
+
missing: [],
|
|
156
|
+
checked: 0,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return evaluateDepositClosureFromRepo(root);
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=deposit-closure.js.map
|
|
@@ -5,10 +5,12 @@ export * from "./contained-writes.js";
|
|
|
5
5
|
export * from "./content-manifest.js";
|
|
6
6
|
export { CANONICAL_SCHEMA_REL, type ContractDriftOptions, type ContractDriftResult, evaluateContractDrift, PUBLISHED_SCHEMA_REL, } from "./contract-drift.js";
|
|
7
7
|
export * from "./cursor-tier1.js";
|
|
8
|
+
export * from "./deposit-closure.js";
|
|
8
9
|
export * from "./openclaw-tier1.js";
|
|
9
10
|
export * from "./python-call-scan.js";
|
|
10
11
|
export * from "./rule-ownership-lint.js";
|
|
11
12
|
export * from "./scm-boundary.js";
|
|
13
|
+
export * from "./semantic-single-source.js";
|
|
12
14
|
export * from "./skill-external-fetch-gate.js";
|
|
13
15
|
export * from "./verify-stubs.js";
|
|
14
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -5,10 +5,12 @@ export * from "./contained-writes.js";
|
|
|
5
5
|
export * from "./content-manifest.js";
|
|
6
6
|
export { CANONICAL_SCHEMA_REL, evaluateContractDrift, PUBLISHED_SCHEMA_REL, } from "./contract-drift.js";
|
|
7
7
|
export * from "./cursor-tier1.js";
|
|
8
|
+
export * from "./deposit-closure.js";
|
|
8
9
|
export * from "./openclaw-tier1.js";
|
|
9
10
|
export * from "./python-call-scan.js";
|
|
10
11
|
export * from "./rule-ownership-lint.js";
|
|
11
12
|
export * from "./scm-boundary.js";
|
|
13
|
+
export * from "./semantic-single-source.js";
|
|
12
14
|
export * from "./skill-external-fetch-gate.js";
|
|
13
15
|
export * from "./verify-stubs.js";
|
|
14
16
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C2 — semantic single-source conformance (#3600 / #3899).
|
|
3
|
+
*
|
|
4
|
+
* Shipped guidance must name one value where the framework has one value.
|
|
5
|
+
* The 0.6-versus-0.8 defect lives inside a file that resolves perfectly, so
|
|
6
|
+
* pointer existence (C1) cannot see it. This oracle is not a link checker.
|
|
7
|
+
*
|
|
8
|
+
* Evaluates a staged pack root (flattened consumer deposit) or a source
|
|
9
|
+
* checkout (content/ prefix + root main.md). Three-state: 0 clean / 1 drift / 2 config.
|
|
10
|
+
*/
|
|
11
|
+
/** Closed, typed current-authoring surfaces (#3600 AC / #3899 C2). */
|
|
12
|
+
export declare const C2_AUTHORING_SURFACES: readonly ["main.md", "skills/deft-directive-setup/SKILL.md", "skills/deft-directive-build/SKILL.md", "skills/deft-directive-interview/SKILL.md", "skills/deft-directive-refinement/SKILL.md", "skills/deft-directive-sync/SKILL.md", "templates/project.md.template", "templates/make-spec.md", "conventions/references.md", "commands.md"];
|
|
13
|
+
export type C2AuthoringSurface = (typeof C2_AUTHORING_SURFACES)[number];
|
|
14
|
+
export interface SemanticSingleSourceViolation {
|
|
15
|
+
readonly path: string;
|
|
16
|
+
readonly line: number;
|
|
17
|
+
readonly version: string;
|
|
18
|
+
readonly excerpt: string;
|
|
19
|
+
}
|
|
20
|
+
export interface SemanticSingleSourceResult {
|
|
21
|
+
readonly code: 0 | 1 | 2;
|
|
22
|
+
readonly message: string;
|
|
23
|
+
readonly stream: "stdout" | "stderr";
|
|
24
|
+
readonly setupWriteVersion: string | null;
|
|
25
|
+
readonly violations: readonly SemanticSingleSourceViolation[];
|
|
26
|
+
readonly currentWriteVersions: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a closed-list surface against a flattened pack root or a source
|
|
30
|
+
* checkout (content/ prefix for everything except root harness main.md).
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveAuthoringSurface(packRoot: string, rel: string): string | null;
|
|
33
|
+
export declare function extractQuotedVersions(line: string): string[];
|
|
34
|
+
export declare function extractSetupWriteVersion(setupText: string): string | null;
|
|
35
|
+
export declare function evaluateSemanticSingleSource(packRoot: string): SemanticSingleSourceResult;
|
|
36
|
+
//# sourceMappingURL=semantic-single-source.d.ts.map
|