@momentiq/dark-factory-cli 2.13.1 → 2.14.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/cli.d.ts.map +1 -1
- package/dist/cli.js +52 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/objectives.d.ts +48 -0
- package/dist/commands/objectives.d.ts.map +1 -0
- package/dist/commands/objectives.js +545 -0
- package/dist/commands/objectives.js.map +1 -0
- package/dist/cycle-doc-validator/validate_cycle_doc.py +29 -1
- package/dist/evidence/prove.d.ts.map +1 -1
- package/dist/evidence/prove.js +3 -1
- package/dist/evidence/prove.js.map +1 -1
- package/dist/handoff/handoff-verb.d.ts.map +1 -1
- package/dist/handoff/handoff-verb.js +6 -1
- package/dist/handoff/handoff-verb.js.map +1 -1
- package/dist/handoff/links.d.ts +13 -2
- package/dist/handoff/links.d.ts.map +1 -1
- package/dist/handoff/links.js +98 -7
- package/dist/handoff/links.js.map +1 -1
- package/dist/skills/install.d.ts.map +1 -1
- package/dist/skills/install.js +1 -0
- package/dist/skills/install.js.map +1 -1
- package/dist/worktree-safety.d.ts +41 -0
- package/dist/worktree-safety.d.ts.map +1 -0
- package/dist/worktree-safety.js +105 -0
- package/dist/worktree-safety.js.map +1 -0
- package/package.json +2 -2
- package/skills/objectives/SKILL.md.tmpl +220 -0
- package/skills/objectives/skill.json +17 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
// `df objectives` — Objectives authoring commands for verifiable-objectives
|
|
2
|
+
// (momentiq-ai/dark-factory#207, objectives Phase 1).
|
|
3
|
+
//
|
|
4
|
+
// Subcommands:
|
|
5
|
+
// hash — print the canonical sha256 of a criterion text (for manifest authoring)
|
|
6
|
+
// derive — generate a .darkfactory/objectives.yaml from cycle-doc exit criteria (Task 5)
|
|
7
|
+
// check — verify text-hash bindings in an existing manifest (Task 6)
|
|
8
|
+
//
|
|
9
|
+
// Exit codes: 0 success / 1 semantic failure / 2 usage error.
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { dirname, join, resolve } from "node:path";
|
|
13
|
+
import { canonicalizeCriterion, parseObjectivesManifest, SOURCE_LOCATOR_RE, } from "@momentiq/dark-factory-schemas";
|
|
14
|
+
import { parse as yamlParse, stringify as yamlStringify } from "yaml";
|
|
15
|
+
import { readCycleDoc } from "../mcp/cycle-doc/parser.js";
|
|
16
|
+
export function parseObjectivesArgs(rest) {
|
|
17
|
+
const sub = rest[0];
|
|
18
|
+
const subRest = rest.slice(1);
|
|
19
|
+
if (sub === undefined || sub === "") {
|
|
20
|
+
return { subcommand: undefined };
|
|
21
|
+
}
|
|
22
|
+
if (sub === "hash") {
|
|
23
|
+
return parseHashArgs(subRest);
|
|
24
|
+
}
|
|
25
|
+
if (sub === "derive") {
|
|
26
|
+
return parseDeriveArgs(subRest);
|
|
27
|
+
}
|
|
28
|
+
if (sub === "check") {
|
|
29
|
+
return parseCheckArgs(subRest);
|
|
30
|
+
}
|
|
31
|
+
return { error: `unknown subcommand: ${sub}` };
|
|
32
|
+
}
|
|
33
|
+
function parseHashArgs(rest) {
|
|
34
|
+
let text;
|
|
35
|
+
for (let i = 0; i < rest.length; i++) {
|
|
36
|
+
const a = rest[i] ?? "";
|
|
37
|
+
if (a === "--text") {
|
|
38
|
+
const next = rest[i + 1];
|
|
39
|
+
if (next === undefined || next.startsWith("--")) {
|
|
40
|
+
return { error: "--text requires a value." };
|
|
41
|
+
}
|
|
42
|
+
text = next;
|
|
43
|
+
i++;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (a.startsWith("--text=")) {
|
|
47
|
+
text = a.slice("--text=".length);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
// Flags that are not yet implemented
|
|
51
|
+
if (a === "--locator" || a === "--cycle") {
|
|
52
|
+
return {
|
|
53
|
+
error: `${a} is not yet implemented — use --text "<criterion>" to hash a criterion directly.`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (a.startsWith("--locator=") || a.startsWith("--cycle=")) {
|
|
57
|
+
const flag = a.startsWith("--locator=") ? "--locator" : "--cycle";
|
|
58
|
+
return {
|
|
59
|
+
error: `${flag} is not yet implemented — use --text "<criterion>" to hash a criterion directly.`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return { error: `unknown flag or positional arg: ${a}` };
|
|
63
|
+
}
|
|
64
|
+
if (text === undefined) {
|
|
65
|
+
return { error: "--text is required (e.g. --text \"- **EC1**: Criterion text\")." };
|
|
66
|
+
}
|
|
67
|
+
return { subcommand: "hash", text };
|
|
68
|
+
}
|
|
69
|
+
function parseDeriveArgs(rest) {
|
|
70
|
+
let cycle;
|
|
71
|
+
let apply = false;
|
|
72
|
+
let json = false;
|
|
73
|
+
let cwd = process.cwd();
|
|
74
|
+
for (let i = 0; i < rest.length; i++) {
|
|
75
|
+
const a = rest[i] ?? "";
|
|
76
|
+
if (a === "--cycle") {
|
|
77
|
+
const next = rest[i + 1];
|
|
78
|
+
if (next === undefined || next.startsWith("--")) {
|
|
79
|
+
return { error: "--cycle requires a value (e.g. --cycle 23)." };
|
|
80
|
+
}
|
|
81
|
+
cycle = next;
|
|
82
|
+
i++;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (a.startsWith("--cycle=")) {
|
|
86
|
+
cycle = a.slice("--cycle=".length);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (a === "--cwd") {
|
|
90
|
+
const next = rest[i + 1];
|
|
91
|
+
if (next === undefined || next.startsWith("--")) {
|
|
92
|
+
return { error: "--cwd requires a value." };
|
|
93
|
+
}
|
|
94
|
+
cwd = next;
|
|
95
|
+
i++;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (a.startsWith("--cwd=")) {
|
|
99
|
+
cwd = a.slice("--cwd=".length);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (a === "--apply") {
|
|
103
|
+
apply = true;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (a === "--json") {
|
|
107
|
+
json = true;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
return { error: `unknown flag or positional arg: ${a}` };
|
|
111
|
+
}
|
|
112
|
+
if (cycle === undefined || cycle === "") {
|
|
113
|
+
return { error: "--cycle is required (e.g. --cycle 23)." };
|
|
114
|
+
}
|
|
115
|
+
// Normalize a `cycle23` / `cycle 23` style value down to the bare number the
|
|
116
|
+
// id + source.ref use (`cycle<N>#ec<k>`, `{kind:"cycle", ref:"<N>"}`). The
|
|
117
|
+
// cycle-doc parser keys on the `cycle<N>` id form, so we rebuild that below.
|
|
118
|
+
const ref = cycle.replace(/^cycle/i, "").trim();
|
|
119
|
+
if (ref === "" || !/^\d+(?:\.\d+)*$/.test(ref)) {
|
|
120
|
+
return { error: `--cycle must be a cycle number (e.g. 23 or cycle23), got ${JSON.stringify(cycle)}.` };
|
|
121
|
+
}
|
|
122
|
+
return { subcommand: "derive", cycle: ref, apply, json, cwd };
|
|
123
|
+
}
|
|
124
|
+
function parseCheckArgs(rest) {
|
|
125
|
+
let json = false;
|
|
126
|
+
let cwd = process.cwd();
|
|
127
|
+
for (let i = 0; i < rest.length; i++) {
|
|
128
|
+
const a = rest[i] ?? "";
|
|
129
|
+
if (a === "--cwd") {
|
|
130
|
+
const next = rest[i + 1];
|
|
131
|
+
if (next === undefined || next.startsWith("--")) {
|
|
132
|
+
return { error: "--cwd requires a value." };
|
|
133
|
+
}
|
|
134
|
+
cwd = next;
|
|
135
|
+
i++;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (a.startsWith("--cwd=")) {
|
|
139
|
+
cwd = a.slice("--cwd=".length);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (a === "--json") {
|
|
143
|
+
json = true;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
return { error: `unknown flag or positional arg: ${a}` };
|
|
147
|
+
}
|
|
148
|
+
return { subcommand: "check", json, cwd };
|
|
149
|
+
}
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// Exit-criteria extraction — the hash-consistency core.
|
|
152
|
+
//
|
|
153
|
+
// This MUST enumerate list items and assign criterion ids IDENTICALLY to the
|
|
154
|
+
// Python gate validator's resolver (`validate_cycle_doc.py` `_list_items` +
|
|
155
|
+
// `_find_criterion`), or a derived manifest's text-hash sha256 will not match
|
|
156
|
+
// what the validator recomputes and every objective fails the gate.
|
|
157
|
+
//
|
|
158
|
+
// - Item enumeration mirrors `_list_items`: a line is an item iff it matches
|
|
159
|
+
// `^\s*(?:[-*+]|\d+[.)])\s+` (dash/star/plus or `N.`/`N)` markers).
|
|
160
|
+
// - Id assignment mirrors `_find_criterion`'s resolution, inverted: the
|
|
161
|
+
// validator resolves `ec<k>` by (1) an explicit `EC<k>` label match, else
|
|
162
|
+
// (2) positional (`ec<N>` → Nth item). So we read each item's OWN `EC<k>`
|
|
163
|
+
// label (the validator's label regex, constrained to the `EC<digits>`
|
|
164
|
+
// exit-criterion convention so every id stays valid per OBJECTIVE_ID_RE);
|
|
165
|
+
// when no `EC<k>` label is present we fall back to positional `ec<index>`.
|
|
166
|
+
// Round-tripping is verified: `_find_criterion(section, <our id>)` returns
|
|
167
|
+
// the exact line we hashed, across in-order / out-of-order / mixed / plain
|
|
168
|
+
// / numbered docs (see the unit tests).
|
|
169
|
+
//
|
|
170
|
+
// The sha256 we emit is `sha256(canonicalizeCriterion(<raw item line>))` — the
|
|
171
|
+
// FULL raw line, exactly the `ctext` the validator feeds to
|
|
172
|
+
// `canonicalize_criterion`. `canonicalizeCriterion` (the shared schema mirror)
|
|
173
|
+
// strips the marker + label + emphasis itself, so feeding the raw line is what
|
|
174
|
+
// keeps the two sides byte-identical.
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// Mirror of the validator's `_list_items` item-detection regex.
|
|
177
|
+
const ITEM_RE = /^\s*(?:[-*+]|\d+[.)])\s+/;
|
|
178
|
+
// Mirror of the validator's `_find_criterion` label regex, constrained to the
|
|
179
|
+
// `EC<digits>` exit-criterion convention and capturing the number. Requires a
|
|
180
|
+
// trailing separator `[:.)–—-]` exactly like the validator (so a bare
|
|
181
|
+
// "`EC1` foo" with no separator correctly falls through to positional, matching
|
|
182
|
+
// the validator's resolution).
|
|
183
|
+
const EC_LABEL_RE = /^\s*(?:[-*+]|\d+[.)])\s*\*{0,2}EC(\d+)\*{0,2}\s*[:.)–—-]/i;
|
|
184
|
+
// Display-text derivation: strip the list marker, then a leading `EC<k>` token
|
|
185
|
+
// (bold/backtick-wrapped, with or without a separator), then residual emphasis,
|
|
186
|
+
// and fold whitespace. This is the human-facing `text` field only — it is NOT
|
|
187
|
+
// the hash input (the hash uses `canonicalizeCriterion(<raw line>)`), so its
|
|
188
|
+
// exact shape carries no cross-impl contract; it just reads cleanly.
|
|
189
|
+
function criterionDisplayText(rawLine) {
|
|
190
|
+
let s = rawLine.normalize("NFC");
|
|
191
|
+
s = s.replace(/^\s*(?:[-*+]|\d+[.)])\s+/, ""); // list marker
|
|
192
|
+
s = s.replace(/^\s*[`*]{0,2}EC\d+[`*]{0,2}\s*(?:[:.)–—-]\s+)?/i, ""); // EC<k> label token
|
|
193
|
+
s = s.replace(/[*`]/g, ""); // residual emphasis / code ticks
|
|
194
|
+
s = s.replace(/\s+/g, " ").trim();
|
|
195
|
+
return s;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Enumerate a `## Exit criteria` section body's items and assign each a
|
|
199
|
+
* validator-compatible criterion id. See the block comment above for the
|
|
200
|
+
* cross-impl-consistency contract this upholds.
|
|
201
|
+
*/
|
|
202
|
+
export function extractExitCriteria(sectionBody) {
|
|
203
|
+
const out = [];
|
|
204
|
+
const lines = sectionBody.split(/\r?\n/);
|
|
205
|
+
const items = lines.filter((ln) => ITEM_RE.test(ln));
|
|
206
|
+
for (let i = 0; i < items.length; i++) {
|
|
207
|
+
const raw = items[i] ?? "";
|
|
208
|
+
const labelMatch = EC_LABEL_RE.exec(raw);
|
|
209
|
+
const id = labelMatch ? `ec${parseInt(labelMatch[1] ?? "", 10)}` : `ec${i + 1}`;
|
|
210
|
+
out.push({ id, text: criterionDisplayText(raw), raw });
|
|
211
|
+
}
|
|
212
|
+
return out;
|
|
213
|
+
}
|
|
214
|
+
function sha256Hex(s) {
|
|
215
|
+
return createHash("sha256").update(s, "utf8").digest("hex");
|
|
216
|
+
}
|
|
217
|
+
const MANIFEST_RELATIVE_PATH = join(".darkfactory", "objectives.yaml");
|
|
218
|
+
const HELP = [
|
|
219
|
+
"df objectives — objectives authoring commands for verifiable-objectives.",
|
|
220
|
+
"",
|
|
221
|
+
"Usage:",
|
|
222
|
+
" df objectives <subcommand> [flags]",
|
|
223
|
+
"",
|
|
224
|
+
"Subcommands:",
|
|
225
|
+
" hash Print the canonical sha256 of a criterion text.",
|
|
226
|
+
" derive Generate .darkfactory/objectives.yaml from cycle-doc exit criteria.",
|
|
227
|
+
" check Verify text-hash bindings in an existing manifest.",
|
|
228
|
+
"",
|
|
229
|
+
"Flags (hash):",
|
|
230
|
+
" --text <criterion> Criterion text to hash (required).",
|
|
231
|
+
"",
|
|
232
|
+
"Flags (derive):",
|
|
233
|
+
" --cycle <N> Cycle number whose Exit criteria to derive from (required).",
|
|
234
|
+
" --apply Write .darkfactory/objectives.yaml (default: print to stdout).",
|
|
235
|
+
" --cwd <path> Repository root to operate in (default: process cwd).",
|
|
236
|
+
" --json Emit the manifest object as JSON instead of YAML.",
|
|
237
|
+
"",
|
|
238
|
+
"Flags (check):",
|
|
239
|
+
" --cwd <path> Repository root containing .darkfactory/objectives.yaml (default: process cwd).",
|
|
240
|
+
" --json Emit a structured JSON result.",
|
|
241
|
+
"",
|
|
242
|
+
" --help, -h Show this message.",
|
|
243
|
+
"",
|
|
244
|
+
"Exit codes:",
|
|
245
|
+
" 0 success",
|
|
246
|
+
" 1 semantic failure",
|
|
247
|
+
" 2 usage / flag error",
|
|
248
|
+
"",
|
|
249
|
+
].join("\n");
|
|
250
|
+
export async function cmdObjectives(rest, io, deps = {}) {
|
|
251
|
+
if (rest.includes("--help") || rest.includes("-h")) {
|
|
252
|
+
io.stdout(`${HELP}`);
|
|
253
|
+
return 0;
|
|
254
|
+
}
|
|
255
|
+
const parsed = parseObjectivesArgs(rest);
|
|
256
|
+
if ("error" in parsed) {
|
|
257
|
+
io.stderr(`df objectives: ${parsed.error}\nRun \`df objectives --help\` for usage.\n`);
|
|
258
|
+
return 2;
|
|
259
|
+
}
|
|
260
|
+
if (parsed.subcommand === undefined) {
|
|
261
|
+
io.stdout(`${HELP}`);
|
|
262
|
+
return 2;
|
|
263
|
+
}
|
|
264
|
+
if (parsed.subcommand === "hash") {
|
|
265
|
+
const digest = createHash("sha256").update(canonicalizeCriterion(parsed.text), "utf8").digest("hex");
|
|
266
|
+
io.stdout(digest + "\n");
|
|
267
|
+
return 0;
|
|
268
|
+
}
|
|
269
|
+
if (parsed.subcommand === "derive") {
|
|
270
|
+
return cmdDerive(parsed, io, deps);
|
|
271
|
+
}
|
|
272
|
+
if (parsed.subcommand === "check") {
|
|
273
|
+
return cmdCheck(parsed, io, deps);
|
|
274
|
+
}
|
|
275
|
+
// Should not reach here since parseObjectivesArgs handles unknown subcommands
|
|
276
|
+
io.stdout(`${HELP}`);
|
|
277
|
+
return 2;
|
|
278
|
+
}
|
|
279
|
+
async function cmdDerive(opts, io, deps) {
|
|
280
|
+
const read = deps.readCycleDoc ?? readCycleDoc;
|
|
281
|
+
const cycleDocId = `cycle${opts.cycle}`;
|
|
282
|
+
const doc = await read(opts.cwd, cycleDocId);
|
|
283
|
+
if (doc === null) {
|
|
284
|
+
io.stderr(`df objectives derive: cycle doc ${cycleDocId} not found under ` +
|
|
285
|
+
`${join(opts.cwd, "docs/roadmap/cycles")} — nothing to derive.\n`);
|
|
286
|
+
return 1;
|
|
287
|
+
}
|
|
288
|
+
const section = doc.sections["exit_criteria"];
|
|
289
|
+
if (section === undefined || section.trim() === "") {
|
|
290
|
+
io.stderr(`df objectives derive: cycle doc ${cycleDocId} has no '## Exit criteria' section ` +
|
|
291
|
+
"(or it is empty) — nothing to derive.\n");
|
|
292
|
+
return 1;
|
|
293
|
+
}
|
|
294
|
+
const criteria = extractExitCriteria(section);
|
|
295
|
+
if (criteria.length === 0) {
|
|
296
|
+
io.stderr(`df objectives derive: cycle doc ${cycleDocId} '## Exit criteria' section has no ` +
|
|
297
|
+
"list items — nothing to derive.\n");
|
|
298
|
+
return 1;
|
|
299
|
+
}
|
|
300
|
+
// Duplicate-id guard: a cycle doc with two identically-labeled EC items
|
|
301
|
+
// (e.g. two `**EC1**` entries) produces criteria with the same id. That is an
|
|
302
|
+
// authoring error in the cycle doc — duplicate objective ids make proof/evidence
|
|
303
|
+
// binding ambiguous and are REJECTED by `parseObjectivesManifest`. Fail here
|
|
304
|
+
// with a clear, actionable message rather than letting the self-validation
|
|
305
|
+
// round-trip below throw an opaque "internal error".
|
|
306
|
+
const seenIds = new Set();
|
|
307
|
+
const duplicateIds = new Set();
|
|
308
|
+
for (const c of criteria) {
|
|
309
|
+
const fullId = `${cycleDocId}#${c.id}`;
|
|
310
|
+
if (seenIds.has(fullId))
|
|
311
|
+
duplicateIds.add(fullId);
|
|
312
|
+
seenIds.add(fullId);
|
|
313
|
+
}
|
|
314
|
+
if (duplicateIds.size > 0) {
|
|
315
|
+
io.stderr(`df objectives derive: ${cycleDocId} exit criteria has duplicate criterion ` +
|
|
316
|
+
`id(s): ${[...duplicateIds].join(", ")}. Criterion labels (e.g. \`EC1\`) must be ` +
|
|
317
|
+
`unique — fix the cycle doc to use distinct labels, then re-run.\n`);
|
|
318
|
+
return 1;
|
|
319
|
+
}
|
|
320
|
+
// Idempotence: preserve hand-edited `attestedBy` bindings from an existing
|
|
321
|
+
// manifest by objective id. Re-running refreshes text/hash + reconciles
|
|
322
|
+
// added/removed criteria, but never clobbers bindings the agent authored.
|
|
323
|
+
const manifestPath = resolve(opts.cwd, MANIFEST_RELATIVE_PATH);
|
|
324
|
+
const preservedBindings = loadPreservedBindings(manifestPath, io);
|
|
325
|
+
const objectives = criteria.map((c) => {
|
|
326
|
+
const id = `${cycleDocId}#${c.id}`;
|
|
327
|
+
const locator = `exit_criteria#${c.id}`;
|
|
328
|
+
// Defensive: the locator is built from `exit_criteria` + an `ec<k>` id, both
|
|
329
|
+
// of which satisfy SOURCE_LOCATOR_RE by construction — assert it so a future
|
|
330
|
+
// id-scheme change can't silently emit an unparseable locator.
|
|
331
|
+
if (!SOURCE_LOCATOR_RE.test(locator)) {
|
|
332
|
+
throw new Error(`internal: derived locator ${JSON.stringify(locator)} is malformed`);
|
|
333
|
+
}
|
|
334
|
+
const sha256 = sha256Hex(canonicalizeCriterion(c.raw));
|
|
335
|
+
return {
|
|
336
|
+
id,
|
|
337
|
+
source: { kind: "cycle", ref: opts.cycle },
|
|
338
|
+
text: c.text,
|
|
339
|
+
attestedBy: preservedBindings.get(id) ?? [],
|
|
340
|
+
enforced: false,
|
|
341
|
+
sourceCriterion: { kind: "text-hash", locator, sha256 },
|
|
342
|
+
};
|
|
343
|
+
});
|
|
344
|
+
const manifest = { schemaVersion: 1, objectives };
|
|
345
|
+
// Validate our own output against the schema parser — a derived manifest that
|
|
346
|
+
// can't round-trip is a bug, surfaced loudly here rather than at gate time.
|
|
347
|
+
try {
|
|
348
|
+
parseObjectivesManifest(manifest);
|
|
349
|
+
}
|
|
350
|
+
catch (err) {
|
|
351
|
+
io.stderr(`df objectives derive: internal error — derived manifest failed schema validation: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
352
|
+
return 1;
|
|
353
|
+
}
|
|
354
|
+
if (opts.json) {
|
|
355
|
+
io.stdout(`${JSON.stringify(manifest, null, 2)}\n`);
|
|
356
|
+
}
|
|
357
|
+
const yaml = yamlStringify(manifest);
|
|
358
|
+
if (opts.apply) {
|
|
359
|
+
mkdirSync(dirname(manifestPath), { recursive: true });
|
|
360
|
+
writeFileSync(manifestPath, yaml, "utf8");
|
|
361
|
+
if (!opts.json) {
|
|
362
|
+
io.stdout(`Wrote ${objectives.length} objective${objectives.length === 1 ? "" : "s"} to ` +
|
|
363
|
+
`${MANIFEST_RELATIVE_PATH}\n`);
|
|
364
|
+
}
|
|
365
|
+
return 0;
|
|
366
|
+
}
|
|
367
|
+
if (!opts.json) {
|
|
368
|
+
io.stdout(yaml);
|
|
369
|
+
}
|
|
370
|
+
return 0;
|
|
371
|
+
}
|
|
372
|
+
async function cmdCheck(opts, io, deps) {
|
|
373
|
+
const read = deps.readCycleDoc ?? readCycleDoc;
|
|
374
|
+
const manifestPath = resolve(opts.cwd, MANIFEST_RELATIVE_PATH);
|
|
375
|
+
if (!existsSync(manifestPath)) {
|
|
376
|
+
const msg = `No ${MANIFEST_RELATIVE_PATH} found under ${opts.cwd} — nothing to check.`;
|
|
377
|
+
if (opts.json) {
|
|
378
|
+
io.stdout(JSON.stringify({ ok: true, note: msg, results: [] }, null, 2) + "\n");
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
io.stdout(`note: ${msg}\n`);
|
|
382
|
+
}
|
|
383
|
+
return 0;
|
|
384
|
+
}
|
|
385
|
+
let manifest;
|
|
386
|
+
try {
|
|
387
|
+
const raw = readFileSync(manifestPath, "utf8");
|
|
388
|
+
manifest = parseObjectivesManifest(yamlParse(raw));
|
|
389
|
+
}
|
|
390
|
+
catch (err) {
|
|
391
|
+
io.stderr(`df objectives check: ${MANIFEST_RELATIVE_PATH} could not be parsed: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
392
|
+
return 1;
|
|
393
|
+
}
|
|
394
|
+
const results = [];
|
|
395
|
+
let anyFail = false;
|
|
396
|
+
for (const obj of manifest.objectives) {
|
|
397
|
+
const sc = obj.sourceCriterion;
|
|
398
|
+
if (sc === undefined) {
|
|
399
|
+
results.push({ id: obj.id, status: "note", message: "no sourceCriterion binding — skipped." });
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
if (sc.kind === "human-reviewed") {
|
|
403
|
+
results.push({ id: obj.id, status: "note", message: "human-reviewed — skipped." });
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
if (sc.kind === "inferred") {
|
|
407
|
+
results.push({
|
|
408
|
+
id: obj.id,
|
|
409
|
+
status: "note",
|
|
410
|
+
message: "inferred (awaiting ratification) — skipped.",
|
|
411
|
+
});
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
// sc.kind === "text-hash"
|
|
415
|
+
// Parse the locator: `<section>#<criterion-id>`
|
|
416
|
+
const hashMatch = /^([^#]+)#(.+)$/.exec(sc.locator);
|
|
417
|
+
if (!hashMatch) {
|
|
418
|
+
results.push({ id: obj.id, status: "fail", message: `malformed locator: ${sc.locator}` });
|
|
419
|
+
anyFail = true;
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
const sectionSlug = hashMatch[1];
|
|
423
|
+
const criterionId = hashMatch[2];
|
|
424
|
+
// Only `exit_criteria` is currently resolvable.
|
|
425
|
+
if (sectionSlug !== "exit_criteria") {
|
|
426
|
+
results.push({
|
|
427
|
+
id: obj.id,
|
|
428
|
+
status: "fail",
|
|
429
|
+
message: `unsupported section in locator: ${sectionSlug} (only exit_criteria is supported).`,
|
|
430
|
+
});
|
|
431
|
+
anyFail = true;
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
// Derive cycle id from the objective id (`cycle<N>#ec<k>` → `cycle<N>`).
|
|
435
|
+
const cycleIdMatch = /^(cycle[^#]+)#/.exec(obj.id);
|
|
436
|
+
if (!cycleIdMatch || !obj.source || obj.source.kind !== "cycle") {
|
|
437
|
+
results.push({
|
|
438
|
+
id: obj.id,
|
|
439
|
+
status: "fail",
|
|
440
|
+
message: `cannot derive cycle doc id from objective id: ${obj.id}`,
|
|
441
|
+
});
|
|
442
|
+
anyFail = true;
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
const cycleDocId = `cycle${obj.source.ref}`;
|
|
446
|
+
const doc = await read(opts.cwd, cycleDocId);
|
|
447
|
+
if (doc === null) {
|
|
448
|
+
results.push({
|
|
449
|
+
id: obj.id,
|
|
450
|
+
status: "fail",
|
|
451
|
+
message: `cycle doc ${cycleDocId} not found under ${join(opts.cwd, "docs/roadmap/cycles")}.`,
|
|
452
|
+
});
|
|
453
|
+
anyFail = true;
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
const section = doc.sections[sectionSlug];
|
|
457
|
+
if (section === undefined || section.trim() === "") {
|
|
458
|
+
results.push({
|
|
459
|
+
id: obj.id,
|
|
460
|
+
status: "fail",
|
|
461
|
+
message: `cycle doc ${cycleDocId} has no '${sectionSlug}' section.`,
|
|
462
|
+
});
|
|
463
|
+
anyFail = true;
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
const criteria = extractExitCriteria(section);
|
|
467
|
+
const criterion = criteria.find((c) => c.id === criterionId);
|
|
468
|
+
if (criterion === undefined) {
|
|
469
|
+
results.push({
|
|
470
|
+
id: obj.id,
|
|
471
|
+
status: "fail",
|
|
472
|
+
message: `criterion ${criterionId} not found in ${cycleDocId} '${sectionSlug}' (${criteria.length} items found).`,
|
|
473
|
+
});
|
|
474
|
+
anyFail = true;
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
const actualSha256 = sha256Hex(canonicalizeCriterion(criterion.raw));
|
|
478
|
+
if (actualSha256 !== sc.sha256) {
|
|
479
|
+
results.push({
|
|
480
|
+
id: obj.id,
|
|
481
|
+
status: "fail",
|
|
482
|
+
message: `text-hash mismatch for ${criterionId} in ${cycleDocId}: ` +
|
|
483
|
+
`declared ${sc.sha256.slice(0, 12)}… ≠ actual ${actualSha256.slice(0, 12)}… ` +
|
|
484
|
+
`(criterion text may have changed — re-run \`df objectives derive\` to refresh).`,
|
|
485
|
+
});
|
|
486
|
+
anyFail = true;
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
results.push({ id: obj.id, status: "ok", message: `text-hash verified (${sc.sha256.slice(0, 12)}…).` });
|
|
490
|
+
}
|
|
491
|
+
if (opts.json) {
|
|
492
|
+
io.stdout(JSON.stringify({ ok: !anyFail, results: results.map((r) => ({ id: r.id, status: r.status, message: r.message })) }, null, 2) + "\n");
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
for (const r of results) {
|
|
496
|
+
if (r.status === "ok") {
|
|
497
|
+
io.stdout(`ok ${r.id}: ${r.message}\n`);
|
|
498
|
+
}
|
|
499
|
+
else if (r.status === "fail") {
|
|
500
|
+
io.stdout(`FAIL ${r.id}: ${r.message}\n`);
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
io.stdout(`note ${r.id}: ${r.message}\n`);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
if (!anyFail && results.length > 0) {
|
|
507
|
+
io.stdout(`\nAll ${results.length} objective${results.length === 1 ? "" : "s"} ok.\n`);
|
|
508
|
+
}
|
|
509
|
+
else if (!anyFail && results.length === 0) {
|
|
510
|
+
io.stdout("No objectives to check.\n");
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return anyFail ? 1 : 0;
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Read an existing manifest (if any) and return a map of objective id →
|
|
517
|
+
* `attestedBy` bindings to preserve across a re-derive. A malformed/unreadable
|
|
518
|
+
* existing manifest is non-fatal (we warn and derive fresh) — the worst case is
|
|
519
|
+
* losing hand-edits the operator can re-add, which is strictly safer than
|
|
520
|
+
* refusing to derive.
|
|
521
|
+
*/
|
|
522
|
+
function loadPreservedBindings(manifestPath, io) {
|
|
523
|
+
const preserved = new Map();
|
|
524
|
+
if (!existsSync(manifestPath)) {
|
|
525
|
+
return preserved;
|
|
526
|
+
}
|
|
527
|
+
let parsed;
|
|
528
|
+
try {
|
|
529
|
+
const existing = readFileSync(manifestPath, "utf8");
|
|
530
|
+
parsed = parseObjectivesManifest(yamlParse(existing));
|
|
531
|
+
}
|
|
532
|
+
catch (err) {
|
|
533
|
+
io.stderr(`df objectives derive: warning — existing ${MANIFEST_RELATIVE_PATH} could not be ` +
|
|
534
|
+
`parsed (${err instanceof Error ? err.message : String(err)}); deriving fresh, ` +
|
|
535
|
+
"hand-edited attestedBy bindings are NOT preserved.\n");
|
|
536
|
+
return preserved;
|
|
537
|
+
}
|
|
538
|
+
for (const obj of parsed.objectives) {
|
|
539
|
+
if (obj.attestedBy.length > 0) {
|
|
540
|
+
preserved.set(obj.id, obj.attestedBy);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return preserved;
|
|
544
|
+
}
|
|
545
|
+
//# sourceMappingURL=objectives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"objectives.js","sourceRoot":"","sources":["../../src/commands/objectives.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,sDAAsD;AACtD,EAAE;AACF,eAAe;AACf,sFAAsF;AACtF,4FAA4F;AAC5F,yEAAyE;AACzE,EAAE;AACF,8DAA8D;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,GAGlB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAwC1D,MAAM,UAAU,mBAAmB,CAAC,IAAc;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE9B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;QACpC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACrB,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,uBAAuB,GAAG,EAAE,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,aAAa,CAAC,IAAc;IACnC,IAAI,IAAwB,CAAC;IAE7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAExB,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,OAAO,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC;YAC/C,CAAC;YACD,IAAI,GAAG,IAAI,CAAC;YACZ,CAAC,EAAE,CAAC;YACJ,SAAS;QACX,CAAC;QAED,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACjC,SAAS;QACX,CAAC;QAED,qCAAqC;QACrC,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YACzC,OAAO;gBACL,KAAK,EACH,GAAG,CAAC,kFAAkF;aACzF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;YAClE,OAAO;gBACL,KAAK,EACH,GAAG,IAAI,kFAAkF;aAC5F,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,mCAAmC,CAAC,EAAE,EAAE,CAAC;IAC3D,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,iEAAiE,EAAE,CAAC;IACtF,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACtC,CAAC;AAED,SAAS,eAAe,CAAC,IAAc;IACrC,IAAI,KAAyB,CAAC;IAC9B,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAExB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAExB,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,OAAO,EAAE,KAAK,EAAE,6CAA6C,EAAE,CAAC;YAClE,CAAC;YACD,KAAK,GAAG,IAAI,CAAC;YACb,CAAC,EAAE,CAAC;YACJ,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7B,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACnC,SAAS;QACX,CAAC;QAED,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,OAAO,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC;YAC9C,CAAC;YACD,GAAG,GAAG,IAAI,CAAC;YACX,CAAC,EAAE,CAAC;YACJ,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3B,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QAED,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YACpB,KAAK,GAAG,IAAI,CAAC;YACb,SAAS;QACX,CAAC;QACD,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;YACnB,IAAI,GAAG,IAAI,CAAC;YACZ,SAAS;QACX,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,mCAAmC,CAAC,EAAE,EAAE,CAAC;IAC3D,CAAC;IAED,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxC,OAAO,EAAE,KAAK,EAAE,wCAAwC,EAAE,CAAC;IAC7D,CAAC;IAED,6EAA6E;IAC7E,2EAA2E;IAC3E,6EAA6E;IAC7E,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,OAAO,EAAE,KAAK,EAAE,4DAA4D,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACzG,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AAChE,CAAC;AAED,SAAS,cAAc,CAAC,IAAc;IACpC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAExB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAExB,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,OAAO,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC;YAC9C,CAAC;YACD,GAAG,GAAG,IAAI,CAAC;YACX,CAAC,EAAE,CAAC;YACJ,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3B,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QAED,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;YACnB,IAAI,GAAG,IAAI,CAAC;YACZ,SAAS;QACX,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,mCAAmC,CAAC,EAAE,EAAE,CAAC;IAC3D,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AAC5C,CAAC;AAED,8EAA8E;AAC9E,wDAAwD;AACxD,EAAE;AACF,6EAA6E;AAC7E,4EAA4E;AAC5E,8EAA8E;AAC9E,oEAAoE;AACpE,EAAE;AACF,+EAA+E;AAC/E,wEAAwE;AACxE,0EAA0E;AAC1E,8EAA8E;AAC9E,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAC9E,+EAA+E;AAC/E,+EAA+E;AAC/E,+EAA+E;AAC/E,4CAA4C;AAC5C,EAAE;AACF,+EAA+E;AAC/E,4DAA4D;AAC5D,+EAA+E;AAC/E,+EAA+E;AAC/E,sCAAsC;AACtC,8EAA8E;AAE9E,gEAAgE;AAChE,MAAM,OAAO,GAAG,0BAA0B,CAAC;AAE3C,8EAA8E;AAC9E,8EAA8E;AAC9E,sEAAsE;AACtE,gFAAgF;AAChF,+BAA+B;AAC/B,MAAM,WAAW,GAAG,2DAA2D,CAAC;AAEhF,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,6EAA6E;AAC7E,qEAAqE;AACrE,SAAS,oBAAoB,CAAC,OAAe;IAC3C,IAAI,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc;IAC7D,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,iDAAiD,EAAE,EAAE,CAAC,CAAC,CAAC,oBAAoB;IAC1F,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,iCAAiC;IAC7D,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,OAAO,CAAC,CAAC;AACX,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,MAAM,GAAG,GAAyB,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,oBAAoB,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,sBAAsB,GAAG,IAAI,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;AAEvE,MAAM,IAAI,GAAG;IACX,0EAA0E;IAC1E,EAAE;IACF,QAAQ;IACR,sCAAsC;IACtC,EAAE;IACF,cAAc;IACd,4DAA4D;IAC5D,gFAAgF;IAChF,+DAA+D;IAC/D,EAAE;IACF,eAAe;IACf,0DAA0D;IAC1D,EAAE;IACF,iBAAiB;IACjB,mFAAmF;IACnF,sFAAsF;IACtF,6EAA6E;IAC7E,yEAAyE;IACzE,EAAE;IACF,gBAAgB;IAChB,uGAAuG;IACvG,sDAAsD;IACtD,EAAE;IACF,0CAA0C;IAC1C,EAAE;IACF,aAAa;IACb,cAAc;IACd,uBAAuB;IACvB,yBAAyB;IACzB,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAc,EACd,EAAgB,EAChB,OAAuB,EAAE;IAEzB,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,EAAE,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QACrB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAEzC,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;QACtB,EAAE,CAAC,MAAM,CAAC,kBAAkB,MAAM,CAAC,KAAK,6CAA6C,CAAC,CAAC;QACvF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACpC,EAAE,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QACrB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrG,EAAE,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,SAAS,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;QAClC,OAAO,QAAQ,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,8EAA8E;IAC9E,EAAE,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IACrB,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,IAAmB,EACnB,EAAgB,EAChB,IAAoB;IAEpB,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC;IAC/C,MAAM,UAAU,GAAG,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;IAExC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC7C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,EAAE,CAAC,MAAM,CACP,mCAAmC,UAAU,mBAAmB;YAC9D,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,yBAAyB,CACpE,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC9C,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACnD,EAAE,CAAC,MAAM,CACP,mCAAmC,UAAU,qCAAqC;YAChF,yCAAyC,CAC5C,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,EAAE,CAAC,MAAM,CACP,mCAAmC,UAAU,qCAAqC;YAChF,mCAAmC,CACtC,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,wEAAwE;IACxE,8EAA8E;IAC9E,iFAAiF;IACjF,6EAA6E;IAC7E,2EAA2E;IAC3E,qDAAqD;IACrD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,GAAG,UAAU,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QAC1B,EAAE,CAAC,MAAM,CACP,yBAAyB,UAAU,yCAAyC;YAC1E,UAAU,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,4CAA4C;YAClF,mEAAmE,CACtE,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,2EAA2E;IAC3E,wEAAwE;IACxE,0EAA0E;IAC1E,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;IAC/D,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAElE,MAAM,UAAU,GAAgB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACjD,MAAM,EAAE,GAAG,GAAG,UAAU,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,iBAAiB,CAAC,CAAC,EAAE,EAAE,CAAC;QACxC,6EAA6E;QAC7E,6EAA6E;QAC7E,+DAA+D;QAC/D,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,OAAO;YACL,EAAE;YACF,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE;YAC1C,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,UAAU,EAAE,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE;YAC3C,QAAQ,EAAE,KAAK;YACf,eAAe,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE;SACxD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAuB,EAAE,aAAa,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;IAEtE,8EAA8E;IAC9E,4EAA4E;IAC5E,IAAI,CAAC;QACH,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,EAAE,CAAC,MAAM,CACP,qFACE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,IAAI,CACL,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,EAAE,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAErC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,aAAa,CAAC,YAAY,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,EAAE,CAAC,MAAM,CACP,SAAS,UAAU,CAAC,MAAM,aAAa,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM;gBAC7E,GAAG,sBAAsB,IAAI,CAChC,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AA0BD,KAAK,UAAU,QAAQ,CACrB,IAAkB,EAClB,EAAgB,EAChB,IAAoB;IAEpB,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC;IAC/C,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;IAE/D,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,MAAM,sBAAsB,gBAAgB,IAAI,CAAC,GAAG,sBAAsB,CAAC;QACvF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAClF,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAC/C,QAAQ,GAAG,uBAAuB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,EAAE,CAAC,MAAM,CACP,wBAAwB,sBAAsB,yBAC5C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,IAAI,CACL,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,GAAG,CAAC,eAAe,CAAC;QAE/B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,uCAAuC,EAAE,CAAC,CAAC;YAC/F,SAAS;QACX,CAAC;QAED,IAAI,EAAE,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC,CAAC;YACnF,SAAS;QACX,CAAC;QAED,IAAI,EAAE,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,6CAA6C;aACvD,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,0BAA0B;QAC1B,gDAAgD;QAChD,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC1F,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QACD,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;QAClC,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;QAElC,gDAAgD;QAChD,IAAI,WAAW,KAAK,eAAe,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,mCAAmC,WAAW,qCAAqC;aAC7F,CAAC,CAAC;YACH,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QAED,yEAAyE;QACzE,MAAM,YAAY,GAAG,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,YAAY,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,iDAAiD,GAAG,CAAC,EAAE,EAAE;aACnE,CAAC,CAAC;YACH,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QAE5C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAC7C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,aAAa,UAAU,oBAAoB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,GAAG;aAC7F,CAAC,CAAC;YACH,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC1C,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,aAAa,UAAU,YAAY,WAAW,YAAY;aACpE,CAAC,CAAC;YACH,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;QAC7D,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,aAAa,WAAW,iBAAiB,UAAU,KAAK,WAAW,MAAM,QAAQ,CAAC,MAAM,gBAAgB;aAClH,CAAC,CAAC;YACH,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QAED,MAAM,YAAY,GAAG,SAAS,CAAC,qBAAqB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACrE,IAAI,YAAY,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,MAAM;gBACd,OAAO,EACL,0BAA0B,WAAW,OAAO,UAAU,IAAI;oBAC1D,YAAY,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI;oBAC7E,iFAAiF;aACpF,CAAC,CAAC;YACH,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1G,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,EAAE,CAAC,MAAM,CACP,IAAI,CAAC,SAAS,CACZ,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EACnG,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBACtB,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;YAC/C,CAAC;iBAAM,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC/B,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;YAC/C,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,EAAE,CAAC,MAAM,CAAC,SAAS,OAAO,CAAC,MAAM,aAAa,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;QACzF,CAAC;aAAM,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5C,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,qBAAqB,CAC5B,YAAoB,EACpB,EAAgB;IAEhB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAmC,CAAC;IAC7D,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,MAA0B,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACpD,MAAM,GAAG,uBAAuB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,EAAE,CAAC,MAAM,CACP,4CAA4C,sBAAsB,gBAAgB;YAChF,WAAW,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB;YAChF,sDAAsD,CACzD,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACpC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -1205,6 +1205,10 @@ def validate_objectives(
|
|
|
1205
1205
|
route_ids = _route_ids(repo_root)
|
|
1206
1206
|
declared = _declared_refs(trailers)
|
|
1207
1207
|
errors: list[str] = []
|
|
1208
|
+
# Objective ids must be UNIQUE within a manifest (mirrors the TS
|
|
1209
|
+
# parseObjectivesManifest reject): a duplicate id makes proof/evidence binding
|
|
1210
|
+
# ambiguous. Tracked across the loop below.
|
|
1211
|
+
seen_ids: set[str] = set()
|
|
1208
1212
|
for idx, obj in enumerate(objectives):
|
|
1209
1213
|
loc = f"{OBJECTIVES_MANIFEST_PATH} objectives[{idx}]"
|
|
1210
1214
|
if not isinstance(obj, dict):
|
|
@@ -1215,6 +1219,10 @@ def validate_objectives(
|
|
|
1215
1219
|
errors.append(
|
|
1216
1220
|
f"{loc}.id: expected 'cycle<N>#ec<k>' or 'issue<N>#ac<k>', got {oid!r}"
|
|
1217
1221
|
)
|
|
1222
|
+
if isinstance(oid, str):
|
|
1223
|
+
if oid in seen_ids:
|
|
1224
|
+
errors.append(f"{loc}.id: duplicate objective id: {oid!r}")
|
|
1225
|
+
seen_ids.add(oid)
|
|
1218
1226
|
text = obj.get("text")
|
|
1219
1227
|
if not isinstance(text, str) or not text:
|
|
1220
1228
|
errors.append(f"{loc}.text: expected a non-empty string")
|
|
@@ -1327,9 +1335,29 @@ def validate_objectives(
|
|
|
1327
1335
|
"(v1 verifies in-repo cycle docs) — recorded, not verified",
|
|
1328
1336
|
file=sys.stderr,
|
|
1329
1337
|
)
|
|
1338
|
+
elif sc_kind == "inferred":
|
|
1339
|
+
# Drafted-to-source (e.g. LLM-inferred) but NOT yet ratified →
|
|
1340
|
+
# structural-validate only, then a NON-BLOCKING note. Never
|
|
1341
|
+
# hash-verified (it is by definition not yet a ratified criterion);
|
|
1342
|
+
# ratification flips it to text-hash, which IS verified above.
|
|
1343
|
+
sloc, ssha = sc.get("locator"), sc.get("sha256")
|
|
1344
|
+
if not isinstance(sloc, str) or not SOURCE_LOCATOR_RE.match(sloc):
|
|
1345
|
+
errors.append(
|
|
1346
|
+
f"{loc}.sourceCriterion.locator: expected '<section-slug>#<criterion-id>', got {sloc!r}"
|
|
1347
|
+
)
|
|
1348
|
+
elif not isinstance(ssha, str) or not SHA256_HEX_RE.match(ssha):
|
|
1349
|
+
errors.append(
|
|
1350
|
+
f"{loc}.sourceCriterion.sha256: expected lowercase-hex SHA-256 (64 chars), got {ssha!r}"
|
|
1351
|
+
)
|
|
1352
|
+
else:
|
|
1353
|
+
print(
|
|
1354
|
+
f"[objectives] {loc}.sourceCriterion: inferred — drafted-to-source, "
|
|
1355
|
+
"awaiting ratification (recorded, not verified)",
|
|
1356
|
+
file=sys.stderr,
|
|
1357
|
+
)
|
|
1330
1358
|
else:
|
|
1331
1359
|
errors.append(
|
|
1332
|
-
f"{loc}.sourceCriterion.kind: expected 'text-hash' | 'human-reviewed', got {sc_kind!r}"
|
|
1360
|
+
f"{loc}.sourceCriterion.kind: expected 'text-hash' | 'human-reviewed' | 'inferred', got {sc_kind!r}"
|
|
1333
1361
|
)
|
|
1334
1362
|
elif sc is not None:
|
|
1335
1363
|
errors.append(f"{loc}.sourceCriterion: expected a mapping")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prove.d.ts","sourceRoot":"","sources":["../../src/evidence/prove.ts"],"names":[],"mappings":"AAsBA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,YAAY,EAEjB,KAAK,SAAS,EAKd,KAAK,aAAa,EACnB,MAAM,gCAAgC,CAAC;AASxC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAGD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,SAAS,EAAE,CAAC;IAExB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAEhD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAEnD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAqED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"prove.d.ts","sourceRoot":"","sources":["../../src/evidence/prove.ts"],"names":[],"mappings":"AAsBA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,YAAY,EAEjB,KAAK,SAAS,EAKd,KAAK,aAAa,EACnB,MAAM,gCAAgC,CAAC;AASxC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAGD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,SAAS,EAAE,CAAC;IAExB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAEhD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAEnD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAqED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAgC3F;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAQD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAiEtC"}
|
package/dist/evidence/prove.js
CHANGED
|
@@ -92,7 +92,9 @@ export function buildProofRecord(inputs, generatedAt) {
|
|
|
92
92
|
? "agent-asserted"
|
|
93
93
|
: o.sourceCriterion.kind === "human-reviewed"
|
|
94
94
|
? "human-reviewed"
|
|
95
|
-
: "
|
|
95
|
+
: o.sourceCriterion.kind === "inferred"
|
|
96
|
+
? "inferred"
|
|
97
|
+
: "source-bound";
|
|
96
98
|
return { id: o.id, text: o.text, enforced: o.enforced, status, bindings, sourceVerification };
|
|
97
99
|
});
|
|
98
100
|
const summary = { proven: 0, pending: 0, failed: 0, total: objectives.length };
|