syntaur 0.68.0 → 0.70.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/.claude-plugin/plugin.json +1 -1
- package/dashboard/dist/assets/{_basePickBy-CE2CIvur.js → _basePickBy-DKk6tHtk.js} +1 -1
- package/dashboard/dist/assets/{_baseUniq-BznLQqID.js → _baseUniq-DM-f7DWz.js} +1 -1
- package/dashboard/dist/assets/{arc-B6JqtWve.js → arc-ZBlA3YdV.js} +1 -1
- package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-P8UCT3rj.js → architectureDiagram-2XIMDMQ5-BUmvtGTF.js} +1 -1
- package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-C1ATZKSf.js → blockDiagram-WCTKOSBZ-B3qxWK6s.js} +1 -1
- package/dashboard/dist/assets/{c4Diagram-IC4MRINW-AvN1yayQ.js → c4Diagram-IC4MRINW-BEq_UJO-.js} +1 -1
- package/dashboard/dist/assets/channel-fypxffzQ.js +1 -0
- package/dashboard/dist/assets/{chunk-4BX2VUAB-CyYz6mlJ.js → chunk-4BX2VUAB-C-Y9ryMm.js} +1 -1
- package/dashboard/dist/assets/{chunk-55IACEB6-QyOF7ox_.js → chunk-55IACEB6-CGdtbsjw.js} +1 -1
- package/dashboard/dist/assets/{chunk-FMBD7UC4-DVTHM99U.js → chunk-FMBD7UC4-DllxJhUp.js} +1 -1
- package/dashboard/dist/assets/{chunk-JSJVCQXG-DQfxaQtT.js → chunk-JSJVCQXG-jjMM8O5F.js} +1 -1
- package/dashboard/dist/assets/{chunk-KX2RTZJC-4R1oobH6.js → chunk-KX2RTZJC-B_6BPltQ.js} +1 -1
- package/dashboard/dist/assets/{chunk-NQ4KR5QH-D8H_7yNS.js → chunk-NQ4KR5QH-D0hJiXHp.js} +1 -1
- package/dashboard/dist/assets/{chunk-QZHKN3VN-DLxDUSuo.js → chunk-QZHKN3VN-BCWo4hLS.js} +1 -1
- package/dashboard/dist/assets/{chunk-WL4C6EOR-CWuFDkVp.js → chunk-WL4C6EOR-DH_jEAwg.js} +1 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-1KnjQvtL.js +1 -0
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-1KnjQvtL.js +1 -0
- package/dashboard/dist/assets/clone-CKMabBhS.js +1 -0
- package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-D23Dy_Za.js → cose-bilkent-S5V4N54A-5ld00TOH.js} +1 -1
- package/dashboard/dist/assets/{dagre-KLK3FWXG-CaKBk8eh.js → dagre-KLK3FWXG-Cnu6eQWy.js} +1 -1
- package/dashboard/dist/assets/{diagram-E7M64L7V-BAPQPki-.js → diagram-E7M64L7V-_CBBKNP-.js} +1 -1
- package/dashboard/dist/assets/{diagram-IFDJBPK2-Cla6qyvn.js → diagram-IFDJBPK2-DE6WjIb1.js} +1 -1
- package/dashboard/dist/assets/{diagram-P4PSJMXO-DnTZq_y6.js → diagram-P4PSJMXO-DpW7UzNK.js} +1 -1
- package/dashboard/dist/assets/{erDiagram-INFDFZHY-yc1_7ebn.js → erDiagram-INFDFZHY-BD2409fE.js} +1 -1
- package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-CMt2tF6O.js → flowDiagram-PKNHOUZH-1p0khhFI.js} +1 -1
- package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-CXiK-5Gp.js → ganttDiagram-A5KZAMGK-B2zFyA4s.js} +1 -1
- package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-B4PbW06T.js → gitGraphDiagram-K3NZZRJ6-bH-4YH7h.js} +1 -1
- package/dashboard/dist/assets/{graph-CjdFy-q-.js → graph-BT24B6iQ.js} +1 -1
- package/dashboard/dist/assets/{index-DlUgV5eO.css → index-BZwPAi8K.css} +1 -1
- package/dashboard/dist/assets/index-Cxqr3rQB.js +670 -0
- package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-BeOWVt7p.js → infoDiagram-LFFYTUFH-CMzP4Hcg.js} +1 -1
- package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-LE7swZOH.js → ishikawaDiagram-PHBUUO56-DMEmFC7M.js} +1 -1
- package/dashboard/dist/assets/{journeyDiagram-4ABVD52K-DG9-sksf.js → journeyDiagram-4ABVD52K-CAtzYQUm.js} +1 -1
- package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-7CKAw6eI.js → kanban-definition-K7BYSVSG-d1JVbtvX.js} +1 -1
- package/dashboard/dist/assets/{layout-CHChKPuz.js → layout-BVuI38I_.js} +1 -1
- package/dashboard/dist/assets/{linear-BWSj4au4.js → linear-Bc8PGMbp.js} +1 -1
- package/dashboard/dist/assets/{mermaid.core-CAwQaPqG.js → mermaid.core-UtwFYLNj.js} +4 -4
- package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-CtZWMkVN.js → mindmap-definition-YRQLILUH-DHc5RCDj.js} +1 -1
- package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-CstCoaK7.js → pieDiagram-SKSYHLDU-9anIsdIA.js} +1 -1
- package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-DD8zRtaB.js → quadrantDiagram-337W2JSQ-FZ0D9HnU.js} +1 -1
- package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-BWpKIK3b.js → requirementDiagram-Z7DCOOCP-BkjCvH_u.js} +1 -1
- package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-08gqQtFM.js → sankeyDiagram-WA2Y5GQK-DzqwYHDo.js} +1 -1
- package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-DsfIDBUH.js → sequenceDiagram-2WXFIKYE-BW4g5Ao-.js} +1 -1
- package/dashboard/dist/assets/{stateDiagram-RAJIS63D-Dqzfk_yy.js → stateDiagram-RAJIS63D-D0tKU3Z0.js} +1 -1
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-DxWQhjNO.js +1 -0
- package/dashboard/dist/assets/{timeline-definition-YZTLITO2-DgH_p9jR.js → timeline-definition-YZTLITO2-Bu269QDX.js} +1 -1
- package/dashboard/dist/assets/{treemap-KZPCXAKY-7XKqMhq9.js → treemap-KZPCXAKY-BGu_rrva.js} +1 -1
- package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-BFtNLBWM.js → vennDiagram-LZ73GAT5-Cx_n5FRZ.js} +1 -1
- package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-CQPevMNl.js → xychartDiagram-JWTSCODW-BOJsKV_W.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dist/dashboard/server.js +83 -46
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.js +353 -326
- package/dist/index.js.map +1 -1
- package/dist/launch/index.js +328 -37
- package/dist/launch/index.js.map +1 -1
- package/package.json +1 -1
- package/platforms/claude-code/.claude-plugin/plugin.json +1 -1
- package/platforms/codex/.codex-plugin/plugin.json +1 -1
- package/platforms/hermes/plugins/syntaur/__pycache__/__init__.cpython-312.pyc +0 -0
- package/platforms/hermes/plugins/syntaur/__pycache__/boundary.cpython-312.pyc +0 -0
- package/dashboard/dist/assets/channel-IZujZyS6.js +0 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-ChnJofe3.js +0 -1
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-ChnJofe3.js +0 -1
- package/dashboard/dist/assets/clone-JjIbzsqJ.js +0 -1
- package/dashboard/dist/assets/index-COOcebN7.js +0 -659
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-D542UPiR.js +0 -1
package/dist/launch/index.js
CHANGED
|
@@ -317,7 +317,7 @@ function getTargetStatus(_from, command, table) {
|
|
|
317
317
|
if (!table) {
|
|
318
318
|
return DEFAULT_COMMAND_TARGETS.get(command) ?? null;
|
|
319
319
|
}
|
|
320
|
-
return table.get(command) ?? table.get(
|
|
320
|
+
return table.get(`${_from}:${command}`) ?? table.get(command) ?? null;
|
|
321
321
|
}
|
|
322
322
|
var DEFAULT_COMMAND_TARGETS, DEFAULT_TRANSITION_TABLE;
|
|
323
323
|
var init_state_machine = __esm({
|
|
@@ -359,6 +359,287 @@ var init_state_machine = __esm({
|
|
|
359
359
|
});
|
|
360
360
|
|
|
361
361
|
// src/lifecycle/frontmatter.ts
|
|
362
|
+
function extractFrontmatter(fileContent) {
|
|
363
|
+
const match = fileContent.match(/^---\n([\s\S]*?)\n---/);
|
|
364
|
+
if (!match) {
|
|
365
|
+
throw new Error("No frontmatter found in file. Expected --- delimiters.");
|
|
366
|
+
}
|
|
367
|
+
const frontmatterBlock = match[1];
|
|
368
|
+
const body = fileContent.slice(match[0].length);
|
|
369
|
+
return [frontmatterBlock, body];
|
|
370
|
+
}
|
|
371
|
+
function parseSimpleValue(raw) {
|
|
372
|
+
const trimmed = raw.trim();
|
|
373
|
+
if (trimmed === "null" || trimmed === "~" || trimmed === "") return null;
|
|
374
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length >= 2) {
|
|
375
|
+
return trimmed.slice(1, -1).replace(/\\(["\\])/g, "$1");
|
|
376
|
+
}
|
|
377
|
+
if (trimmed.startsWith("'") && trimmed.endsWith("'") && trimmed.length >= 2) {
|
|
378
|
+
return trimmed.slice(1, -1);
|
|
379
|
+
}
|
|
380
|
+
return trimmed;
|
|
381
|
+
}
|
|
382
|
+
function parseDependsOn(frontmatter) {
|
|
383
|
+
const inlineMatch = frontmatter.match(/^dependsOn:\s*\[\s*\]/m);
|
|
384
|
+
if (inlineMatch) return [];
|
|
385
|
+
const results = [];
|
|
386
|
+
const blockMatch = frontmatter.match(/^dependsOn:\s*\n((?:\s+-\s+.*\n?)*)/m);
|
|
387
|
+
if (blockMatch) {
|
|
388
|
+
const items = blockMatch[1].matchAll(/^\s+-\s+(.+)$/gm);
|
|
389
|
+
for (const item of items) {
|
|
390
|
+
results.push(item[1].trim());
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return results;
|
|
394
|
+
}
|
|
395
|
+
function parseLinks(frontmatter) {
|
|
396
|
+
const inlineMatch = frontmatter.match(/^links:\s*\[\s*\]/m);
|
|
397
|
+
if (inlineMatch) return [];
|
|
398
|
+
const results = [];
|
|
399
|
+
const blockMatch = frontmatter.match(/^links:\s*\n((?:\s+-\s+.*\n?)*)/m);
|
|
400
|
+
if (blockMatch) {
|
|
401
|
+
const items = blockMatch[1].matchAll(/^\s+-\s+(.+)$/gm);
|
|
402
|
+
for (const item of items) {
|
|
403
|
+
results.push(item[1].trim());
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return results;
|
|
407
|
+
}
|
|
408
|
+
function parseExternalIds(frontmatter) {
|
|
409
|
+
const inlineMatch = frontmatter.match(/^externalIds:\s*\[\s*\]/m);
|
|
410
|
+
if (inlineMatch) return [];
|
|
411
|
+
const results = [];
|
|
412
|
+
const blockMatch = frontmatter.match(
|
|
413
|
+
/^externalIds:\s*\n((?:\s+-\s+[\s\S]*?)(?=^\w|\n---))/m
|
|
414
|
+
);
|
|
415
|
+
if (!blockMatch) return [];
|
|
416
|
+
const itemBlocks = blockMatch[1].split(/\n\s+-\s+/).filter(Boolean);
|
|
417
|
+
for (const block of itemBlocks) {
|
|
418
|
+
const lines = block.split("\n");
|
|
419
|
+
const entry = {};
|
|
420
|
+
for (const line of lines) {
|
|
421
|
+
const colonIdx = line.indexOf(":");
|
|
422
|
+
if (colonIdx < 0) continue;
|
|
423
|
+
const key = line.slice(0, colonIdx).trim().replace(/^-\s+/, "");
|
|
424
|
+
if (!key) continue;
|
|
425
|
+
entry[key] = parseSimpleValue(line.slice(colonIdx + 1));
|
|
426
|
+
}
|
|
427
|
+
if (entry["system"] && entry["id"]) {
|
|
428
|
+
results.push({
|
|
429
|
+
system: entry["system"],
|
|
430
|
+
id: entry["id"],
|
|
431
|
+
url: entry["url"] || null
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return results;
|
|
436
|
+
}
|
|
437
|
+
function parseStatusHistory(frontmatter) {
|
|
438
|
+
if (/^statusHistory:\s*\[\s*\]/m.test(frontmatter)) return [];
|
|
439
|
+
const headerMatch = frontmatter.match(/^statusHistory:\s*$/m);
|
|
440
|
+
if (!headerMatch) return [];
|
|
441
|
+
const headerStart = headerMatch.index ?? frontmatter.indexOf(headerMatch[0]);
|
|
442
|
+
const bodyStart = headerStart + headerMatch[0].length + 1;
|
|
443
|
+
const after = frontmatter.slice(bodyStart);
|
|
444
|
+
const bodyLines = [];
|
|
445
|
+
for (const line of after.split("\n")) {
|
|
446
|
+
if (line.length === 0) {
|
|
447
|
+
bodyLines.push(line);
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
if (line[0] !== " " && line[0] !== " ") break;
|
|
451
|
+
bodyLines.push(line);
|
|
452
|
+
}
|
|
453
|
+
const body = bodyLines.join("\n");
|
|
454
|
+
const results = [];
|
|
455
|
+
const itemBlocks = body.split(/\n\s+-\s+/).filter((b) => b.trim().length > 0);
|
|
456
|
+
for (const block of itemBlocks) {
|
|
457
|
+
const entry = {};
|
|
458
|
+
for (const line of block.split("\n")) {
|
|
459
|
+
const colonIdx = line.indexOf(":");
|
|
460
|
+
if (colonIdx < 0) continue;
|
|
461
|
+
const key = line.slice(0, colonIdx).trim().replace(/^-\s+/, "");
|
|
462
|
+
if (!key) continue;
|
|
463
|
+
entry[key] = parseSimpleValue(line.slice(colonIdx + 1));
|
|
464
|
+
}
|
|
465
|
+
if (!entry["to"]) continue;
|
|
466
|
+
const result = {
|
|
467
|
+
at: entry["at"] ?? "",
|
|
468
|
+
from: entry["from"] ?? null,
|
|
469
|
+
to: entry["to"],
|
|
470
|
+
command: entry["command"] ?? "",
|
|
471
|
+
by: entry["by"] ?? null
|
|
472
|
+
};
|
|
473
|
+
if (entry["reason"] != null) result.reason = entry["reason"];
|
|
474
|
+
if ("phaseFrom" in entry) result.phaseFrom = entry["phaseFrom"];
|
|
475
|
+
if ("phaseTo" in entry) result.phaseTo = entry["phaseTo"];
|
|
476
|
+
if ("dispositionFrom" in entry) result.dispositionFrom = entry["dispositionFrom"];
|
|
477
|
+
if ("dispositionTo" in entry) result.dispositionTo = entry["dispositionTo"];
|
|
478
|
+
results.push(result);
|
|
479
|
+
}
|
|
480
|
+
return results;
|
|
481
|
+
}
|
|
482
|
+
function parseNestedBlock(frontmatter, header) {
|
|
483
|
+
if (new RegExp(`^${header}:\\s*(null|~)\\s*$`, "m").test(frontmatter)) return null;
|
|
484
|
+
const headerMatch = frontmatter.match(new RegExp(`^${header}:\\s*$`, "m"));
|
|
485
|
+
if (!headerMatch) return null;
|
|
486
|
+
const headerStart = headerMatch.index ?? frontmatter.indexOf(headerMatch[0]);
|
|
487
|
+
const after = frontmatter.slice(headerStart + headerMatch[0].length + 1);
|
|
488
|
+
const out = {};
|
|
489
|
+
for (const line of after.split("\n")) {
|
|
490
|
+
if (line.length === 0) continue;
|
|
491
|
+
if (line[0] !== " " && line[0] !== " ") break;
|
|
492
|
+
const colonIdx = line.indexOf(":");
|
|
493
|
+
if (colonIdx < 0) continue;
|
|
494
|
+
const key = line.slice(0, colonIdx).trim();
|
|
495
|
+
if (!key) continue;
|
|
496
|
+
out[key] = parseSimpleValue(line.slice(colonIdx + 1));
|
|
497
|
+
}
|
|
498
|
+
return Object.keys(out).length > 0 ? out : null;
|
|
499
|
+
}
|
|
500
|
+
function parsePlanApproval(frontmatter) {
|
|
501
|
+
const block = parseNestedBlock(frontmatter, "planApproval");
|
|
502
|
+
if (!block || !block["file"] || !block["digest"]) return null;
|
|
503
|
+
return {
|
|
504
|
+
file: block["file"],
|
|
505
|
+
digest: block["digest"],
|
|
506
|
+
by: block["by"] ?? null,
|
|
507
|
+
at: block["at"] ?? ""
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
function parseOverride(frontmatter) {
|
|
511
|
+
const block = parseNestedBlock(frontmatter, "override");
|
|
512
|
+
if (!block || !block["status"]) return null;
|
|
513
|
+
return {
|
|
514
|
+
status: block["status"],
|
|
515
|
+
source: block["source"] ?? "human",
|
|
516
|
+
reason: block["reason"] ?? null,
|
|
517
|
+
at: block["at"] ?? ""
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
function parseFactsMap(frontmatter) {
|
|
521
|
+
const block = parseNestedBlock(frontmatter, "facts");
|
|
522
|
+
if (!block) return {};
|
|
523
|
+
const out = {};
|
|
524
|
+
for (const [k, v] of Object.entries(block)) {
|
|
525
|
+
if (v === null) continue;
|
|
526
|
+
out[k] = v;
|
|
527
|
+
}
|
|
528
|
+
return out;
|
|
529
|
+
}
|
|
530
|
+
function parseAttestations(frontmatter) {
|
|
531
|
+
if (/^attestations:\s*\[\s*\]/m.test(frontmatter)) return [];
|
|
532
|
+
const headerMatch = frontmatter.match(/^attestations:\s*$/m);
|
|
533
|
+
if (!headerMatch) return [];
|
|
534
|
+
const headerStart = headerMatch.index ?? frontmatter.indexOf(headerMatch[0]);
|
|
535
|
+
const bodyStart = headerStart + headerMatch[0].length + 1;
|
|
536
|
+
const after = frontmatter.slice(bodyStart);
|
|
537
|
+
const bodyLines = [];
|
|
538
|
+
for (const line of after.split("\n")) {
|
|
539
|
+
if (line.length === 0) {
|
|
540
|
+
bodyLines.push(line);
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
if (line[0] !== " " && line[0] !== " ") break;
|
|
544
|
+
bodyLines.push(line);
|
|
545
|
+
}
|
|
546
|
+
const body = bodyLines.join("\n");
|
|
547
|
+
const results = [];
|
|
548
|
+
const itemBlocks = body.split(/\n\s+-\s+/).filter((b) => b.trim().length > 0);
|
|
549
|
+
for (const block of itemBlocks) {
|
|
550
|
+
const entry = {};
|
|
551
|
+
for (const line of block.split("\n")) {
|
|
552
|
+
const colonIdx = line.indexOf(":");
|
|
553
|
+
if (colonIdx < 0) continue;
|
|
554
|
+
const key = line.slice(0, colonIdx).trim().replace(/^-\s+/, "");
|
|
555
|
+
if (!key) continue;
|
|
556
|
+
entry[key] = parseSimpleValue(line.slice(colonIdx + 1));
|
|
557
|
+
}
|
|
558
|
+
const verdict = entry["verdict"];
|
|
559
|
+
if (!entry["fact"] || !entry["actor"] || !verdict || !entry["at"]) continue;
|
|
560
|
+
if (verdict !== "approved" && verdict !== "changes-requested") continue;
|
|
561
|
+
const record = {
|
|
562
|
+
fact: entry["fact"],
|
|
563
|
+
actor: entry["actor"],
|
|
564
|
+
verdict,
|
|
565
|
+
at: entry["at"]
|
|
566
|
+
};
|
|
567
|
+
if (entry["note"] != null) record.note = entry["note"];
|
|
568
|
+
if (entry["file"] != null) record.file = entry["file"];
|
|
569
|
+
if (entry["digest"] != null) record.digest = entry["digest"];
|
|
570
|
+
if (entry["commit"] != null) record.commit = entry["commit"];
|
|
571
|
+
results.push(record);
|
|
572
|
+
}
|
|
573
|
+
return results;
|
|
574
|
+
}
|
|
575
|
+
function parseWorkspace(frontmatter) {
|
|
576
|
+
const defaults = {
|
|
577
|
+
repository: null,
|
|
578
|
+
worktreePath: null,
|
|
579
|
+
branch: null,
|
|
580
|
+
parentBranch: null
|
|
581
|
+
};
|
|
582
|
+
const fields = ["repository", "worktreePath", "branch", "parentBranch"];
|
|
583
|
+
for (const field of fields) {
|
|
584
|
+
const match = frontmatter.match(new RegExp(`^\\s+${field}:\\s*(.*)$`, "m"));
|
|
585
|
+
if (match) {
|
|
586
|
+
defaults[field] = parseSimpleValue(match[1]);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return defaults;
|
|
590
|
+
}
|
|
591
|
+
function parseTags(frontmatter) {
|
|
592
|
+
const inlineMatch = frontmatter.match(/^tags:\s*\[\s*\]/m);
|
|
593
|
+
if (inlineMatch) return [];
|
|
594
|
+
const results = [];
|
|
595
|
+
const blockMatch = frontmatter.match(/^tags:\s*\n((?:\s+-\s+.*\n?)*)/m);
|
|
596
|
+
if (blockMatch) {
|
|
597
|
+
const items = blockMatch[1].matchAll(/^\s+-\s+(.+)$/gm);
|
|
598
|
+
for (const item of items) {
|
|
599
|
+
results.push(item[1].trim());
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
return results;
|
|
603
|
+
}
|
|
604
|
+
function parseAssignmentFrontmatter(fileContent) {
|
|
605
|
+
const [frontmatter] = extractFrontmatter(fileContent);
|
|
606
|
+
function getField2(key) {
|
|
607
|
+
const match = frontmatter.match(new RegExp(`^${key}:\\s*(.*)$`, "m"));
|
|
608
|
+
if (!match) return null;
|
|
609
|
+
return parseSimpleValue(match[1]);
|
|
610
|
+
}
|
|
611
|
+
return {
|
|
612
|
+
id: getField2("id") ?? "",
|
|
613
|
+
slug: getField2("slug") ?? "",
|
|
614
|
+
title: getField2("title") ?? "",
|
|
615
|
+
project: getField2("project"),
|
|
616
|
+
type: getField2("type"),
|
|
617
|
+
status: getField2("status") ?? "pending",
|
|
618
|
+
priority: getField2("priority") ?? "medium",
|
|
619
|
+
created: getField2("created") ?? "",
|
|
620
|
+
updated: getField2("updated") ?? "",
|
|
621
|
+
assignee: getField2("assignee"),
|
|
622
|
+
externalIds: parseExternalIds(frontmatter),
|
|
623
|
+
statusHistory: parseStatusHistory(frontmatter),
|
|
624
|
+
dependsOn: parseDependsOn(frontmatter),
|
|
625
|
+
links: parseLinks(frontmatter),
|
|
626
|
+
blockedReason: getField2("blockedReason"),
|
|
627
|
+
workspace: parseWorkspace(frontmatter),
|
|
628
|
+
tags: parseTags(frontmatter),
|
|
629
|
+
archived: getField2("archived") === "true",
|
|
630
|
+
archivedAt: getField2("archivedAt"),
|
|
631
|
+
archivedReason: getField2("archivedReason"),
|
|
632
|
+
phase: getField2("phase"),
|
|
633
|
+
disposition: getField2("disposition"),
|
|
634
|
+
planApproval: parsePlanApproval(frontmatter),
|
|
635
|
+
parked: getField2("parked") === "true",
|
|
636
|
+
reviewRequested: getField2("reviewRequested") === "true",
|
|
637
|
+
implementationStarted: getField2("implementationStarted") === "true",
|
|
638
|
+
override: parseOverride(frontmatter),
|
|
639
|
+
facts: parseFactsMap(frontmatter),
|
|
640
|
+
attestations: parseAttestations(frontmatter)
|
|
641
|
+
};
|
|
642
|
+
}
|
|
362
643
|
var init_frontmatter = __esm({
|
|
363
644
|
"src/lifecycle/frontmatter.ts"() {
|
|
364
645
|
"use strict";
|
|
@@ -393,7 +674,7 @@ var init_event_emit = __esm({
|
|
|
393
674
|
});
|
|
394
675
|
|
|
395
676
|
// src/dashboard/parser.ts
|
|
396
|
-
function
|
|
677
|
+
function extractFrontmatter2(fileContent) {
|
|
397
678
|
const match = fileContent.match(/^---\n([\s\S]*?)\n---/);
|
|
398
679
|
if (!match) {
|
|
399
680
|
return ["", fileContent];
|
|
@@ -402,7 +683,7 @@ function extractFrontmatter(fileContent) {
|
|
|
402
683
|
const body = fileContent.slice(match[0].length).trim();
|
|
403
684
|
return [frontmatterBlock, body];
|
|
404
685
|
}
|
|
405
|
-
function
|
|
686
|
+
function parseSimpleValue2(raw) {
|
|
406
687
|
const trimmed = raw.trim();
|
|
407
688
|
if (trimmed === "null" || trimmed === "~" || trimmed === "") return null;
|
|
408
689
|
if (trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length >= 2) {
|
|
@@ -416,7 +697,7 @@ function parseSimpleValue(raw) {
|
|
|
416
697
|
function getField(frontmatter, key) {
|
|
417
698
|
const match = frontmatter.match(new RegExp(`^${key}:\\s*(.*)$`, "m"));
|
|
418
699
|
if (!match) return null;
|
|
419
|
-
return
|
|
700
|
+
return parseSimpleValue2(match[1]);
|
|
420
701
|
}
|
|
421
702
|
function getNestedField(frontmatter, parent, key) {
|
|
422
703
|
const parentRegex = new RegExp(`^${parent}:\\s*\\n((?:\\s+.*\\n?)*)`, "m");
|
|
@@ -425,7 +706,7 @@ function getNestedField(frontmatter, parent, key) {
|
|
|
425
706
|
const block = parentMatch[1];
|
|
426
707
|
const fieldMatch = block.match(new RegExp(`^\\s+${key}:\\s*(.*)$`, "m"));
|
|
427
708
|
if (!fieldMatch) return null;
|
|
428
|
-
return
|
|
709
|
+
return parseSimpleValue2(fieldMatch[1]);
|
|
429
710
|
}
|
|
430
711
|
function parseListField(frontmatter, fieldName) {
|
|
431
712
|
const inlineMatch = frontmatter.match(new RegExp(`^${fieldName}:\\s*\\[\\s*\\]`, "m"));
|
|
@@ -450,7 +731,7 @@ function unquoteYamlString(value) {
|
|
|
450
731
|
return value;
|
|
451
732
|
}
|
|
452
733
|
function parseProject(fileContent) {
|
|
453
|
-
const [fm, body] =
|
|
734
|
+
const [fm, body] = extractFrontmatter2(fileContent);
|
|
454
735
|
const slug = getField(fm, "slug") ?? getField(fm, "mission") ?? "";
|
|
455
736
|
return {
|
|
456
737
|
id: getField(fm, "id") ?? "",
|
|
@@ -465,12 +746,12 @@ function parseProject(fileContent) {
|
|
|
465
746
|
tags: parseListField(fm, "tags"),
|
|
466
747
|
workspace: getField(fm, "workspace"),
|
|
467
748
|
repositories: parseListField(fm, "repositories").map(unquoteYamlString),
|
|
468
|
-
externalIds:
|
|
749
|
+
externalIds: parseExternalIds2(fm),
|
|
469
750
|
body
|
|
470
751
|
};
|
|
471
752
|
}
|
|
472
753
|
function parseStatus(fileContent) {
|
|
473
|
-
const [fm, body] =
|
|
754
|
+
const [fm, body] = extractFrontmatter2(fileContent);
|
|
474
755
|
const progress = { total: 0 };
|
|
475
756
|
const progressMatch = fm.match(/^progress:\s*\n((?:\s+.*\n?)*)/m);
|
|
476
757
|
if (progressMatch) {
|
|
@@ -494,7 +775,7 @@ function parseStatus(fileContent) {
|
|
|
494
775
|
body
|
|
495
776
|
};
|
|
496
777
|
}
|
|
497
|
-
function
|
|
778
|
+
function parseExternalIds2(frontmatter) {
|
|
498
779
|
const inlineMatch = frontmatter.match(/^externalIds:\s*\[\s*\]/m);
|
|
499
780
|
if (inlineMatch) return [];
|
|
500
781
|
const results = [];
|
|
@@ -511,7 +792,7 @@ function parseExternalIds(frontmatter) {
|
|
|
511
792
|
if (colonIdx < 0) continue;
|
|
512
793
|
const key = line.slice(0, colonIdx).trim().replace(/^-\s+/, "");
|
|
513
794
|
if (!key) continue;
|
|
514
|
-
entry[key] =
|
|
795
|
+
entry[key] = parseSimpleValue2(line.slice(colonIdx + 1));
|
|
515
796
|
}
|
|
516
797
|
if (entry["system"] && entry["id"]) {
|
|
517
798
|
results.push({
|
|
@@ -523,7 +804,7 @@ function parseExternalIds(frontmatter) {
|
|
|
523
804
|
}
|
|
524
805
|
return results;
|
|
525
806
|
}
|
|
526
|
-
function
|
|
807
|
+
function parseStatusHistory2(frontmatter) {
|
|
527
808
|
if (/^statusHistory:\s*\[\s*\]/m.test(frontmatter)) return [];
|
|
528
809
|
const headerMatch = frontmatter.match(/^statusHistory:\s*$/m);
|
|
529
810
|
if (!headerMatch) return [];
|
|
@@ -549,7 +830,7 @@ function parseStatusHistory(frontmatter) {
|
|
|
549
830
|
if (colonIdx < 0) continue;
|
|
550
831
|
const key = line.slice(0, colonIdx).trim().replace(/^-\s+/, "");
|
|
551
832
|
if (!key) continue;
|
|
552
|
-
entry[key] =
|
|
833
|
+
entry[key] = parseSimpleValue2(line.slice(colonIdx + 1));
|
|
553
834
|
}
|
|
554
835
|
if (!entry["to"]) continue;
|
|
555
836
|
const result = {
|
|
@@ -568,7 +849,7 @@ function parseStatusHistory(frontmatter) {
|
|
|
568
849
|
}
|
|
569
850
|
return results;
|
|
570
851
|
}
|
|
571
|
-
function
|
|
852
|
+
function parseFactsMap2(frontmatter) {
|
|
572
853
|
const headerMatch = frontmatter.match(/^facts:\s*$/m);
|
|
573
854
|
if (!headerMatch) return {};
|
|
574
855
|
const headerStart = headerMatch.index ?? frontmatter.indexOf(headerMatch[0]);
|
|
@@ -581,13 +862,13 @@ function parseFactsMap(frontmatter) {
|
|
|
581
862
|
if (colonIdx < 0) continue;
|
|
582
863
|
const key = line.slice(0, colonIdx).trim();
|
|
583
864
|
if (!key) continue;
|
|
584
|
-
const value =
|
|
865
|
+
const value = parseSimpleValue2(line.slice(colonIdx + 1));
|
|
585
866
|
if (value === null) continue;
|
|
586
867
|
out[key] = value;
|
|
587
868
|
}
|
|
588
869
|
return out;
|
|
589
870
|
}
|
|
590
|
-
function
|
|
871
|
+
function parseAttestations2(frontmatter) {
|
|
591
872
|
if (/^attestations:\s*\[\s*\]/m.test(frontmatter)) return [];
|
|
592
873
|
const headerMatch = frontmatter.match(/^attestations:\s*$/m);
|
|
593
874
|
if (!headerMatch) return [];
|
|
@@ -613,7 +894,7 @@ function parseAttestations(frontmatter) {
|
|
|
613
894
|
if (colonIdx < 0) continue;
|
|
614
895
|
const key = line.slice(0, colonIdx).trim().replace(/^-\s+/, "");
|
|
615
896
|
if (!key) continue;
|
|
616
|
-
entry[key] =
|
|
897
|
+
entry[key] = parseSimpleValue2(line.slice(colonIdx + 1));
|
|
617
898
|
}
|
|
618
899
|
const verdict = entry["verdict"];
|
|
619
900
|
if (!entry["fact"] || !entry["actor"] || !verdict || !entry["at"]) continue;
|
|
@@ -633,7 +914,7 @@ function parseAttestations(frontmatter) {
|
|
|
633
914
|
return results;
|
|
634
915
|
}
|
|
635
916
|
function parseAssignmentFull(fileContent) {
|
|
636
|
-
const [fm, body] =
|
|
917
|
+
const [fm, body] = extractFrontmatter2(fileContent);
|
|
637
918
|
return {
|
|
638
919
|
id: getField(fm, "id") ?? "",
|
|
639
920
|
slug: getField(fm, "slug") ?? "",
|
|
@@ -653,8 +934,8 @@ function parseAssignmentFull(fileContent) {
|
|
|
653
934
|
branch: getNestedField(fm, "workspace", "branch"),
|
|
654
935
|
parentBranch: getNestedField(fm, "workspace", "parentBranch")
|
|
655
936
|
},
|
|
656
|
-
externalIds:
|
|
657
|
-
statusHistory:
|
|
937
|
+
externalIds: parseExternalIds2(fm),
|
|
938
|
+
statusHistory: parseStatusHistory2(fm),
|
|
658
939
|
tags: parseListField(fm, "tags"),
|
|
659
940
|
archived: getField(fm, "archived") === "true",
|
|
660
941
|
archivedAt: getField(fm, "archivedAt"),
|
|
@@ -688,12 +969,12 @@ function parseAssignmentFull(fileContent) {
|
|
|
688
969
|
at: getNestedField(fm, "override", "at") ?? ""
|
|
689
970
|
};
|
|
690
971
|
})(),
|
|
691
|
-
facts:
|
|
692
|
-
attestations:
|
|
972
|
+
facts: parseFactsMap2(fm),
|
|
973
|
+
attestations: parseAttestations2(fm)
|
|
693
974
|
};
|
|
694
975
|
}
|
|
695
976
|
function parsePlan(fileContent) {
|
|
696
|
-
const [fm, body] =
|
|
977
|
+
const [fm, body] = extractFrontmatter2(fileContent);
|
|
697
978
|
return {
|
|
698
979
|
assignment: getField(fm, "assignment") ?? "",
|
|
699
980
|
status: getField(fm, "status") ?? "",
|
|
@@ -703,7 +984,7 @@ function parsePlan(fileContent) {
|
|
|
703
984
|
};
|
|
704
985
|
}
|
|
705
986
|
function parseScratchpad(fileContent) {
|
|
706
|
-
const [fm, body] =
|
|
987
|
+
const [fm, body] = extractFrontmatter2(fileContent);
|
|
707
988
|
return {
|
|
708
989
|
assignment: getField(fm, "assignment") ?? "",
|
|
709
990
|
updated: getField(fm, "updated") ?? "",
|
|
@@ -711,7 +992,7 @@ function parseScratchpad(fileContent) {
|
|
|
711
992
|
};
|
|
712
993
|
}
|
|
713
994
|
function parseHandoff(fileContent) {
|
|
714
|
-
const [fm, body] =
|
|
995
|
+
const [fm, body] = extractFrontmatter2(fileContent);
|
|
715
996
|
return {
|
|
716
997
|
assignment: getField(fm, "assignment") ?? "",
|
|
717
998
|
handoffCount: parseInt(getField(fm, "handoffCount") ?? "0", 10),
|
|
@@ -720,7 +1001,7 @@ function parseHandoff(fileContent) {
|
|
|
720
1001
|
};
|
|
721
1002
|
}
|
|
722
1003
|
function parseDecisionRecord(fileContent) {
|
|
723
|
-
const [fm, body] =
|
|
1004
|
+
const [fm, body] = extractFrontmatter2(fileContent);
|
|
724
1005
|
return {
|
|
725
1006
|
assignment: getField(fm, "assignment") ?? "",
|
|
726
1007
|
decisionCount: parseInt(getField(fm, "decisionCount") ?? "0", 10),
|
|
@@ -729,7 +1010,7 @@ function parseDecisionRecord(fileContent) {
|
|
|
729
1010
|
};
|
|
730
1011
|
}
|
|
731
1012
|
function parseComments(fileContent) {
|
|
732
|
-
const [fm, body] =
|
|
1013
|
+
const [fm, body] = extractFrontmatter2(fileContent);
|
|
733
1014
|
const entries = [];
|
|
734
1015
|
const sections = body.split(
|
|
735
1016
|
/^## (?=[^\n]*\n\s*\*\*Recorded:\*\*[^\n]*\n\*\*Author:\*\*[^\n]*\n\*\*Type:\*\*\s*(?:question|note|feedback)\b)/m
|
|
@@ -764,7 +1045,7 @@ function parseComments(fileContent) {
|
|
|
764
1045
|
};
|
|
765
1046
|
}
|
|
766
1047
|
function parseProgress(fileContent) {
|
|
767
|
-
const [fm, body] =
|
|
1048
|
+
const [fm, body] = extractFrontmatter2(fileContent);
|
|
768
1049
|
const entries = [];
|
|
769
1050
|
const sections = body.split(/^## /m).slice(1);
|
|
770
1051
|
for (const section of sections) {
|
|
@@ -783,7 +1064,7 @@ function parseProgress(fileContent) {
|
|
|
783
1064
|
};
|
|
784
1065
|
}
|
|
785
1066
|
function parsePlaybook(fileContent) {
|
|
786
|
-
const [fm, body] =
|
|
1067
|
+
const [fm, body] = extractFrontmatter2(fileContent);
|
|
787
1068
|
return {
|
|
788
1069
|
slug: getField(fm, "slug") ?? "",
|
|
789
1070
|
name: getField(fm, "name") ?? "",
|
|
@@ -3951,7 +4232,7 @@ async function resolveAssignmentById(projectsDir, assignmentsDir, id) {
|
|
|
3951
4232
|
let workspaceGroup = null;
|
|
3952
4233
|
try {
|
|
3953
4234
|
const content = await readFile6(standalonePath, "utf-8");
|
|
3954
|
-
const [fm] =
|
|
4235
|
+
const [fm] = extractFrontmatter2(content);
|
|
3955
4236
|
workspaceGroup = getField(fm, "workspaceGroup");
|
|
3956
4237
|
} catch {
|
|
3957
4238
|
}
|
|
@@ -3979,7 +4260,7 @@ async function resolveAssignmentById(projectsDir, assignmentsDir, id) {
|
|
|
3979
4260
|
if (!await fileExists(aPath)) continue;
|
|
3980
4261
|
try {
|
|
3981
4262
|
const content = await readFile6(aPath, "utf-8");
|
|
3982
|
-
const [fm] =
|
|
4263
|
+
const [fm] = extractFrontmatter2(content);
|
|
3983
4264
|
const fileId = getField(fm, "id");
|
|
3984
4265
|
if (fileId === id) {
|
|
3985
4266
|
projectMatch = {
|
|
@@ -4322,8 +4603,7 @@ async function areDependenciesSatisfied(projectDir, dependsOn, terminalStatuses)
|
|
|
4322
4603
|
if (!await fileExists(depPath)) return false;
|
|
4323
4604
|
try {
|
|
4324
4605
|
const content = await readFile9(depPath, "utf-8");
|
|
4325
|
-
const
|
|
4326
|
-
const status = m ? m[1].trim() : "";
|
|
4606
|
+
const { status } = parseAssignmentFrontmatter(content);
|
|
4327
4607
|
if (!terminalStatuses.has(status)) return false;
|
|
4328
4608
|
} catch {
|
|
4329
4609
|
return false;
|
|
@@ -4438,6 +4718,7 @@ var init_facts = __esm({
|
|
|
4438
4718
|
init_fs();
|
|
4439
4719
|
init_git_worktree();
|
|
4440
4720
|
init_derive();
|
|
4721
|
+
init_frontmatter();
|
|
4441
4722
|
HTML_COMMENT_RE = /<!--[\s\S]*?-->/g;
|
|
4442
4723
|
PLAN_FILE_RE = /^plan(?:-v(\d+))?\.md$/;
|
|
4443
4724
|
}
|
|
@@ -6565,25 +6846,29 @@ async function resolveSessionPlan(input, terminal) {
|
|
|
6565
6846
|
}
|
|
6566
6847
|
let cwd = session.path;
|
|
6567
6848
|
let fallbackWarning = null;
|
|
6568
|
-
if (session.
|
|
6569
|
-
const detail = await getAssignmentDetail(
|
|
6849
|
+
if (!isExistingDir(session.path)) {
|
|
6850
|
+
const detail = session.projectSlug && session.assignmentSlug ? await getAssignmentDetail(
|
|
6570
6851
|
input.projectsDir,
|
|
6571
6852
|
session.projectSlug,
|
|
6572
6853
|
session.assignmentSlug
|
|
6573
|
-
)
|
|
6854
|
+
) : session.assignmentSlug ? await getAssignmentDetailById(
|
|
6855
|
+
input.projectsDir,
|
|
6856
|
+
input.assignmentsDir,
|
|
6857
|
+
session.assignmentSlug
|
|
6858
|
+
) : null;
|
|
6574
6859
|
if (detail) {
|
|
6575
6860
|
const picked = resolveWorkspaceCwd({
|
|
6576
6861
|
worktreePath: detail.workspace.worktreePath,
|
|
6577
6862
|
repository: detail.workspace.repository,
|
|
6578
6863
|
branch: detail.workspace.branch,
|
|
6579
|
-
assignmentSlug:
|
|
6864
|
+
assignmentSlug: detail.slug
|
|
6580
6865
|
});
|
|
6581
6866
|
if (picked.cwd !== null) {
|
|
6582
6867
|
cwd = picked.cwd;
|
|
6583
6868
|
fallbackWarning = picked.fallbackWarning;
|
|
6584
6869
|
} else {
|
|
6585
6870
|
fallbackWarning = formatFallbackCwdWarning({
|
|
6586
|
-
assignmentSlug:
|
|
6871
|
+
assignmentSlug: detail.slug,
|
|
6587
6872
|
workspaceDir: session.path,
|
|
6588
6873
|
worktreePath: detail.workspace.worktreePath,
|
|
6589
6874
|
branch: detail.workspace.branch
|
|
@@ -6591,6 +6876,12 @@ async function resolveSessionPlan(input, terminal) {
|
|
|
6591
6876
|
}
|
|
6592
6877
|
}
|
|
6593
6878
|
}
|
|
6879
|
+
if (!cwd.trim()) {
|
|
6880
|
+
throw new LaunchError(
|
|
6881
|
+
"workspace-path-invalid",
|
|
6882
|
+
`Session ${input.id} has no recorded working directory and no linked assignment workspace resolved \u2014 refusing to launch in an unknown directory.`
|
|
6883
|
+
);
|
|
6884
|
+
}
|
|
6594
6885
|
const agent = getAgents(input.config).find((a) => a.id === session.agent);
|
|
6595
6886
|
if (!agent) {
|
|
6596
6887
|
throw new LaunchError(
|