@deftai/directive-core 0.104.0 → 0.105.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/authz/classify.js +526 -42
- package/dist/check/cached-orchestrator.d.ts +1 -1
- package/dist/check/cached-orchestrator.js +2 -2
- package/dist/check/named-cause.d.ts +1 -1
- package/dist/check/named-cause.js +33 -3
- package/dist/codebase/default-extractor.d.ts +5 -0
- package/dist/codebase/default-extractor.js +7 -15
- package/dist/deposit/copy-tree.js +60 -0
- package/dist/deposit/python-free.js +26 -18
- package/dist/doctor/checks.d.ts +8 -0
- package/dist/doctor/checks.js +37 -25
- package/dist/doctor/doctor-state.d.ts +4 -0
- package/dist/doctor/doctor-state.js +7 -1
- package/dist/doctor/main.js +9 -19
- package/dist/doctor/types.d.ts +9 -0
- package/dist/fs/contained-write.d.ts +115 -1
- package/dist/fs/contained-write.js +241 -5
- package/dist/fs/mutation-ledger.d.ts +54 -0
- package/dist/fs/mutation-ledger.js +133 -0
- package/dist/fs/non-product-dirs.d.ts +79 -0
- package/dist/fs/non-product-dirs.js +96 -0
- package/dist/hooks/dispatcher.d.ts +3 -1
- package/dist/hooks/dispatcher.js +14 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/init-deposit/agent-hooks.js +17 -15
- package/dist/init-deposit/core-guard-pin-content.d.ts +7 -0
- package/dist/init-deposit/core-guard-pin-content.js +393 -0
- package/dist/init-deposit/gitignore.js +9 -0
- package/dist/init-deposit/hygiene.d.ts +47 -11
- package/dist/init-deposit/hygiene.js +172 -37
- package/dist/init-deposit/legacy-detect.js +6 -2
- package/dist/init-deposit/refresh.d.ts +21 -1
- package/dist/init-deposit/refresh.js +106 -9
- package/dist/init-deposit/scaffold.js +28 -279
- package/dist/init-deposit/slash-deposit.js +13 -7
- package/dist/init-deposit/xbrief-projections.d.ts +8 -1
- package/dist/init-deposit/xbrief-projections.js +24 -11
- package/dist/intake/clause-derivation.d.ts +38 -1
- package/dist/intake/clause-derivation.js +211 -9
- package/dist/intake/issue-ingest.d.ts +3 -1
- package/dist/intake/issue-ingest.js +35 -6
- package/dist/lifecycle/completed-tracked-on-delivery.d.ts +5 -0
- package/dist/lifecycle/completed-tracked-on-delivery.js +85 -18
- package/dist/literal-acceptance/capture.d.ts +10 -0
- package/dist/literal-acceptance/capture.js +224 -75
- package/dist/literal-acceptance/evaluate.d.ts +29 -4
- package/dist/literal-acceptance/evaluate.js +70 -2
- package/dist/literal-acceptance/index.d.ts +3 -3
- package/dist/literal-acceptance/index.js +3 -3
- package/dist/literal-acceptance/safety.d.ts +41 -0
- package/dist/literal-acceptance/safety.js +126 -2
- package/dist/literal-acceptance/types.d.ts +8 -0
- package/dist/orphan-active/evaluate.d.ts +7 -1
- package/dist/orphan-active/evaluate.js +102 -23
- package/dist/platform/platform-capabilities.js +2 -3
- package/dist/policy/base-branch.d.ts +37 -0
- package/dist/policy/base-branch.js +114 -0
- package/dist/policy/branch-sync.d.ts +80 -0
- package/dist/policy/branch-sync.js +211 -0
- package/dist/policy/ceremony-dial-escalation.js +1 -0
- package/dist/policy/ceremony-dial.js +4 -14
- package/dist/policy/delivery-branch.d.ts +5 -3
- package/dist/policy/delivery-branch.js +7 -3
- package/dist/policy/file-size-thresholds.d.ts +24 -0
- package/dist/policy/file-size-thresholds.js +23 -0
- package/dist/policy/forge-outage-retry.d.ts +47 -0
- package/dist/policy/forge-outage-retry.js +157 -0
- package/dist/policy/index.d.ts +7 -0
- package/dist/policy/index.js +66 -7
- package/dist/policy/project-invariants.d.ts +50 -0
- package/dist/policy/project-invariants.js +205 -0
- package/dist/policy/sync-default.d.ts +129 -0
- package/dist/policy/sync-default.js +452 -0
- package/dist/policy/sync-max-files.d.ts +93 -0
- package/dist/policy/sync-max-files.js +192 -0
- package/dist/pr-monitor/absent-required.d.ts +11 -0
- package/dist/pr-monitor/absent-required.js +61 -0
- package/dist/pr-monitor/constants.d.ts +7 -0
- package/dist/pr-monitor/constants.js +7 -0
- package/dist/pr-monitor/index.d.ts +2 -1
- package/dist/pr-monitor/index.js +2 -1
- package/dist/pr-monitor/main.js +4 -0
- package/dist/pr-monitor/monitor.js +24 -1
- package/dist/pr-wait-mergeable/classify.js +6 -0
- package/dist/preflight/evaluate.d.ts +4 -0
- package/dist/preflight/evaluate.js +35 -1
- package/dist/preflight/index.d.ts +4 -0
- package/dist/preflight/index.js +2 -0
- package/dist/preflight/intended-placement.d.ts +62 -0
- package/dist/preflight/intended-placement.js +275 -0
- package/dist/preflight/project-invariants-gate.d.ts +29 -0
- package/dist/preflight/project-invariants-gate.js +82 -0
- package/dist/product-first-done-gate/acceptance-resolver.d.ts +128 -0
- package/dist/product-first-done-gate/acceptance-resolver.js +144 -0
- package/dist/product-first-done-gate/acceptance.d.ts +7 -4
- package/dist/product-first-done-gate/acceptance.js +79 -8
- package/dist/product-first-done-gate/empty-resolution.d.ts +4 -1
- package/dist/product-first-done-gate/empty-resolution.js +12 -1
- package/dist/product-first-done-gate/evaluate.d.ts +12 -0
- package/dist/product-first-done-gate/evaluate.js +254 -31
- package/dist/product-first-done-gate/index.d.ts +2 -0
- package/dist/product-first-done-gate/index.js +1 -0
- package/dist/release/build-dist.d.ts +101 -0
- package/dist/release/build-dist.js +428 -46
- package/dist/run-summary/emit.d.ts +16 -10
- package/dist/run-summary/emit.js +26 -15
- package/dist/run-summary/index.d.ts +3 -2
- package/dist/run-summary/index.js +2 -1
- package/dist/run-summary/session-id.d.ts +21 -0
- package/dist/run-summary/session-id.js +92 -0
- package/dist/run-summary/types.d.ts +29 -4
- package/dist/run-summary/types.js +1 -0
- package/dist/scope/acceptance-evidence.d.ts +19 -7
- package/dist/scope/acceptance-evidence.js +38 -11
- package/dist/scope/delivery-evidence.d.ts +3 -3
- package/dist/scope/delivery-evidence.js +22 -27
- package/dist/scope/index.d.ts +1 -0
- package/dist/scope/index.js +1 -0
- package/dist/scope/parent-lineage.js +7 -6
- package/dist/scope/project-invariant-coverage.d.ts +54 -0
- package/dist/scope/project-invariant-coverage.js +322 -0
- package/dist/scope/transition.js +1 -1
- package/dist/scope-provenance/compare-intent.d.ts +27 -0
- package/dist/scope-provenance/compare-intent.js +233 -0
- package/dist/scope-provenance/digest.d.ts +18 -1
- package/dist/scope-provenance/digest.js +16 -11
- package/dist/scope-provenance/evaluate.d.ts +5 -1
- package/dist/scope-provenance/evaluate.js +64 -4
- package/dist/scope-provenance/extract-intent.d.ts +43 -0
- package/dist/scope-provenance/extract-intent.js +262 -0
- package/dist/scope-provenance/index.d.ts +7 -1
- package/dist/scope-provenance/index.js +7 -1
- package/dist/scope-provenance/intent-digest.d.ts +12 -0
- package/dist/scope-provenance/intent-digest.js +33 -0
- package/dist/scope-provenance/intent-evaluate.d.ts +43 -0
- package/dist/scope-provenance/intent-evaluate.js +149 -0
- package/dist/scope-provenance/json-tokenizer.d.ts +19 -0
- package/dist/scope-provenance/json-tokenizer.js +225 -0
- package/dist/scope-provenance/known-machine.d.ts +38 -0
- package/dist/scope-provenance/known-machine.js +157 -0
- package/dist/scope-provenance/mint-artifacts.d.ts +102 -0
- package/dist/scope-provenance/mint-artifacts.js +425 -0
- package/dist/session/ac-pass-banking.d.ts +4 -36
- package/dist/session/ac-pass-banking.js +30 -77
- package/dist/session/ac-pass-reuse.d.ts +53 -0
- package/dist/session/ac-pass-reuse.js +95 -0
- package/dist/session/git.js +19 -4
- package/dist/session/index.d.ts +4 -0
- package/dist/session/index.js +4 -0
- package/dist/session/occupancy-stress-worker.d.ts +7 -0
- package/dist/session/occupancy-stress-worker.js +36 -0
- package/dist/session/occupancy.d.ts +97 -0
- package/dist/session/occupancy.js +422 -0
- package/dist/session/openclaw-soft-rebind-deposit.js +6 -6
- package/dist/session/product-state-hash.d.ts +26 -0
- package/dist/session/product-state-hash.js +683 -0
- package/dist/session/session-ready.d.ts +2 -0
- package/dist/session/session-ready.js +52 -30
- package/dist/session/session-start.d.ts +7 -0
- package/dist/session/session-start.js +71 -7
- package/dist/session/verify-ac-session-cache.d.ts +42 -0
- package/dist/session/verify-ac-session-cache.js +126 -0
- package/dist/session/verify-session-ritual.d.ts +5 -0
- package/dist/session/verify-session-ritual.js +9 -0
- package/dist/slash/openclaw-deposit.js +13 -9
- package/dist/slice/constants.d.ts +2 -2
- package/dist/slice/constants.js +2 -2
- package/dist/slice/existing.js +9 -3
- package/dist/slice/lock.d.ts +16 -1
- package/dist/slice/lock.js +137 -11
- package/dist/story-ready/evaluate.d.ts +2 -0
- package/dist/story-ready/evaluate.js +13 -0
- package/dist/swarm/complete-cohort.d.ts +3 -0
- package/dist/swarm/complete-cohort.js +59 -11
- package/dist/swarm/finalize-cohort.js +33 -2
- package/dist/swarm/launch.d.ts +22 -0
- package/dist/swarm/launch.js +155 -0
- package/dist/swarm/routing-set-cli.d.ts +11 -1
- package/dist/swarm/routing-set-cli.js +13 -3
- package/dist/swarm/routing-verify.d.ts +12 -0
- package/dist/swarm/routing-verify.js +59 -20
- package/dist/swarm/routing.d.ts +14 -0
- package/dist/swarm/routing.js +53 -3
- package/dist/telemetry-coverage/fake-trial.js +10 -0
- package/dist/telemetry-coverage/kinds.js +2 -0
- package/dist/triage/actions/index.js +4 -1
- package/dist/ts-check-lane/index.d.ts +3 -0
- package/dist/ts-check-lane/index.js +2 -0
- package/dist/ts-check-lane/progress-reporter.d.ts +17 -0
- package/dist/ts-check-lane/progress-reporter.js +38 -0
- package/dist/ts-check-lane/progress.d.ts +32 -0
- package/dist/ts-check-lane/progress.js +57 -0
- package/dist/ts-check-lane/run-lane.d.ts +3 -1
- package/dist/ts-check-lane/run-lane.js +8 -6
- package/dist/validate-content/validate-links.d.ts +8 -0
- package/dist/validate-content/validate-links.js +9 -15
- package/dist/value/feedback-file.js +12 -2
- package/dist/vbrief-build/index.d.ts +1 -0
- package/dist/vbrief-build/index.js +1 -0
- package/dist/vbrief-build/project-invariants-io.d.ts +16 -0
- package/dist/vbrief-build/project-invariants-io.js +41 -0
- package/dist/vbrief-reconcile/graph.js +18 -1
- package/dist/vbrief-reconcile/index.d.ts +1 -1
- package/dist/vbrief-reconcile/index.js +1 -1
- package/dist/vbrief-reconcile/types.d.ts +13 -0
- package/dist/vbrief-reconcile/umbrellas.d.ts +14 -0
- package/dist/vbrief-reconcile/umbrellas.js +261 -26
- package/dist/vbrief-validate/index.d.ts +1 -1
- package/dist/vbrief-validate/index.js +1 -1
- package/dist/vbrief-validate/plan-hooks.d.ts +4 -0
- package/dist/vbrief-validate/plan-hooks.js +68 -0
- package/dist/verify-ac/evaluate.d.ts +7 -1
- package/dist/verify-ac/evaluate.js +34 -26
- package/dist/verify-ac/flag.d.ts +4 -0
- package/dist/verify-ac/flag.js +16 -0
- package/dist/verify-ac/index.d.ts +2 -2
- package/dist/verify-ac/index.js +2 -2
- package/dist/verify-source/contained-writes.js +2 -0
- package/dist/verify-source/verify-stubs.d.ts +15 -1
- package/dist/verify-source/verify-stubs.js +20 -16
- package/dist/vitest-runner/win32-coverage-tmp-setup.d.ts +5 -6
- package/dist/vitest-runner/win32-coverage-tmp-setup.js +5 -6
- package/dist/xbrief-migrate/migrate-project.js +2 -5
- package/package.json +3 -3
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify-time intent pin evaluation (#3376 R2–R6 / #3385).
|
|
3
|
+
*
|
|
4
|
+
* Reads base-committed record + preimage (never working-tree copies).
|
|
5
|
+
* Legacy records (no intentDigest) authorize paths only; intent edits warn.
|
|
6
|
+
* xbriefBodyDigest is never authority.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { join, resolve } from "node:path";
|
|
10
|
+
import { compareExtractedIntent } from "./compare-intent.js";
|
|
11
|
+
import { approvedScopeIntentRel } from "./digest.js";
|
|
12
|
+
import { extractIntentFromPayload, extractIntentFromRaw, } from "./extract-intent.js";
|
|
13
|
+
import { computeIntentDigest, INTENT_DIGEST_ALGO } from "./intent-digest.js";
|
|
14
|
+
import { parseJsonRejectingDuplicateKeys } from "./json-tokenizer.js";
|
|
15
|
+
export function parseIntentPreimageRaw(raw) {
|
|
16
|
+
try {
|
|
17
|
+
const data = JSON.parse(raw);
|
|
18
|
+
if (data === null || typeof data !== "object" || Array.isArray(data))
|
|
19
|
+
return null;
|
|
20
|
+
const rec = data;
|
|
21
|
+
if (rec.schemaVersion !== 1)
|
|
22
|
+
return null;
|
|
23
|
+
if (rec.algo !== INTENT_DIGEST_ALGO)
|
|
24
|
+
return null;
|
|
25
|
+
if (rec.plan === null || typeof rec.plan !== "object" || Array.isArray(rec.plan))
|
|
26
|
+
return null;
|
|
27
|
+
if (!Array.isArray(rec.approvedRepos))
|
|
28
|
+
return null;
|
|
29
|
+
return data;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function remint() {
|
|
36
|
+
return ("Remint via `task scope:record-approved-scope -- <xbrief-path> --actor <you> --confirm` " +
|
|
37
|
+
"and commit `.deft/approved-scope/<plan-id>.json` plus `.intent.json` on the merge base. " +
|
|
38
|
+
"Read the preimage before committing (#3385).");
|
|
39
|
+
}
|
|
40
|
+
function mapCompare(f) {
|
|
41
|
+
if (f.kind === "unclassified-key")
|
|
42
|
+
return "unclassified-key";
|
|
43
|
+
return "intent-drift";
|
|
44
|
+
}
|
|
45
|
+
function finding(input, kind, detail, warnOnly = false) {
|
|
46
|
+
return {
|
|
47
|
+
kind,
|
|
48
|
+
planId: input.planId,
|
|
49
|
+
xbriefRelPath: input.xbriefRelPath,
|
|
50
|
+
detail,
|
|
51
|
+
remediation: remint(),
|
|
52
|
+
warnOnly,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function readBase(input, rel) {
|
|
56
|
+
if (input.readAtBase !== undefined)
|
|
57
|
+
return input.readAtBase(rel);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
function decisionExists(input, rel) {
|
|
61
|
+
const fromBase = readBase(input, rel);
|
|
62
|
+
if (fromBase !== null)
|
|
63
|
+
return true;
|
|
64
|
+
const full = join(resolve(input.projectRoot), ...rel.split("/"));
|
|
65
|
+
return existsSync(full);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Evaluate intent pin for one modified active xBRIEF.
|
|
69
|
+
* Returns [] when intent is not in play (unmodified, or nothing to check).
|
|
70
|
+
*/
|
|
71
|
+
export function evaluateIntentForXbrief(input) {
|
|
72
|
+
if (!input.xbriefModified)
|
|
73
|
+
return [];
|
|
74
|
+
const parsed = parseJsonRejectingDuplicateKeys(input.liveRaw);
|
|
75
|
+
if (!parsed.ok) {
|
|
76
|
+
return [finding(input, "duplicate-key", parsed.error)];
|
|
77
|
+
}
|
|
78
|
+
const liveExtract = extractIntentFromPayload(parsed.value, {
|
|
79
|
+
projectRoot: input.projectRoot,
|
|
80
|
+
approvedReposSeed: input.approvedReposSeed,
|
|
81
|
+
});
|
|
82
|
+
if (!liveExtract.ok) {
|
|
83
|
+
if (liveExtract.error.includes("duplicate items[].id")) {
|
|
84
|
+
return [finding(input, "duplicate-item-id", liveExtract.error)];
|
|
85
|
+
}
|
|
86
|
+
return [finding(input, "intent-parse-error", liveExtract.error)];
|
|
87
|
+
}
|
|
88
|
+
if (input.approvalRewritten || input.preimageRewritten) {
|
|
89
|
+
return [
|
|
90
|
+
finding(input, "same-pr-intent-rewrite", "approved-scope record or preimage rewritten in the same change set; " +
|
|
91
|
+
"cannot self-authorize intent"),
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
const hasIntent = input.approved !== null &&
|
|
95
|
+
typeof input.approved.intentDigest === "string" &&
|
|
96
|
+
input.approved.intentDigest.length > 0;
|
|
97
|
+
if (!hasIntent) {
|
|
98
|
+
return evaluateLegacyIntent(input, liveExtract.preimage);
|
|
99
|
+
}
|
|
100
|
+
const preimageRel = approvedScopeIntentRel(input.planId);
|
|
101
|
+
const basePreimageRaw = readBase(input, preimageRel);
|
|
102
|
+
if (basePreimageRaw === null) {
|
|
103
|
+
if (input.currentScopeNonEmpty) {
|
|
104
|
+
return [
|
|
105
|
+
finding(input, "first-activation-missing-intent-pin", "first activation with nonempty scope requires a base-committed record + preimage"),
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
const basePreimage = parseIntentPreimageRaw(basePreimageRaw);
|
|
111
|
+
if (basePreimage === null) {
|
|
112
|
+
return [finding(input, "intent-digest-mismatch", "base preimage is malformed")];
|
|
113
|
+
}
|
|
114
|
+
const expected = computeIntentDigest(basePreimage);
|
|
115
|
+
if (expected !== input.approved?.intentDigest) {
|
|
116
|
+
return [
|
|
117
|
+
finding(input, "intent-digest-mismatch", "base preimage digest does not match record intentDigest"),
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
const compared = compareExtractedIntent(basePreimage, liveExtract.preimage, {
|
|
121
|
+
changedFiles: input.changedFiles,
|
|
122
|
+
decisionExists: (rel) => decisionExists(input, rel),
|
|
123
|
+
});
|
|
124
|
+
return compared.findings.map((f) => finding(input, mapCompare(f), f.detail));
|
|
125
|
+
}
|
|
126
|
+
function evaluateLegacyIntent(input, live) {
|
|
127
|
+
const baseRaw = readBase(input, input.xbriefRelPath);
|
|
128
|
+
if (baseRaw === null) {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
const baseExtract = extractIntentFromRaw(baseRaw, {
|
|
132
|
+
projectRoot: input.projectRoot,
|
|
133
|
+
approvedReposSeed: input.approvedReposSeed,
|
|
134
|
+
});
|
|
135
|
+
if (!baseExtract.ok)
|
|
136
|
+
return [];
|
|
137
|
+
const compared = compareExtractedIntent(baseExtract.preimage, live, {
|
|
138
|
+
changedFiles: input.changedFiles,
|
|
139
|
+
decisionExists: (rel) => decisionExists(input, rel),
|
|
140
|
+
});
|
|
141
|
+
if (compared.ok)
|
|
142
|
+
return [];
|
|
143
|
+
return compared.findings.map((f) => finding(input, "legacy-intent-edit", f.detail, true));
|
|
144
|
+
}
|
|
145
|
+
/** Explicit: never treat xbriefBodyDigest as authority. */
|
|
146
|
+
export function bodyDigestIsAuthority(_rec) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=intent-evaluate.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validating JSON tokenizer for scope-provenance intent parse (#3385 F3 / E9).
|
|
3
|
+
*
|
|
4
|
+
* JSON.parse collapses duplicate object keys; a reviver never sees them.
|
|
5
|
+
* This scanner rejects duplicate keys (including nested) and does not treat
|
|
6
|
+
* JSON-looking text inside string values as structure.
|
|
7
|
+
*/
|
|
8
|
+
export interface JsonParseOk {
|
|
9
|
+
readonly ok: true;
|
|
10
|
+
readonly value: unknown;
|
|
11
|
+
}
|
|
12
|
+
export interface JsonParseErr {
|
|
13
|
+
readonly ok: false;
|
|
14
|
+
readonly error: string;
|
|
15
|
+
}
|
|
16
|
+
export type JsonParseResult = JsonParseOk | JsonParseErr;
|
|
17
|
+
/** Parse JSON and reject duplicate object keys (nested included). */
|
|
18
|
+
export declare function parseJsonRejectingDuplicateKeys(text: string): JsonParseResult;
|
|
19
|
+
//# sourceMappingURL=json-tokenizer.d.ts.map
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validating JSON tokenizer for scope-provenance intent parse (#3385 F3 / E9).
|
|
3
|
+
*
|
|
4
|
+
* JSON.parse collapses duplicate object keys; a reviver never sees them.
|
|
5
|
+
* This scanner rejects duplicate keys (including nested) and does not treat
|
|
6
|
+
* JSON-looking text inside string values as structure.
|
|
7
|
+
*/
|
|
8
|
+
class Scanner {
|
|
9
|
+
s;
|
|
10
|
+
i = 0;
|
|
11
|
+
constructor(s) {
|
|
12
|
+
this.s = s;
|
|
13
|
+
}
|
|
14
|
+
parseDocument() {
|
|
15
|
+
this.skipWs();
|
|
16
|
+
const value = this.parseValue();
|
|
17
|
+
this.skipWs();
|
|
18
|
+
if (this.i < this.s.length) {
|
|
19
|
+
throw new Error(`trailing content at ${this.i}`);
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
peek() {
|
|
24
|
+
return this.s[this.i] ?? "";
|
|
25
|
+
}
|
|
26
|
+
next() {
|
|
27
|
+
const ch = this.s[this.i] ?? "";
|
|
28
|
+
this.i += 1;
|
|
29
|
+
return ch;
|
|
30
|
+
}
|
|
31
|
+
skipWs() {
|
|
32
|
+
while (this.i < this.s.length) {
|
|
33
|
+
const c = this.s[this.i];
|
|
34
|
+
if (c === " " || c === "\t" || c === "\n" || c === "\r") {
|
|
35
|
+
this.i += 1;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
parseValue() {
|
|
42
|
+
this.skipWs();
|
|
43
|
+
const c = this.peek();
|
|
44
|
+
if (c === '"')
|
|
45
|
+
return this.parseString();
|
|
46
|
+
if (c === "{")
|
|
47
|
+
return this.parseObject();
|
|
48
|
+
if (c === "[")
|
|
49
|
+
return this.parseArray();
|
|
50
|
+
if (c === "t" || c === "f")
|
|
51
|
+
return this.parseLiteralBool();
|
|
52
|
+
if (c === "n")
|
|
53
|
+
return this.parseNull();
|
|
54
|
+
if (c === "-" || (c >= "0" && c <= "9"))
|
|
55
|
+
return this.parseNumber();
|
|
56
|
+
throw new Error(`unexpected token at ${this.i}`);
|
|
57
|
+
}
|
|
58
|
+
parseObject() {
|
|
59
|
+
this.next(); // {
|
|
60
|
+
this.skipWs();
|
|
61
|
+
const out = {};
|
|
62
|
+
const seen = new Set();
|
|
63
|
+
if (this.peek() === "}") {
|
|
64
|
+
this.next();
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
while (true) {
|
|
68
|
+
this.skipWs();
|
|
69
|
+
if (this.peek() !== '"') {
|
|
70
|
+
throw new Error(`expected object key at ${this.i}`);
|
|
71
|
+
}
|
|
72
|
+
const key = this.parseString();
|
|
73
|
+
if (seen.has(key)) {
|
|
74
|
+
throw new Error(`duplicate key ${JSON.stringify(key)}`);
|
|
75
|
+
}
|
|
76
|
+
seen.add(key);
|
|
77
|
+
this.skipWs();
|
|
78
|
+
if (this.next() !== ":") {
|
|
79
|
+
throw new Error(`expected ':' after key at ${this.i}`);
|
|
80
|
+
}
|
|
81
|
+
out[key] = this.parseValue();
|
|
82
|
+
this.skipWs();
|
|
83
|
+
const sep = this.next();
|
|
84
|
+
if (sep === "}")
|
|
85
|
+
return out;
|
|
86
|
+
if (sep !== ",") {
|
|
87
|
+
throw new Error(`expected ',' or '}' at ${this.i}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
parseArray() {
|
|
92
|
+
this.next(); // [
|
|
93
|
+
this.skipWs();
|
|
94
|
+
const out = [];
|
|
95
|
+
if (this.peek() === "]") {
|
|
96
|
+
this.next();
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
while (true) {
|
|
100
|
+
out.push(this.parseValue());
|
|
101
|
+
this.skipWs();
|
|
102
|
+
const sep = this.next();
|
|
103
|
+
if (sep === "]")
|
|
104
|
+
return out;
|
|
105
|
+
if (sep !== ",") {
|
|
106
|
+
throw new Error(`expected ',' or ']' at ${this.i}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
parseString() {
|
|
111
|
+
this.next(); // "
|
|
112
|
+
let out = "";
|
|
113
|
+
while (this.i < this.s.length) {
|
|
114
|
+
const c = this.next();
|
|
115
|
+
if (c === '"')
|
|
116
|
+
return out;
|
|
117
|
+
if (c === "\\") {
|
|
118
|
+
out += this.parseEscape();
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (c.charCodeAt(0) < 0x20) {
|
|
122
|
+
throw new Error(`unescaped control in string at ${this.i}`);
|
|
123
|
+
}
|
|
124
|
+
out += c;
|
|
125
|
+
}
|
|
126
|
+
throw new Error("unterminated string");
|
|
127
|
+
}
|
|
128
|
+
parseEscape() {
|
|
129
|
+
const c = this.next();
|
|
130
|
+
switch (c) {
|
|
131
|
+
case '"':
|
|
132
|
+
case "\\":
|
|
133
|
+
case "/":
|
|
134
|
+
return c;
|
|
135
|
+
case "b":
|
|
136
|
+
return "\b";
|
|
137
|
+
case "f":
|
|
138
|
+
return "\f";
|
|
139
|
+
case "n":
|
|
140
|
+
return "\n";
|
|
141
|
+
case "r":
|
|
142
|
+
return "\r";
|
|
143
|
+
case "t":
|
|
144
|
+
return "\t";
|
|
145
|
+
case "u": {
|
|
146
|
+
const hex = this.s.slice(this.i, this.i + 4);
|
|
147
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex)) {
|
|
148
|
+
throw new Error(`invalid unicode escape at ${this.i}`);
|
|
149
|
+
}
|
|
150
|
+
this.i += 4;
|
|
151
|
+
return String.fromCharCode(parseInt(hex, 16));
|
|
152
|
+
}
|
|
153
|
+
default:
|
|
154
|
+
throw new Error(`invalid escape at ${this.i}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
parseNumber() {
|
|
158
|
+
const start = this.i;
|
|
159
|
+
if (this.peek() === "-")
|
|
160
|
+
this.next();
|
|
161
|
+
if (this.peek() === "0") {
|
|
162
|
+
this.next();
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
if (this.peek() < "1" || this.peek() > "9") {
|
|
166
|
+
throw new Error(`invalid number at ${start}`);
|
|
167
|
+
}
|
|
168
|
+
while (this.peek() >= "0" && this.peek() <= "9")
|
|
169
|
+
this.next();
|
|
170
|
+
}
|
|
171
|
+
if (this.peek() === ".") {
|
|
172
|
+
this.next();
|
|
173
|
+
if (this.peek() < "0" || this.peek() > "9") {
|
|
174
|
+
throw new Error(`invalid fraction at ${this.i}`);
|
|
175
|
+
}
|
|
176
|
+
while (this.peek() >= "0" && this.peek() <= "9")
|
|
177
|
+
this.next();
|
|
178
|
+
}
|
|
179
|
+
if (this.peek() === "e" || this.peek() === "E") {
|
|
180
|
+
this.next();
|
|
181
|
+
if (this.peek() === "+" || this.peek() === "-")
|
|
182
|
+
this.next();
|
|
183
|
+
if (this.peek() < "0" || this.peek() > "9") {
|
|
184
|
+
throw new Error(`invalid exponent at ${this.i}`);
|
|
185
|
+
}
|
|
186
|
+
while (this.peek() >= "0" && this.peek() <= "9")
|
|
187
|
+
this.next();
|
|
188
|
+
}
|
|
189
|
+
const n = Number(this.s.slice(start, this.i));
|
|
190
|
+
if (!Number.isFinite(n)) {
|
|
191
|
+
throw new Error(`invalid number at ${start}`);
|
|
192
|
+
}
|
|
193
|
+
return n;
|
|
194
|
+
}
|
|
195
|
+
parseLiteralBool() {
|
|
196
|
+
if (this.s.startsWith("true", this.i)) {
|
|
197
|
+
this.i += 4;
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
if (this.s.startsWith("false", this.i)) {
|
|
201
|
+
this.i += 5;
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
throw new Error(`invalid literal at ${this.i}`);
|
|
205
|
+
}
|
|
206
|
+
parseNull() {
|
|
207
|
+
if (this.s.startsWith("null", this.i)) {
|
|
208
|
+
this.i += 4;
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
throw new Error(`invalid literal at ${this.i}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/** Parse JSON and reject duplicate object keys (nested included). */
|
|
215
|
+
export function parseJsonRejectingDuplicateKeys(text) {
|
|
216
|
+
try {
|
|
217
|
+
const value = new Scanner(text).parseDocument();
|
|
218
|
+
return { ok: true, value };
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
222
|
+
return { ok: false, error: msg };
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=json-tokenizer.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Known-machine vs extracted classification for plan.* (#3376 R1 / #3385 F1).
|
|
3
|
+
*
|
|
4
|
+
* Seeded from the #3376 corpus inventory (capacity stamps, completion
|
|
5
|
+
* provenance, swarm readiness, tags-as-label-mirror). Growing this list MUST
|
|
6
|
+
* land with a writer annotation in KNOWN_MACHINE_WRITERS (same-PR CI rule)
|
|
7
|
+
* and MUST NOT change existing intent digests.
|
|
8
|
+
*/
|
|
9
|
+
export type KeyClass = "extract" | "extract-partial" | "machine" | "unknown";
|
|
10
|
+
/** Recursive walk nodes (not pinned wholesale). */
|
|
11
|
+
export declare const PARTIAL_NODES: Set<string>;
|
|
12
|
+
/** plan.* keys that are machine space (never hash inputs). */
|
|
13
|
+
export declare const PLAN_MACHINE_KEYS: Set<string>;
|
|
14
|
+
/** plan.metadata.* machine keys / wholesale machine subtrees. */
|
|
15
|
+
export declare const METADATA_MACHINE_KEYS: Set<string>;
|
|
16
|
+
/** plan.metadata.swarm.* machine keys. */
|
|
17
|
+
export declare const SWARM_MACHINE_KEYS: Set<string>;
|
|
18
|
+
/** plan.items[] machine keys (raw planRef is machine; parentId is extracted). */
|
|
19
|
+
export declare const ITEM_MACHINE_KEYS: Set<string>;
|
|
20
|
+
/** reference fields that are never extracted. */
|
|
21
|
+
export declare const REFERENCE_MACHINE_KEYS: Set<string>;
|
|
22
|
+
/** Item fields copied into the preimage when present. */
|
|
23
|
+
export declare const ITEM_EXTRACT_KEYS: readonly ["id", "title", "summary", "narrative", "type"];
|
|
24
|
+
/** Swarm fields extracted as intent (prose + file_scope for review). */
|
|
25
|
+
export declare const SWARM_EXTRACT_KEYS: Set<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Writer annotation for each known-machine key. Adding a key without an entry
|
|
28
|
+
* fails the same-PR writer-discipline test (#3385 F1).
|
|
29
|
+
*/
|
|
30
|
+
export declare const KNOWN_MACHINE_WRITERS: Readonly<Record<string, {
|
|
31
|
+
writer: string;
|
|
32
|
+
}>>;
|
|
33
|
+
export declare function classifyPlanPath(path: string): KeyClass;
|
|
34
|
+
export declare function classifyItemKey(key: string): KeyClass;
|
|
35
|
+
export declare function classifyReferenceKey(key: string): KeyClass;
|
|
36
|
+
/** Every known-machine leaf that the writer-discipline test enumerates. */
|
|
37
|
+
export declare function allKnownMachineLeaves(): string[];
|
|
38
|
+
//# sourceMappingURL=known-machine.d.ts.map
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Known-machine vs extracted classification for plan.* (#3376 R1 / #3385 F1).
|
|
3
|
+
*
|
|
4
|
+
* Seeded from the #3376 corpus inventory (capacity stamps, completion
|
|
5
|
+
* provenance, swarm readiness, tags-as-label-mirror). Growing this list MUST
|
|
6
|
+
* land with a writer annotation in KNOWN_MACHINE_WRITERS (same-PR CI rule)
|
|
7
|
+
* and MUST NOT change existing intent digests.
|
|
8
|
+
*/
|
|
9
|
+
/** Recursive walk nodes (not pinned wholesale). */
|
|
10
|
+
export const PARTIAL_NODES = new Set(["", "metadata", "metadata.swarm"]);
|
|
11
|
+
/** plan.* keys that are machine space (never hash inputs). */
|
|
12
|
+
export const PLAN_MACHINE_KEYS = new Set([
|
|
13
|
+
"status",
|
|
14
|
+
"updated",
|
|
15
|
+
"created",
|
|
16
|
+
"createdAt",
|
|
17
|
+
"updatedAt",
|
|
18
|
+
"completed",
|
|
19
|
+
"percentComplete",
|
|
20
|
+
"tags",
|
|
21
|
+
"planRef",
|
|
22
|
+
"plan_ref",
|
|
23
|
+
]);
|
|
24
|
+
/** plan.metadata.* machine keys / wholesale machine subtrees. */
|
|
25
|
+
export const METADATA_MACHINE_KEYS = new Set([
|
|
26
|
+
"capacityBucket",
|
|
27
|
+
"capacityBucketSource",
|
|
28
|
+
"completionProvenance",
|
|
29
|
+
"deliveryDisposition",
|
|
30
|
+
"handoffState",
|
|
31
|
+
"parent_lineage",
|
|
32
|
+
"parentLineage",
|
|
33
|
+
"x-migrator",
|
|
34
|
+
]);
|
|
35
|
+
/** plan.metadata.swarm.* machine keys. */
|
|
36
|
+
export const SWARM_MACHINE_KEYS = new Set([
|
|
37
|
+
"readiness",
|
|
38
|
+
"parallel_safe",
|
|
39
|
+
"verify_commands",
|
|
40
|
+
"expected_outputs",
|
|
41
|
+
"depends_on",
|
|
42
|
+
"conflict_group",
|
|
43
|
+
"size",
|
|
44
|
+
"file_scope_confidence",
|
|
45
|
+
"model_tier",
|
|
46
|
+
]);
|
|
47
|
+
/** plan.items[] machine keys (raw planRef is machine; parentId is extracted). */
|
|
48
|
+
export const ITEM_MACHINE_KEYS = new Set([
|
|
49
|
+
"status",
|
|
50
|
+
"completed",
|
|
51
|
+
"percentComplete",
|
|
52
|
+
"effort",
|
|
53
|
+
"updated",
|
|
54
|
+
"created",
|
|
55
|
+
"planRef",
|
|
56
|
+
"plan_ref",
|
|
57
|
+
]);
|
|
58
|
+
/** reference fields that are never extracted. */
|
|
59
|
+
export const REFERENCE_MACHINE_KEYS = new Set(["TrustLevel", "trustLevel"]);
|
|
60
|
+
/** Item fields copied into the preimage when present. */
|
|
61
|
+
export const ITEM_EXTRACT_KEYS = ["id", "title", "summary", "narrative", "type"];
|
|
62
|
+
/** Swarm fields extracted as intent (prose + file_scope for review). */
|
|
63
|
+
export const SWARM_EXTRACT_KEYS = new Set([
|
|
64
|
+
"file_scope",
|
|
65
|
+
"missing_traces_justification",
|
|
66
|
+
"acceptance_criteria_justification",
|
|
67
|
+
"notes",
|
|
68
|
+
]);
|
|
69
|
+
/**
|
|
70
|
+
* Writer annotation for each known-machine key. Adding a key without an entry
|
|
71
|
+
* fails the same-PR writer-discipline test (#3385 F1).
|
|
72
|
+
*/
|
|
73
|
+
export const KNOWN_MACHINE_WRITERS = {
|
|
74
|
+
"plan.status": { writer: "packages/core/src/scope/transition.ts" },
|
|
75
|
+
"plan.updated": { writer: "packages/core/src/scope/transition.ts" },
|
|
76
|
+
"plan.created": { writer: "packages/core/src/scope/transition.ts" },
|
|
77
|
+
"plan.createdAt": { writer: "packages/core/src/scope/transition.ts" },
|
|
78
|
+
"plan.updatedAt": { writer: "packages/core/src/scope/transition.ts" },
|
|
79
|
+
"plan.completed": { writer: "packages/core/src/scope/transition.ts" },
|
|
80
|
+
"plan.percentComplete": { writer: "packages/core/src/scope/transition.ts" },
|
|
81
|
+
"plan.tags": { writer: "packages/core/src/intake/issue-ingest.ts" },
|
|
82
|
+
"plan.planRef": { writer: "packages/core/src/scope/decomposed-refs.ts" },
|
|
83
|
+
"plan.plan_ref": { writer: "packages/core/src/scope/decomposed-refs.ts" },
|
|
84
|
+
"plan.metadata.capacityBucket": { writer: "packages/core/src/scope/capacity-stamp.ts" },
|
|
85
|
+
"plan.metadata.capacityBucketSource": { writer: "packages/core/src/scope/capacity-stamp.ts" },
|
|
86
|
+
"plan.metadata.completionProvenance": { writer: "packages/core/src/scope/delivery-evidence.ts" },
|
|
87
|
+
"plan.metadata.deliveryDisposition": { writer: "packages/core/src/scope/delivery-evidence.ts" },
|
|
88
|
+
"plan.metadata.handoffState": { writer: "packages/core/src/scope/delivery-evidence.ts" },
|
|
89
|
+
"plan.metadata.parent_lineage": { writer: "packages/core/src/scope/parent-lineage.ts" },
|
|
90
|
+
"plan.metadata.parentLineage": { writer: "packages/core/src/scope/parent-lineage.ts" },
|
|
91
|
+
"plan.metadata.x-migrator": { writer: "packages/core/src/xbrief-migrate" },
|
|
92
|
+
"plan.metadata.swarm.readiness": { writer: "packages/core/src/swarm/complete-cohort.ts" },
|
|
93
|
+
"plan.metadata.swarm.parallel_safe": { writer: "packages/core/src/swarm/complete-cohort.ts" },
|
|
94
|
+
"plan.metadata.swarm.verify_commands": { writer: "packages/core/src/swarm/launch.ts" },
|
|
95
|
+
"plan.metadata.swarm.expected_outputs": { writer: "packages/core/src/swarm/launch.ts" },
|
|
96
|
+
"plan.metadata.swarm.depends_on": { writer: "packages/core/src/swarm/launch.ts" },
|
|
97
|
+
"plan.metadata.swarm.conflict_group": { writer: "packages/core/src/swarm/launch.ts" },
|
|
98
|
+
"plan.metadata.swarm.size": { writer: "packages/core/src/swarm/launch.ts" },
|
|
99
|
+
"plan.metadata.swarm.file_scope_confidence": { writer: "packages/core/src/swarm/launch.ts" },
|
|
100
|
+
"plan.metadata.swarm.model_tier": { writer: "packages/core/src/swarm/launch.ts" },
|
|
101
|
+
"plan.items[].status": { writer: "packages/core/src/scope/transition.ts" },
|
|
102
|
+
"plan.items[].completed": { writer: "packages/core/src/scope/transition.ts" },
|
|
103
|
+
"plan.items[].percentComplete": { writer: "packages/core/src/scope/transition.ts" },
|
|
104
|
+
"plan.items[].effort": { writer: "packages/core/src/scope/transition.ts" },
|
|
105
|
+
"plan.items[].updated": { writer: "packages/core/src/scope/transition.ts" },
|
|
106
|
+
"plan.items[].created": { writer: "packages/core/src/scope/transition.ts" },
|
|
107
|
+
"plan.items[].planRef": { writer: "packages/core/src/scope/decomposed-refs.ts" },
|
|
108
|
+
"plan.items[].plan_ref": { writer: "packages/core/src/scope/decomposed-refs.ts" },
|
|
109
|
+
"plan.references[].TrustLevel": { writer: "packages/core/src/intake/issue-ingest.ts" },
|
|
110
|
+
"plan.references[].trustLevel": { writer: "packages/core/src/intake/issue-ingest.ts" },
|
|
111
|
+
};
|
|
112
|
+
export function classifyPlanPath(path) {
|
|
113
|
+
if (PARTIAL_NODES.has(path))
|
|
114
|
+
return "extract-partial";
|
|
115
|
+
if (path === "items" ||
|
|
116
|
+
path === "references" ||
|
|
117
|
+
path === "metadata" ||
|
|
118
|
+
path === "metadata.swarm") {
|
|
119
|
+
return "extract-partial";
|
|
120
|
+
}
|
|
121
|
+
if (PLAN_MACHINE_KEYS.has(path))
|
|
122
|
+
return "machine";
|
|
123
|
+
if (path.startsWith("metadata.") && METADATA_MACHINE_KEYS.has(path.slice("metadata.".length))) {
|
|
124
|
+
return "machine";
|
|
125
|
+
}
|
|
126
|
+
if (path.startsWith("metadata.swarm.")) {
|
|
127
|
+
const leaf = path.slice("metadata.swarm.".length);
|
|
128
|
+
if (SWARM_MACHINE_KEYS.has(leaf))
|
|
129
|
+
return "machine";
|
|
130
|
+
if (SWARM_EXTRACT_KEYS.has(leaf))
|
|
131
|
+
return "extract";
|
|
132
|
+
return "unknown";
|
|
133
|
+
}
|
|
134
|
+
if (path === "edges" || path === "title" || path === "narratives" || path === "acceptance") {
|
|
135
|
+
return "extract";
|
|
136
|
+
}
|
|
137
|
+
if (path === "architecture" || path === "id")
|
|
138
|
+
return "extract";
|
|
139
|
+
return "unknown";
|
|
140
|
+
}
|
|
141
|
+
export function classifyItemKey(key) {
|
|
142
|
+
if (ITEM_MACHINE_KEYS.has(key))
|
|
143
|
+
return "machine";
|
|
144
|
+
if (ITEM_EXTRACT_KEYS.includes(key))
|
|
145
|
+
return "extract";
|
|
146
|
+
return "unknown";
|
|
147
|
+
}
|
|
148
|
+
export function classifyReferenceKey(key) {
|
|
149
|
+
if (REFERENCE_MACHINE_KEYS.has(key))
|
|
150
|
+
return "machine";
|
|
151
|
+
return "extract";
|
|
152
|
+
}
|
|
153
|
+
/** Every known-machine leaf that the writer-discipline test enumerates. */
|
|
154
|
+
export function allKnownMachineLeaves() {
|
|
155
|
+
return Object.keys(KNOWN_MACHINE_WRITERS).sort((a, b) => a.localeCompare(b));
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=known-machine.js.map
|