thoth-agents 0.3.10 → 0.3.12
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 +119 -33
- package/dist/{chunk-TKIDBRM3.js → chunk-5UBJB5QO.js} +4 -1
- package/dist/{chunk-M2WF46BP.js → chunk-DX4U3AD3.js} +387 -231
- package/dist/{chunk-JBG7XMIG.js → chunk-VPVBYBPU.js} +602 -180
- package/dist/cli/codex-plugin-install.d.ts +16 -2
- package/dist/cli/index.js +7 -5
- package/dist/cli/tui/index.js +2 -2
- package/dist/config/constants.d.ts +3 -3
- package/dist/harness/adapters/claude-code.d.ts +8 -0
- package/dist/harness/adapters/codex-surfaces.d.ts +2 -2
- package/dist/harness/core/agent-pack.d.ts +60 -5
- package/dist/harness/core/sdd.d.ts +32 -19
- package/dist/harness/writers/codex-plugin-package.d.ts +1 -0
- package/dist/index.js +2 -2
- package/package.json +4 -4
- package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +7 -7
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/agents/deep.md +10 -31
- package/plugin/agents/designer.md +10 -31
- package/plugin/agents/explorer.md +10 -30
- package/plugin/agents/librarian.md +10 -30
- package/plugin/agents/oracle.md +11 -31
- package/plugin/agents/orchestrator.md +48 -35
- package/plugin/agents/quick.md +10 -31
- package/plugin/skills/plan-reviewer/SKILL.md +54 -15
- package/plugin/skills/thoth-archive/SKILL.md +5 -0
- package/plugin/skills/thoth-archive/scripts/archive.mjs +30 -10
- 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 +48 -11
- package/plugin/skills/thoth-sdd/references/phases/implement.md +44 -6
- 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-archive/scripts/archive.mjs +30 -10
- 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 +48 -11
- package/skills/thoth-sdd/references/phases/implement.md +44 -6
- 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
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: thoth-sdd
|
|
3
|
-
description: Run thoth-agents Direct, Accelerated, or Full specification-driven development with Spec Kit-grade artifacts, OpenSpec-style durable deltas, fast-forward planning, and
|
|
3
|
+
description: Run thoth-agents Direct, Accelerated, or Full specification-driven development with Spec Kit-grade artifacts, OpenSpec-style durable deltas, fast-forward planning, and proportional independent verification.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Requires Node.js >=22.13 for bundled validation scripts.
|
|
6
|
+
metadata:
|
|
7
|
+
author: thoth-agents
|
|
8
|
+
version: "1.0"
|
|
4
9
|
---
|
|
5
10
|
|
|
6
11
|
# Thoth SDD
|
|
@@ -18,21 +23,53 @@ intent is clear and risk is low.
|
|
|
18
23
|
|
|
19
24
|
Accelerated is a **fast-forward** route: root writes `spec.md`, `plan.md`, and
|
|
20
25
|
`tasks.md` in one uninterrupted pass and creates optional artifacts only for a
|
|
21
|
-
concrete risk. After `ready`, both artifact-backed routes
|
|
26
|
+
concrete risk. After `ready`, both artifact-backed routes offer
|
|
22
27
|
`Review plan with Oracle (Recommended)` or `Proceed without review`. Full uses
|
|
23
28
|
separate planning gates because uncertainty or failure cost justifies them.
|
|
24
29
|
|
|
25
30
|
An explicitly named route counts as the user's selection. Otherwise assess and
|
|
26
|
-
recommend Direct, Accelerated, or Full,
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
recommend Direct, Accelerated, or Full, first summarize the relevant request
|
|
32
|
+
context, scope, clarity, risk, and why the recommendation fits, then ask. When a
|
|
33
|
+
native route question returns answerless, make at most three total attempts;
|
|
34
|
+
after the third answerless result, treat the recommended route as selected. Any
|
|
35
|
+
explicit answer wins. A generic request to “use SDD” makes Accelerated the
|
|
36
|
+
minimum recommendation but does not force it.
|
|
37
|
+
|
|
38
|
+
At the post-`ready` review choice, an explicit answer wins, including
|
|
39
|
+
`Proceed without review`. When the native question returns answerless, make at
|
|
40
|
+
most three total attempts; after the third answerless result, treat
|
|
41
|
+
`Review plan with Oracle (Recommended)` as selected. Once review is selected,
|
|
42
|
+
repair actionable same-intent planning blockers, revalidate affected gates, and
|
|
43
|
+
use a fresh Oracle for every new approval round until `[OKAY]`; stop instead on
|
|
44
|
+
a material human-owned blocker.
|
|
45
|
+
|
|
46
|
+
These bounded fallbacks apply only to the route, plan-review, and implementation
|
|
47
|
+
questions. Never apply them to secrets, destructive or security-sensitive
|
|
48
|
+
actions, or material human-owned product or architecture decisions.
|
|
29
49
|
|
|
30
50
|
## Ownership
|
|
31
51
|
|
|
32
52
|
- Root owns sequential coordination artifacts, gate execution, and archive.
|
|
33
53
|
- Explorer owns Full-route repository discovery.
|
|
34
|
-
-
|
|
35
|
-
|
|
54
|
+
- SDD routes govern artifacts and gates, not implementation ownership. Root,
|
|
55
|
+
`designer`, `quick`, or `deep` may implement in Direct, Accelerated, or Full.
|
|
56
|
+
- Root decides ownership from explicit safe user direction and demonstrated net
|
|
57
|
+
gain. Delegation benefits include specialization, context isolation,
|
|
58
|
+
independent bounded work, quality, latency, or total cost; root continuity
|
|
59
|
+
benefits include short or sequential work, shared mutable state, accumulated
|
|
60
|
+
context, rediscovery, and coordination overhead. Route, file count, or cheaper
|
|
61
|
+
model price alone never selects an owner.
|
|
62
|
+
- Only after deciding to delegate implementation, select `designer` for UI/UX,
|
|
63
|
+
`quick` for known narrow low-risk work, or `deep` for coupled, edge-case-heavy,
|
|
64
|
+
migration, concurrency, shared-contract, or high-risk work.
|
|
65
|
+
- Each mutable surface has one writer; independent non-overlapping surfaces may
|
|
66
|
+
split, while coupled surfaces use one `deep` writer and ordered handoffs.
|
|
67
|
+
- Oracle owns `plan-review` when review is explicitly selected or chosen by the
|
|
68
|
+
bounded recommended fallback. Every route requires
|
|
69
|
+
mandatory verification, but final-verification ownership is proportional:
|
|
70
|
+
trivial deterministic Direct work may be verified by Root when Root is not
|
|
71
|
+
self-approving its own implementation; materially risky Direct work and every
|
|
72
|
+
Accelerated or Full final verify require a fresh read-only Oracle. The
|
|
36
73
|
implementation writer never approves its own work.
|
|
37
74
|
|
|
38
75
|
## Progressive loading
|
|
@@ -78,10 +115,10 @@ node "<skill-dir>/scripts/validate.mjs" --change openspec/changes/<feature> --ro
|
|
|
78
115
|
- **Checklist**: run only when activated; the later `ready` gate includes it if
|
|
79
116
|
present.
|
|
80
117
|
|
|
81
|
-
`ready` validates the artifacts needed before the
|
|
82
|
-
`Review plan with Oracle (Recommended)`
|
|
83
|
-
approval remains separate from implementation confirmation and never
|
|
84
|
-
final verification.
|
|
118
|
+
`ready` validates the artifacts needed before the explicit or bounded-default
|
|
119
|
+
`Review plan with Oracle (Recommended)` / `Proceed without review` choice.
|
|
120
|
+
Review approval remains separate from implementation confirmation and never
|
|
121
|
+
satisfies final verification.
|
|
85
122
|
`closeout` additionally requires completed tasks, independent oracle PASS,
|
|
86
123
|
complete FR/buildable-SC evidence, an observed PASS or explicit residual RISK
|
|
87
124
|
for every outcome SC, and an archive report ready for the transactional archive
|
|
@@ -1,12 +1,42 @@
|
|
|
1
1
|
# Implement contract
|
|
2
2
|
|
|
3
|
-
**Owner**: root, designer
|
|
3
|
+
**Owner**: adaptive root, `designer`, `quick`, or `deep` in every route; exactly
|
|
4
|
+
one writer per mutable surface
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
SDD routes govern artifacts and gates, not implementation ownership. Before
|
|
7
|
+
implementation or dispatch, root records the decided owner, task-shape/net-gain
|
|
8
|
+
rationale, exact paths, accepted FR/buildable-SC scope, non-goals, and
|
|
9
|
+
verification commands. Route, file count, or cheaper model price alone is not an
|
|
10
|
+
ownership rationale.
|
|
11
|
+
|
|
12
|
+
Root may retain implementation when short or sequential work, shared mutable
|
|
13
|
+
state, accumulated context, rediscovery, or coordination overhead outweighs
|
|
14
|
+
delegation benefit. Delegate when specialization, context isolation, independent
|
|
15
|
+
bounded work, quality, latency, or total cost creates demonstrated net gain. If
|
|
16
|
+
root owns the surface, do not dispatch a writer. If a specialist owns it, send a
|
|
17
|
+
bounded handoff with the exact surface, requirements, and checks.
|
|
18
|
+
|
|
19
|
+
Root marks selected artifact-backed tasks `[~]`; Direct or no-artifact work has
|
|
20
|
+
no task state. Use the mandatory `tdd` skill for behavior changes and work in
|
|
21
|
+
vertical red/green slices. Child writers never edit task state; root marks `[x]`
|
|
22
|
+
only after checking task-specific evidence.
|
|
23
|
+
|
|
24
|
+
After deciding delegation creates net gain, select deterministically:
|
|
25
|
+
|
|
26
|
+
- `designer` for user-facing UI/UX, interaction, accessibility, responsive, or
|
|
27
|
+
visual-quality work;
|
|
28
|
+
- `quick` for a known narrow mechanical low-risk surface with exact targets;
|
|
29
|
+
- `deep` for coupled multi-file, shared-contract, migration, concurrency,
|
|
30
|
+
edge-case-heavy, or high-risk work.
|
|
31
|
+
|
|
32
|
+
Proven independent surfaces may use different writers only with non-overlapping
|
|
33
|
+
ownership. Overlapping or compatibility-coupled work uses one `deep` writer and
|
|
34
|
+
ordered handoffs. A writer escalates before expanding beyond its routing
|
|
35
|
+
boundary. Every route requires mandatory verification, and the implementation
|
|
36
|
+
writer never approves its own work. For trivial deterministic Direct work, Root
|
|
37
|
+
may run the proportionate focused checks when Root is not self-approving its own
|
|
38
|
+
implementation. For materially risky Direct work and every Accelerated or Full
|
|
39
|
+
final verify, root hands the unchanged candidate to a fresh read-only Oracle.
|
|
10
40
|
|
|
11
41
|
Implementation evidence may refine an artifact without restarting the workflow:
|
|
12
42
|
|
|
@@ -17,3 +47,11 @@ Implementation evidence may refine an artifact without restarting the workflow:
|
|
|
17
47
|
silently expanding this one.
|
|
18
48
|
|
|
19
49
|
Report files changed, checks executed, deviations, and remaining work.
|
|
50
|
+
|
|
51
|
+
## Native dispatch groups and waves
|
|
52
|
+
|
|
53
|
+
For each ready group, confirm prerequisites, ordered lane tasks, exact path
|
|
54
|
+
union, owner, requirements, and checks. Select the capacity-bounded set of
|
|
55
|
+
undispatched ready lanes and create one fresh native specialist assignment per admitted lane. Issue every dispatch in that native wave before any wait, status,
|
|
56
|
+
result collection, or root implementation action. Retain handles; when terminal evidence frees capacity, dispatch the next undispatched ready lane before waiting again. Validate terminal evidence per lane, while root alone updates task state. Cross the declared barrier only after every lane is terminal and reconciled. Preserve truthful capability/capacity fallback: when native
|
|
57
|
+
concurrency is unavailable or width is one, use a truthful sequential fallback.
|
|
@@ -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.10",
|
|
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
|
-
}
|