thoth-agents 0.3.11 → 0.4.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/README.md +182 -389
- package/dist/agents/prompt-dialects.d.ts +4 -1
- package/dist/agents/prompt-sections.d.ts +2 -1
- package/dist/{chunk-CB3EBA7H.js → chunk-5EBXGMOK.js} +1 -1
- package/dist/chunk-62L3ORXN.js +30 -0
- package/dist/{chunk-GIUU6FNE.js → chunk-Q6SDM4KP.js} +208 -106
- package/dist/chunk-SECDI3TL.js +312 -0
- package/dist/{chunk-ZEAAWBF2.js → chunk-WJ2YMM2E.js} +2877 -290
- package/dist/cli/codex-plugin-install.d.ts +16 -2
- package/dist/cli/index.js +188 -15
- package/dist/cli/install-completion.d.ts +13 -0
- package/dist/cli/install-ledger.d.ts +1 -1
- package/dist/cli/install.d.ts +11 -1
- package/dist/cli/operations/pi.d.ts +43 -0
- package/dist/cli/owned-skills.d.ts +17 -0
- package/dist/cli/pi-effort.d.ts +10 -0
- package/dist/cli/pi-install.d.ts +131 -0
- package/dist/cli/pi-migration.d.ts +12 -0
- package/dist/cli/pi-native-probe.d.ts +34 -0
- package/dist/cli/pi-package-receipt.d.ts +59 -0
- package/dist/cli/pi-paths.d.ts +20 -0
- package/dist/cli/pi-resources.d.ts +15 -0
- package/dist/cli/skills.d.ts +1 -1
- package/dist/cli/tui/index.js +12 -4
- package/dist/cli/tui/operations.d.ts +1 -0
- package/dist/cli/types.d.ts +4 -2
- package/dist/harness/adapters/pi.d.ts +8 -0
- package/dist/harness/core/agent-pack.d.ts +26 -6
- package/dist/harness/core/sdd.d.ts +27 -15
- package/dist/harness/pi-specialists.d.ts +6 -0
- package/dist/harness/types.d.ts +2 -2
- package/dist/harness/writers/codex-plugin-package.d.ts +1 -0
- package/dist/harness/writers/pi-agent.d.ts +16 -0
- package/dist/index.js +6 -4
- package/dist/pi.d.ts +11 -0
- package/dist/pi.js +46 -0
- package/package.json +17 -6
- package/pi/.thoth-agents-assets.json +12 -0
- package/pi/agents/thoth-deep.md +81 -0
- package/pi/agents/thoth-designer.md +81 -0
- package/pi/agents/thoth-explorer.md +81 -0
- package/pi/agents/thoth-librarian.md +83 -0
- package/pi/agents/thoth-oracle.md +83 -0
- package/pi/agents/thoth-quick.md +81 -0
- package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +2 -2
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/agents/oracle.md +3 -3
- package/plugin/agents/orchestrator.md +35 -30
- package/plugin/skills/plan-reviewer/SKILL.md +54 -15
- package/plugin/skills/thoth-archive/SKILL.md +5 -0
- package/plugin/skills/thoth-constitution/SKILL.md +5 -0
- package/plugin/skills/thoth-constitution/templates/constitution.md +19 -2
- package/plugin/skills/thoth-init/SKILL.md +5 -0
- package/plugin/skills/thoth-sdd/SKILL.md +35 -10
- package/plugin/skills/thoth-sdd/references/phases/implement.md +13 -2
- package/plugin/skills/thoth-sdd/references/phases/tasks.md +23 -2
- package/plugin/skills/thoth-sdd/references/phases/verify.md +7 -5
- package/plugin/skills/thoth-sdd/scripts/validate.mjs +263 -30
- package/plugin/skills/thoth-sdd/templates/tasks.md +18 -2
- package/skills/README.md +2 -1
- package/skills/plan-reviewer/SKILL.md +54 -15
- package/skills/thoth-archive/SKILL.md +5 -0
- package/skills/thoth-constitution/SKILL.md +5 -0
- package/skills/thoth-constitution/templates/constitution.md +19 -2
- package/skills/thoth-init/SKILL.md +5 -0
- package/skills/thoth-sdd/SKILL.md +35 -10
- package/skills/thoth-sdd/references/phases/implement.md +13 -2
- package/skills/thoth-sdd/references/phases/tasks.md +23 -2
- package/skills/thoth-sdd/references/phases/verify.md +7 -5
- package/skills/thoth-sdd/scripts/validate.mjs +263 -30
- package/skills/thoth-sdd/templates/tasks.md +18 -2
- package/.agents/plugins/marketplace.json +0 -20
- package/.claude-plugin/marketplace.json +0 -21
|
@@ -22,6 +22,27 @@ not justify artificial implementation tasks.
|
|
|
22
22
|
|
|
23
23
|
Order test-first work before its implementation, group tasks by independently
|
|
24
24
|
deliverable story, identify the MVP, and state dependencies. `[P]` is permitted
|
|
25
|
-
only
|
|
26
|
-
|
|
25
|
+
only for tasks assigned to a declared lane whose mutable path union does not
|
|
26
|
+
overlap another lane in the same group. If there is no safe parallel work, use
|
|
27
27
|
`- None: <evidence-backed reason>` instead. Avoid ceremonial tasks.
|
|
28
|
+
|
|
29
|
+
## Parallel execution
|
|
30
|
+
|
|
31
|
+
Declare safe work with this exact grammar:
|
|
32
|
+
|
|
33
|
+
### Group P1
|
|
34
|
+
|
|
35
|
+
- Lane L1: T001 -> T002 | Owner: deep
|
|
36
|
+
- Lane L2: T003 -> T004 | Owner: quick
|
|
37
|
+
- Prerequisites: None
|
|
38
|
+
- Barrier: Final verification
|
|
39
|
+
- Rationale: Both lane path sets are disjoint and neither lane consumes peer output.
|
|
40
|
+
|
|
41
|
+
Groups and lanes are sequential and unique. Every `[P]` task belongs to exactly one lane; non-`[P]` tasks do not. Lane surfaces are the union of exact task
|
|
42
|
+
paths, and lanes in a group have disjoint surfaces and no cross-lane dependency.
|
|
43
|
+
The `Rationale` must explicitly state path-disjointness and cross-lane dependency
|
|
44
|
+
evidence so structural validation can gate the evidence shape and Oracle can
|
|
45
|
+
judge whether the claim is true.
|
|
46
|
+
Prerequisites name known tasks outside the group; the barrier is a downstream
|
|
47
|
+
task or `Final verification` after all lane members. If no group exists, use
|
|
48
|
+
only `- None: <evidence-backed reason>` and no task may use `[P]`.
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# Verify contract
|
|
2
2
|
|
|
3
|
-
**Owner**:
|
|
3
|
+
**Owner**: route- and risk-aware; Root for trivial deterministic Direct, otherwise a fresh read-only Oracle
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Every route requires mandatory verification. Trivial deterministic Direct work
|
|
6
|
+
may be verified by Root with focused deterministic checks. Materially risky
|
|
7
|
+
Direct work and Accelerated or Full final verification use a fresh read-only
|
|
8
|
+
Oracle. The implementation writer never approves its own work. Inspect changed
|
|
9
|
+
code and run or validate the smallest sufficient checks.
|
|
8
10
|
|
|
9
11
|
Judge three dimensions separately: **completeness** of accepted scope and
|
|
10
12
|
coverage, **correctness** against behavioral contracts and executed evidence,
|
|
@@ -16,7 +18,7 @@ task.
|
|
|
16
18
|
|
|
17
19
|
Return `pass` or `fail`, compliance matrix, commands/results, stable findings,
|
|
18
20
|
critical issues, warnings, and remediation anchors. For Direct, return the
|
|
19
|
-
verdict in-session. For Accelerated and Full, root persists
|
|
21
|
+
verdict in-session regardless of owner. For Accelerated and Full, root persists Oracle's exact result
|
|
20
22
|
using `<skill-dir>/templates/verify-report.md`, where `<skill-dir>` is the
|
|
21
23
|
directory containing the installed `thoth-sdd/SKILL.md`. Fail routes to converge
|
|
22
24
|
(straight back to implement for Direct); PASS permits closeout and archive for
|
|
@@ -540,6 +540,97 @@ function exactTaskPath(line) {
|
|
|
540
540
|
return normalized.toLowerCase();
|
|
541
541
|
}
|
|
542
542
|
|
|
543
|
+
function taskDependencyEdges(content) {
|
|
544
|
+
return [...content.matchAll(/\bT\d{3}(?:\s*->\s*T\d{3})+\b/g)].flatMap(
|
|
545
|
+
([chain]) => {
|
|
546
|
+
const ids = chain.match(/\bT\d{3}\b/g) ?? [];
|
|
547
|
+
return ids.slice(1).map((target, index) => ({
|
|
548
|
+
source: ids[index],
|
|
549
|
+
target,
|
|
550
|
+
}));
|
|
551
|
+
},
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function parseParallelGroups(content) {
|
|
556
|
+
const lines = content.split(/\r?\n/);
|
|
557
|
+
const headingIndexes = lines
|
|
558
|
+
.map((line, index) => (/^###\s+Group\s+P\d+\s*$/.test(line) ? index : -1))
|
|
559
|
+
.filter((index) => index >= 0);
|
|
560
|
+
const groups = [];
|
|
561
|
+
let valid = headingIndexes.length > 0;
|
|
562
|
+
|
|
563
|
+
if (
|
|
564
|
+
lines
|
|
565
|
+
.slice(0, headingIndexes[0] ?? lines.length)
|
|
566
|
+
.some((line) => line.trim())
|
|
567
|
+
) {
|
|
568
|
+
valid = false;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
for (const [groupIndex, start] of headingIndexes.entries()) {
|
|
572
|
+
const end = headingIndexes[groupIndex + 1] ?? lines.length;
|
|
573
|
+
const groupId = /^###\s+Group\s+P(\d+)\s*$/.exec(lines[start])?.[1];
|
|
574
|
+
const body = lines.slice(start + 1, end).filter((line) => line.trim());
|
|
575
|
+
const lanes = [];
|
|
576
|
+
let prerequisites;
|
|
577
|
+
let barrier;
|
|
578
|
+
let rationale;
|
|
579
|
+
for (const line of body) {
|
|
580
|
+
const lane =
|
|
581
|
+
/^- Lane L(\d+): (T\d{3}(?: -> T\d{3})*)(?: \| Owner: (\S+))?\s*$/.exec(
|
|
582
|
+
line,
|
|
583
|
+
);
|
|
584
|
+
if (lane) {
|
|
585
|
+
lanes.push({
|
|
586
|
+
number: Number.parseInt(lane[1], 10),
|
|
587
|
+
taskIds: lane[2].split(' -> '),
|
|
588
|
+
owner: lane[3],
|
|
589
|
+
});
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
const prerequisiteLine =
|
|
593
|
+
/^- Prerequisites: (None|T\d{3}(?:, T\d{3})*)\s*$/.exec(line);
|
|
594
|
+
if (prerequisiteLine && prerequisites === undefined) {
|
|
595
|
+
prerequisites =
|
|
596
|
+
prerequisiteLine[1] === 'None' ? [] : prerequisiteLine[1].split(', ');
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
const barrierLine = /^- Barrier: (Final verification|T\d{3})\s*$/.exec(
|
|
600
|
+
line,
|
|
601
|
+
);
|
|
602
|
+
if (barrierLine && barrier === undefined) {
|
|
603
|
+
barrier = barrierLine[1];
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
const rationaleLine = /^- Rationale: (\S.*)$/.exec(line);
|
|
607
|
+
if (rationaleLine && rationale === undefined) {
|
|
608
|
+
rationale = rationaleLine[1];
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
valid = false;
|
|
612
|
+
}
|
|
613
|
+
if (
|
|
614
|
+
groupId === undefined ||
|
|
615
|
+
lanes.length < 2 ||
|
|
616
|
+
rationale === undefined ||
|
|
617
|
+
!isConcreteEvidence(rationale) ||
|
|
618
|
+
lanes.some((lane, index) => lane.number !== index + 1)
|
|
619
|
+
) {
|
|
620
|
+
valid = false;
|
|
621
|
+
}
|
|
622
|
+
groups.push({
|
|
623
|
+
number: Number.parseInt(groupId ?? '0', 10),
|
|
624
|
+
lanes,
|
|
625
|
+
prerequisites,
|
|
626
|
+
barrier,
|
|
627
|
+
rationale,
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
if (groups.some((group, index) => group.number !== index + 1)) valid = false;
|
|
631
|
+
return { groups, valid };
|
|
632
|
+
}
|
|
633
|
+
|
|
543
634
|
function validateTasks(content, errors, spec) {
|
|
544
635
|
const artifact = 'tasks.md';
|
|
545
636
|
const taskLines = content
|
|
@@ -644,12 +735,6 @@ function validateTasks(content, errors, spec) {
|
|
|
644
735
|
}));
|
|
645
736
|
const tasksById = new Map(taskRecords.map((task) => [task.id, task]));
|
|
646
737
|
const hasParallelTask = taskRecords.some((task) => task.parallel);
|
|
647
|
-
const parallelLines = (parallelSection ?? '')
|
|
648
|
-
.split(/\r?\n/)
|
|
649
|
-
.map((line) => [line, [...new Set(line.match(/\bT\d{3}\b/g) ?? [])]])
|
|
650
|
-
.filter(([, ids]) => ids.length >= 2);
|
|
651
|
-
const referencedTaskIds = new Set(parallelLines.flatMap(([, ids]) => ids));
|
|
652
|
-
const hasParallelExample = parallelLines.length > 0;
|
|
653
738
|
const noParallelMatch = /^-\s+None:\s*(\S.*)$/im.exec(parallelSection ?? '');
|
|
654
739
|
const explainsNoParallelWork =
|
|
655
740
|
noParallelMatch !== null && isConcreteEvidence(noParallelMatch[1]);
|
|
@@ -657,42 +742,190 @@ function validateTasks(content, errors, spec) {
|
|
|
657
742
|
left === right ||
|
|
658
743
|
left.startsWith(`${right}/`) ||
|
|
659
744
|
right.startsWith(`${left}/`);
|
|
660
|
-
const
|
|
661
|
-
|
|
745
|
+
const noneOnly =
|
|
746
|
+
explainsNoParallelWork &&
|
|
747
|
+
parallelSection?.trim() === noParallelMatch?.[0].trim();
|
|
748
|
+
const { groups, valid: validGroupGrammar } = parseParallelGroups(
|
|
749
|
+
parallelSection ?? '',
|
|
662
750
|
);
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
.map((task) => task.id);
|
|
666
|
-
const examplesWithoutParallelTask = parallelLines.some(
|
|
667
|
-
([, ids]) => !ids.some((id) => tasksById.get(id)?.parallel),
|
|
751
|
+
const declaredDependencies = taskDependencyEdges(
|
|
752
|
+
sectionContent(content, 'Dependencies') ?? '',
|
|
668
753
|
);
|
|
669
|
-
const
|
|
670
|
-
const paths = ids.map((id) => tasksById.get(id)?.path);
|
|
671
|
-
if (paths.some((path) => path === undefined)) return true;
|
|
672
|
-
return paths.some((path, index) =>
|
|
673
|
-
paths.slice(index + 1).some((other) => pathsOverlap(path, other)),
|
|
674
|
-
);
|
|
675
|
-
});
|
|
754
|
+
const hasGroups = groups.length > 0;
|
|
676
755
|
if (
|
|
677
756
|
parallelSection === undefined ||
|
|
678
|
-
(
|
|
679
|
-
(hasParallelTask &&
|
|
680
|
-
|
|
681
|
-
explainsNoParallelWork ||
|
|
682
|
-
unknownReferences.length > 0 ||
|
|
683
|
-
omittedParallelTasks.length > 0 ||
|
|
684
|
-
examplesWithoutParallelTask ||
|
|
685
|
-
overlappingExamples)) ||
|
|
686
|
-
(!hasParallelTask && !explainsNoParallelWork)
|
|
757
|
+
(hasParallelTask && (!hasGroups || explainsNoParallelWork)) ||
|
|
758
|
+
(!hasParallelTask && !noneOnly) ||
|
|
759
|
+
(explainsNoParallelWork && !noneOnly)
|
|
687
760
|
) {
|
|
688
761
|
errors.push(
|
|
689
762
|
issue(
|
|
690
763
|
'SDD-TASK-PARALLEL',
|
|
691
764
|
artifact,
|
|
692
|
-
'
|
|
765
|
+
'Declare strict parallel groups for [P] tasks, or provide one exclusive evidence-backed None reason.',
|
|
766
|
+
),
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
if (hasGroups && !validGroupGrammar) {
|
|
770
|
+
errors.push(
|
|
771
|
+
issue(
|
|
772
|
+
'SDD-TASK-LANE-GRAMMAR',
|
|
773
|
+
artifact,
|
|
774
|
+
'Groups and lanes must use unique sequential IDs, at least two lanes, and every required field.',
|
|
693
775
|
),
|
|
694
776
|
);
|
|
695
777
|
}
|
|
778
|
+
|
|
779
|
+
if (hasGroups && validGroupGrammar) {
|
|
780
|
+
const memberships = groups.flatMap((group) =>
|
|
781
|
+
group.lanes.flatMap((lane) =>
|
|
782
|
+
lane.taskIds.map((taskId) => ({ group, lane, taskId })),
|
|
783
|
+
),
|
|
784
|
+
);
|
|
785
|
+
const membershipCounts = new Map();
|
|
786
|
+
for (const { taskId } of memberships) {
|
|
787
|
+
membershipCounts.set(taskId, (membershipCounts.get(taskId) ?? 0) + 1);
|
|
788
|
+
}
|
|
789
|
+
const invalidMembership =
|
|
790
|
+
memberships.some(({ taskId }) => !tasksById.get(taskId)?.parallel) ||
|
|
791
|
+
taskRecords.some(
|
|
792
|
+
(task) => task.parallel && membershipCounts.get(task.id) !== 1,
|
|
793
|
+
);
|
|
794
|
+
if (invalidMembership) {
|
|
795
|
+
errors.push(
|
|
796
|
+
issue(
|
|
797
|
+
'SDD-TASK-LANE-MEMBERSHIP',
|
|
798
|
+
artifact,
|
|
799
|
+
'Every [P] task must belong to exactly one lane, and lane members must be known [P] tasks.',
|
|
800
|
+
),
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
if (
|
|
805
|
+
groups.some((group) =>
|
|
806
|
+
group.lanes.some(
|
|
807
|
+
(lane) => !['designer', 'quick', 'deep'].includes(lane.owner),
|
|
808
|
+
),
|
|
809
|
+
)
|
|
810
|
+
) {
|
|
811
|
+
errors.push(
|
|
812
|
+
issue(
|
|
813
|
+
'SDD-TASK-LANE-OWNER',
|
|
814
|
+
artifact,
|
|
815
|
+
'Every lane owner must be designer, quick, or deep.',
|
|
816
|
+
),
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
for (const group of groups) {
|
|
821
|
+
const rationale = group.rationale ?? '';
|
|
822
|
+
const hasPathIndependenceEvidence =
|
|
823
|
+
/\b(?:path|file|surface)s?\b/i.test(rationale) &&
|
|
824
|
+
/\b(?:disjoint|non[- ]?overlap(?:ping)?)\b/i.test(rationale);
|
|
825
|
+
const hasDependencyIndependenceEvidence =
|
|
826
|
+
/\b(?:dependenc(?:y|ies)|consum(?:e|es|ing)|peer output|data flow)\b/i.test(
|
|
827
|
+
rationale,
|
|
828
|
+
);
|
|
829
|
+
if (!hasPathIndependenceEvidence || !hasDependencyIndependenceEvidence) {
|
|
830
|
+
errors.push(
|
|
831
|
+
issue(
|
|
832
|
+
'SDD-TASK-LANE-RATIONALE',
|
|
833
|
+
artifact,
|
|
834
|
+
'Parallel rationale must state concrete path-disjointness and cross-lane dependency evidence for Oracle review.',
|
|
835
|
+
),
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
const memberIds = new Set(group.lanes.flatMap((lane) => lane.taskIds));
|
|
840
|
+
const prerequisites = group.prerequisites ?? [];
|
|
841
|
+
if (
|
|
842
|
+
group.prerequisites === undefined ||
|
|
843
|
+
new Set(prerequisites).size !== prerequisites.length ||
|
|
844
|
+
prerequisites.some(
|
|
845
|
+
(taskId) => !tasksById.has(taskId) || memberIds.has(taskId),
|
|
846
|
+
)
|
|
847
|
+
) {
|
|
848
|
+
errors.push(
|
|
849
|
+
issue(
|
|
850
|
+
'SDD-TASK-LANE-PREREQUISITE',
|
|
851
|
+
artifact,
|
|
852
|
+
'Prerequisites must be unique known tasks outside the group.',
|
|
853
|
+
),
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
const memberNumbers = [...memberIds].map((id) =>
|
|
858
|
+
Number.parseInt(id.slice(1), 10),
|
|
859
|
+
);
|
|
860
|
+
const barrierNumber = /^T\d{3}$/.test(group.barrier ?? '')
|
|
861
|
+
? Number.parseInt(group.barrier.slice(1), 10)
|
|
862
|
+
: undefined;
|
|
863
|
+
if (
|
|
864
|
+
group.barrier !== 'Final verification' &&
|
|
865
|
+
(barrierNumber === undefined ||
|
|
866
|
+
!tasksById.has(group.barrier) ||
|
|
867
|
+
memberIds.has(group.barrier) ||
|
|
868
|
+
prerequisites.includes(group.barrier) ||
|
|
869
|
+
memberNumbers.some((number) => barrierNumber <= number))
|
|
870
|
+
) {
|
|
871
|
+
errors.push(
|
|
872
|
+
issue(
|
|
873
|
+
'SDD-TASK-LANE-BARRIER',
|
|
874
|
+
artifact,
|
|
875
|
+
'A task barrier must be a known downstream non-member task, or use exact Final verification.',
|
|
876
|
+
),
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
const laneByTask = new Map(
|
|
881
|
+
group.lanes.flatMap((lane) =>
|
|
882
|
+
lane.taskIds.map((taskId) => [taskId, lane.number]),
|
|
883
|
+
),
|
|
884
|
+
);
|
|
885
|
+
if (
|
|
886
|
+
declaredDependencies.some(
|
|
887
|
+
({ source, target }) =>
|
|
888
|
+
laneByTask.has(source) &&
|
|
889
|
+
laneByTask.has(target) &&
|
|
890
|
+
laneByTask.get(source) !== laneByTask.get(target),
|
|
891
|
+
)
|
|
892
|
+
) {
|
|
893
|
+
errors.push(
|
|
894
|
+
issue(
|
|
895
|
+
'SDD-TASK-LANE-DEPENDENCY',
|
|
896
|
+
artifact,
|
|
897
|
+
'Declared dependencies cannot connect different lanes in one group.',
|
|
898
|
+
),
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
const lanePaths = group.lanes.map((lane) =>
|
|
903
|
+
lane.taskIds.map((taskId) => tasksById.get(taskId)?.path),
|
|
904
|
+
);
|
|
905
|
+
const overlaps = lanePaths.some((paths, index) =>
|
|
906
|
+
lanePaths
|
|
907
|
+
.slice(index + 1)
|
|
908
|
+
.some((otherPaths) =>
|
|
909
|
+
paths.some(
|
|
910
|
+
(path) =>
|
|
911
|
+
path !== undefined &&
|
|
912
|
+
otherPaths.some(
|
|
913
|
+
(other) => other !== undefined && pathsOverlap(path, other),
|
|
914
|
+
),
|
|
915
|
+
),
|
|
916
|
+
),
|
|
917
|
+
);
|
|
918
|
+
if (overlaps) {
|
|
919
|
+
errors.push(
|
|
920
|
+
issue(
|
|
921
|
+
'SDD-TASK-LANE-OVERLAP',
|
|
922
|
+
artifact,
|
|
923
|
+
'Mutable task paths cannot overlap across lanes in one group.',
|
|
924
|
+
),
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
696
929
|
}
|
|
697
930
|
|
|
698
931
|
function validateChecklist(content, errors, spec, requireComplete) {
|
|
@@ -32,8 +32,24 @@ for them.
|
|
|
32
32
|
|
|
33
33
|
## Parallel execution
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
Use this exact grammar when safe parallel work exists:
|
|
36
|
+
|
|
37
|
+
### Group P1
|
|
38
|
+
|
|
39
|
+
- Lane L1: T001 -> T002 | Owner: deep
|
|
40
|
+
- Lane L2: T003 -> T004 | Owner: quick
|
|
41
|
+
- Prerequisites: None
|
|
42
|
+
- Barrier: Final verification
|
|
43
|
+
- Rationale: Both lane path sets are disjoint and neither lane consumes peer output.
|
|
44
|
+
|
|
45
|
+
Groups and lanes are sequential and unique. Every `[P]` task belongs to exactly one lane; non-`[P]` tasks do not. Lane surfaces are the union of exact task
|
|
46
|
+
paths, and lanes in a group have disjoint surfaces and no cross-lane dependency.
|
|
47
|
+
The `Rationale` must explicitly state path-disjointness and cross-lane dependency
|
|
48
|
+
evidence so structural validation can gate the evidence shape and Oracle can
|
|
49
|
+
judge whether the claim is true.
|
|
50
|
+
Prerequisites name known tasks outside the group; the barrier is a downstream
|
|
51
|
+
task or `Final verification` after all lane members. If no group exists, use
|
|
52
|
+
only `- None: <evidence-backed reason>` and no task may use `[P]`.
|
|
37
53
|
|
|
38
54
|
<!-- PARALLEL-EXECUTION-EVIDENCE -->
|
|
39
55
|
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "thoth-agents",
|
|
3
|
-
"interface": {
|
|
4
|
-
"displayName": "thoth-agents Adaptive Orchestration"
|
|
5
|
-
},
|
|
6
|
-
"plugins": [
|
|
7
|
-
{
|
|
8
|
-
"name": "thoth-agents",
|
|
9
|
-
"source": {
|
|
10
|
-
"source": "local",
|
|
11
|
-
"path": "./plugin"
|
|
12
|
-
},
|
|
13
|
-
"policy": {
|
|
14
|
-
"installation": "AVAILABLE",
|
|
15
|
-
"authentication": "ON_INSTALL"
|
|
16
|
-
},
|
|
17
|
-
"category": "Productivity"
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
|
|
3
|
-
"name": "thoth-agents",
|
|
4
|
-
"description": "Adaptive orchestration with seven roles and runtime-autonomous direct, accelerated, and full Spec Kit-compatible SDD routes.",
|
|
5
|
-
"owner": {
|
|
6
|
-
"name": "thoth-agents maintainers"
|
|
7
|
-
},
|
|
8
|
-
"plugins": [
|
|
9
|
-
{
|
|
10
|
-
"name": "thoth-agents",
|
|
11
|
-
"description": "Adaptive root orchestration, six specialist subagents, and a runtime-autonomous Spec Kit-compatible SDD bundle.",
|
|
12
|
-
"version": "0.3.11",
|
|
13
|
-
"author": {
|
|
14
|
-
"name": "thoth-agents maintainers"
|
|
15
|
-
},
|
|
16
|
-
"source": "./plugin",
|
|
17
|
-
"category": "productivity",
|
|
18
|
-
"homepage": "https://github.com/EremesNG/thoth-agents"
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
}
|