sdd-agent-platform 0.1.0 → 0.2.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 +144 -310
- package/dist/packages/cli/src/main.js +1174 -309
- package/dist/packages/cli/src/main.js.map +1 -1
- package/dist/packages/cli/src/options.d.ts +4 -0
- package/dist/packages/cli/src/options.js +35 -0
- package/dist/packages/cli/src/options.js.map +1 -0
- package/dist/packages/core/src/ai-tools.d.ts +19 -2
- package/dist/packages/core/src/ai-tools.js +112 -21
- package/dist/packages/core/src/ai-tools.js.map +1 -1
- package/dist/packages/core/src/index.d.ts +739 -4
- package/dist/packages/core/src/index.js +3800 -220
- package/dist/packages/core/src/index.js.map +1 -1
- package/dist/packages/core/src/instructions.js +35 -34
- package/dist/packages/core/src/instructions.js.map +1 -1
- package/dist/packages/core/src/path-safety.d.ts +4 -0
- package/dist/packages/core/src/path-safety.js +35 -0
- package/dist/packages/core/src/path-safety.js.map +1 -0
- package/package.json +1 -1
|
@@ -2,25 +2,26 @@ import { SDD_VERSION } from './ai-tools.js';
|
|
|
2
2
|
export const SDD_INSTRUCTIONS_CONTRACT = 'sdd-instructions-v1';
|
|
3
3
|
const INSTRUCTION_PAYLOADS = {
|
|
4
4
|
overview: {
|
|
5
|
-
summary: '
|
|
6
|
-
requiredCommands: ['sdd status', 'sdd
|
|
5
|
+
summary: 'Route natural-language SDD intent from branch/source status to task execution, agent evidence, partition-aware verification, and explicit sync-back while keeping CLI/core output as source of truth.',
|
|
6
|
+
requiredCommands: ['sdd status', 'sdd lifecycle decide --from-text <text>', 'sdd doctor', 'sdd tasks inspect <task_id>', 'sdd do task <task_id>', 'sdd verify task <task_id> [--branch <branch>] [--run <run_id>]', 'sdd sync-back inspect [<run_id>] --task <task_id>'],
|
|
7
7
|
allowedSideEffects: ['read .sdd state', 'read specs documents', 'read generated AI entries'],
|
|
8
8
|
forbiddenSideEffects: ['background write', 'worktree creation', 'auto commit', 'force push', 'unapproved complex sync-back apply'],
|
|
9
9
|
nextSteps: [
|
|
10
|
-
'
|
|
11
|
-
'
|
|
10
|
+
'Treat /sdd as a natural-language intent router, then run sdd status first to see branch/source context and the recommended next command; report only workflow state, blocker/current task, and next action unless the user asks for full detail.',
|
|
11
|
+
'Dynamic routing comes from CLI/core output; follow the recommended next command and do not infer dynamic state from generated markdown.',
|
|
12
|
+
'If intent remains ambiguous after status, ask one clarifying question before spec/plan/do/verify/sync-back work.',
|
|
12
13
|
'If status reports generated entry drift or missing config, run sdd doctor and sdd update before do/verify.',
|
|
13
|
-
'If status recommends a pending task, run sdd tasks inspect <task_id> and execute only the approved task boundary
|
|
14
|
-
'
|
|
15
|
-
'After verify PASS, run sdd sync-back inspect
|
|
14
|
+
'If status recommends a pending task, run sdd tasks inspect <task_id> and execute only the approved task boundary; scout/implementer/reviewer/validator participation should be recorded as artifacts rather than hidden in the main chat.',
|
|
15
|
+
'For verify and sync-back, omit --run by default so CLI resolves the latest eligible run from partition + task id; pass --run only for replay, CI, or old-run inspection.',
|
|
16
|
+
'After verify PASS, run sdd sync-back inspect --task <task_id>; direct-safe tasks may apply directly, while confirm-required tasks need sdd sync-back apply --approved after human confirmation.'
|
|
16
17
|
]
|
|
17
18
|
},
|
|
18
19
|
init: {
|
|
19
|
-
summary: 'Initialize .sdd project configuration
|
|
20
|
-
requiredCommands: ['sdd init --ai claude-code', 'sdd status', 'sdd doctor'],
|
|
21
|
-
allowedSideEffects: ['write .sdd/project.yml', 'write .sdd/runs', 'write
|
|
22
|
-
forbiddenSideEffects: ['
|
|
23
|
-
nextSteps: ['Run sdd init --ai claude-code.', 'Run sdd status to inspect
|
|
20
|
+
summary: 'Initialize .sdd project configuration and managed AI tool entries for the current repository; workflow partition documents are entered through /sdd:spec.',
|
|
21
|
+
requiredCommands: ['sdd init --ai claude-code', 'sdd status', '/sdd:spec', 'sdd doctor'],
|
|
22
|
+
allowedSideEffects: ['write .sdd/project.yml', 'write .sdd/runs', 'write managed generated AI entries'],
|
|
23
|
+
forbiddenSideEffects: ['create workflow partition documents unless explicitly using /sdd:spec or legacy --scaffold-docs', 'overwrite foreign AI entry files', 'background write', 'auto commit'],
|
|
24
|
+
nextSteps: ['Run sdd init --ai claude-code.', 'Run sdd status to inspect current Git branch partition state and the recommended next command.', 'Use /sdd:spec to create or refine specs/<partition>/spec.md; omitted --branch uses the current Git branch, explicit --branch uses the requested partition.', 'Run sdd doctor after initialization.']
|
|
24
25
|
},
|
|
25
26
|
doctor: {
|
|
26
27
|
summary: 'Check project config, scoped runtime evidence, and generated AI entry drift.',
|
|
@@ -37,39 +38,39 @@ const INSTRUCTION_PAYLOADS = {
|
|
|
37
38
|
nextSteps: ['Run sdd update.', 'Run sdd doctor to verify drift is resolved.']
|
|
38
39
|
},
|
|
39
40
|
spec: {
|
|
40
|
-
summary: 'Create
|
|
41
|
-
requiredCommands: ['sdd lifecycle decide', 'read specs/<
|
|
42
|
-
allowedSideEffects: ['read project context', 'read
|
|
43
|
-
forbiddenSideEffects: ['implement code', 'silently advance to plan', 'auto commit'],
|
|
44
|
-
nextSteps: ['Clarify user intent and
|
|
41
|
+
summary: 'Create or refine specs/<partition>/spec.md as the workflow partition entry: omitted --branch uses the current Git branch, explicit --branch uses the requested branch partition.',
|
|
42
|
+
requiredCommands: ['sdd status', 'sdd lifecycle decide --from-text <text>', 'read specs/<partition>/spec.md', 'write specs/<partition>/spec.md'],
|
|
43
|
+
allowedSideEffects: ['read project context', 'create or read the resolved specs/<partition> directory', 'write proposed or approved requirement contract'],
|
|
44
|
+
forbiddenSideEffects: ['implement code', 'design technical solution in spec.md', 'silently advance to plan', 'auto commit'],
|
|
45
|
+
nextSteps: ['Resolve the workflow partition: omit --branch to use the current Git branch, or pass --branch <name> only when intentionally writing another partition.', 'Clarify user intent, objective/customer value, actors, scenarios, scope, and non-goals.', 'Run sdd lifecycle decide --from-text <text> when changes mention state-machine, concurrency, database, SQL, security, API/schema, CI/build, or external unknown risk.', 'Write acceptance criteria with stable IDs such as AC-1 and verification hints.', 'Record assumptions/dependencies, risks/hard gates, open questions, and lifecycle reference.', 'If this is a requirement change after plan/tasks/run work exists, update spec.md and let status expose stale downstream hashes before continuing.', 'Stop before technical design or implementation when requirement gaps remain.']
|
|
45
46
|
},
|
|
46
47
|
plan: {
|
|
47
|
-
summary: '
|
|
48
|
-
requiredCommands: ['read specs/<
|
|
49
|
-
allowedSideEffects: ['read project context', 'read spec document', 'write proposed or approved plan document'],
|
|
48
|
+
summary: 'Refine specs/<partition>/plan.md as a deliverable technical solution document that bridges approved spec requirements into task-ready design and records based_on_spec_hash.',
|
|
49
|
+
requiredCommands: ['sdd status', 'read specs/<partition>/spec.md', 'read specs/<partition>/plan.md', 'write specs/<partition>/plan.md'],
|
|
50
|
+
allowedSideEffects: ['read project context', 'read spec document', 'write proposed or approved technical solution plan document'],
|
|
50
51
|
forbiddenSideEffects: ['implement code', 'silently advance to tasks', 'bypass unresolved spec gaps'],
|
|
51
|
-
nextSteps: ['Read the approved spec.', '
|
|
52
|
+
nextSteps: ['Read the approved spec and acceptance criteria plus the current spec hash from sdd status.', 'Record based_on_spec_hash in plan.md so later /sdd:spec revisions can mark this plan stale.', 'Write plan.md as a technical solution document: background, goals/non-goals, current state, target design, architecture/component impact, interaction/sequence design, state/data design, API/schema design, concurrency/transaction/consistency design, key decisions, alternatives, risk control, rollout/rollback, validation matrix, and task breakdown rationale.', 'Use PlantUML diagrams when they clarify component impact, sequence/activity flow, state machines, or deployment/data relationships.', 'Apply risk-driven requirements: state-machine needs state design, concurrency needs sequence/activity and consistency design, database needs data/transaction/rollback design, api_schema needs interface/schema compatibility, security/sql needs risk control.', 'Stop with explicit plan gaps and tasks readiness.']
|
|
52
53
|
},
|
|
53
54
|
tasks: {
|
|
54
|
-
summary: '
|
|
55
|
-
requiredCommands: ['read specs/<
|
|
56
|
-
allowedSideEffects: ['read spec and plan documents', 'write proposed or approved task
|
|
57
|
-
forbiddenSideEffects: ['implement code', 'execute dependency waves', 'silently advance to do'],
|
|
58
|
-
nextSteps: ['Read approved spec and plan.', 'Run sdd tasks format to get the canonical block format.', 'Keep #### Boundary, #### Acceptance, and #### Implementation Notes as companion sections outside the ```sdd-task fenced block; keep only metadata inside the fence.', '
|
|
55
|
+
summary: 'Refine specs/<partition>/tasks.md as an executable evidence contract that maps spec acceptance and plan sections to task boundaries, agents, artifacts, validation, and Definition of Done.',
|
|
56
|
+
requiredCommands: ['sdd status', 'read specs/<partition>/spec.md', 'read specs/<partition>/plan.md', 'sdd tasks format', 'write specs/<partition>/tasks.md', 'sdd tasks list', 'sdd tasks gaps'],
|
|
57
|
+
allowedSideEffects: ['read spec and plan documents', 'write proposed or approved task execution/evidence contract'],
|
|
58
|
+
forbiddenSideEffects: ['implement code', 'execute dependency waves', 'silently advance to do', 'turn tasks.md into project-management backlog'],
|
|
59
|
+
nextSteps: ['Read approved spec acceptance IDs, approved plan design sections, and the current plan hash from sdd status.', 'Record based_on_plan_hash in tasks.md so later plan/spec revisions can mark these tasks stale.', 'Run sdd tasks format to get the canonical block format.', 'Map every task to acceptance_refs and plan_refs where applicable.', 'Keep #### Boundary, #### Acceptance, #### Definition of Done, #### Evidence Expectations, and #### Implementation Notes as companion sections outside the ```sdd-task fenced block; keep only metadata inside the fence.', 'For risky tasks, include allowed_agents, required_artifacts, verification_availability, and autonomy.', 'Run sdd tasks list and sdd tasks gaps.', 'Stop before do task when task boundary, acceptance refs, plan refs, or evidence requirements are unclear.']
|
|
59
60
|
},
|
|
60
61
|
do: {
|
|
61
|
-
summary: 'Execute one approved task boundary through the ingestion-aware SDD task workflow.',
|
|
62
|
+
summary: 'Execute one approved task boundary through the ingestion-aware SDD task workflow with explicit scout/implementer/reviewer/validator evidence handoff.',
|
|
62
63
|
requiredCommands: ['sdd status', 'sdd instructions do --json', 'sdd tasks inspect <task_id>', 'sdd artifact template artifacts/<agent>-<task_id>.md --task <task_id> --agent <agent>', 'sdd artifact validate <run_id> <artifact> --task <task_id> --agent <agent>', 'sdd do task <task_id>'],
|
|
63
64
|
allowedSideEffects: ['write .sdd/runs artifacts', 'update .sdd run state', 'modify files within selected task boundary'],
|
|
64
65
|
forbiddenSideEffects: ['background write', 'worktree creation', 'auto commit', 'expand beyond selected task boundary without checkpoint', 'mark missing evidence as PASS'],
|
|
65
|
-
nextSteps: ['Run sdd status and resolve exactly one task id from the user request or recommended next command.', 'Run sdd instructions do --json and sdd tasks inspect <task_id>.', 'Restate Boundary,
|
|
66
|
+
nextSteps: ['Run sdd status and resolve exactly one task id from the user request or recommended next command.', 'Run sdd instructions do --json and sdd tasks inspect <task_id>.', 'Restate only the task Boundary, blocking gaps, and validation commands before implementation.', 'Use scout for bounded context only, implementer for selected-boundary edits, reviewer for review evidence, and validator for validation plus acceptance mapping.', 'Use sdd artifact template examples for artifacts/implement-<task_id>.md, artifacts/review-<task_id>.md, and artifacts/validation-<task_id>.md before creating evidence; save physical files under .sdd/runs/<run_id>/artifacts/, pass run-relative artifacts/<file> paths to CLI flags, and keep source/test files in ## Evidence, not in sdd-result.artifacts.', 'Run sdd artifact validate before passing artifacts into sdd do task <task_id>.', 'Run or coordinate implementation only within the selected task boundary.', 'Run sdd do task <task_id> with explicit artifact paths when evidence is available.', 'Report run id, final status, blocking gaps, and next gate; avoid replaying full agent evidence unless the user asks.']
|
|
66
67
|
},
|
|
67
68
|
verify: {
|
|
68
|
-
summary: 'Verify task acceptance coverage
|
|
69
|
-
requiredCommands: ['sdd status', 'sdd
|
|
69
|
+
summary: 'Verify task acceptance coverage from reviewer/validator artifacts, resolving the latest eligible run from partition + task id unless --run is explicit.',
|
|
70
|
+
requiredCommands: ['sdd status', 'sdd instructions verify --json', 'sdd artifact template artifacts/validation-<task_id>.md --task <task_id> --agent validator', 'sdd artifact validate <run_id> <artifact> --task <task_id> --agent validator', 'sdd verify task <task_id> [--branch <branch>] [--run <run_id>]', 'sdd sync-back inspect [<run_id>] --task <task_id>'],
|
|
70
71
|
allowedSideEffects: ['write acceptance coverage artifact', 'update .sdd run state', 'create sync-back proposal'],
|
|
71
72
|
forbiddenSideEffects: ['auto commit', 'force push', 'auto-fix failures', 'unapproved complex sync-back apply', 'mark completed with blocking validation gaps'],
|
|
72
|
-
nextSteps: ['Run sdd status and resolve exactly one
|
|
73
|
+
nextSteps: ['Run sdd status and resolve exactly one task id plus workflow partition from the recommended command or user request.', 'Omit --run by default so CLI resolves the latest eligible run for partition + task id; pass --run only for explicit replay, CI, or old-run inspection.', 'Ensure the validator artifact includes exact Acceptance text, preferably under ## Acceptance Mapping from sdd artifact template.', 'Store artifacts physically under .sdd/runs/<run_id>/artifacts/ but pass run-relative artifacts/<file> paths to validate/verify CLI flags.', 'Run sdd artifact validate before goal-level verify.', 'Run sdd instructions verify --json and sdd verify task <task_id> --branch <branch>.', 'If PASS, run sdd sync-back inspect --branch <branch> --task <task_id> and follow its apply_policy.', 'Report PASS/BLOCKED status, unresolved blockers, and next apply command only; avoid pasting full acceptance coverage unless requested.', 'Direct-safe tasks may run sdd sync-back apply directly; confirm-required tasks require human confirmation and --approved before writing tasks.md.']
|
|
73
74
|
},
|
|
74
75
|
'run-task': {
|
|
75
76
|
summary: 'Run the ingestion-aware task workflow using CLI/core runtime state and artifacts.',
|
|
@@ -79,11 +80,11 @@ const INSTRUCTION_PAYLOADS = {
|
|
|
79
80
|
nextSteps: ['Inspect the task.', 'Run the task loop with explicit artifacts and validation evidence.']
|
|
80
81
|
},
|
|
81
82
|
'verify-task': {
|
|
82
|
-
summary: 'Verify task acceptance coverage using CLI/core verifier artifacts.',
|
|
83
|
-
requiredCommands: ['sdd verify task <task_id> --run <run_id>'],
|
|
83
|
+
summary: 'Verify task acceptance coverage using CLI/core verifier artifacts and partition-aware run resolution.',
|
|
84
|
+
requiredCommands: ['sdd verify task <task_id> [--branch <branch>] [--run <run_id>]'],
|
|
84
85
|
allowedSideEffects: ['write acceptance coverage artifact', 'update .sdd run state'],
|
|
85
86
|
forbiddenSideEffects: ['auto commit', 'force push', 'unapproved complex sync-back'],
|
|
86
|
-
nextSteps: ['Run goal-level verify.', 'Inspect sync-back proposal and follow apply_policy before applying any semantic document update.']
|
|
87
|
+
nextSteps: ['Run goal-level verify without --run for the latest eligible partition/task run, unless inspecting an explicit run.', 'Inspect sync-back proposal and follow apply_policy before applying any semantic document update.']
|
|
87
88
|
}
|
|
88
89
|
};
|
|
89
90
|
export function getSddInstructions(action) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../../../../packages/core/src/instructions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,CAAC,MAAM,yBAAyB,GAAG,qBAAqB,CAAC;AAe/D,MAAM,oBAAoB,GAA8F;IACtH,QAAQ,EAAE;QACR,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../../../../packages/core/src/instructions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function assertSafePathSegment(value: string, field: string): void;
|
|
2
|
+
export declare function safeBranchOrNull(branch: string): string | null;
|
|
3
|
+
export declare function branchToSafePartition(branch: string): string;
|
|
4
|
+
export declare function normalizePortablePath(value: string): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export function assertSafePathSegment(value, field) {
|
|
4
|
+
if (value === '.' || value === '..') {
|
|
5
|
+
throw new Error(`${field} cannot be . or ...`);
|
|
6
|
+
}
|
|
7
|
+
if (!/^[A-Za-z0-9._-]+$/.test(value)) {
|
|
8
|
+
throw new Error(`${field} must contain only letters, digits, dot, underscore, or dash.`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function safeBranchOrNull(branch) {
|
|
12
|
+
try {
|
|
13
|
+
assertSafePathSegment(branch, 'branch');
|
|
14
|
+
return branch;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function branchToSafePartition(branch) {
|
|
21
|
+
const trimmed = branch.trim();
|
|
22
|
+
const safe = safeBranchOrNull(trimmed);
|
|
23
|
+
if (safe) {
|
|
24
|
+
return safe;
|
|
25
|
+
}
|
|
26
|
+
const hash = createHash('sha256').update(trimmed).digest('hex').slice(0, 8);
|
|
27
|
+
const slug = trimmed.replace(/[^A-Za-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 48);
|
|
28
|
+
const candidate = slug && slug !== '.' && slug !== '..' ? `${slug}-${hash}` : `branch-${hash}`;
|
|
29
|
+
assertSafePathSegment(candidate, 'partition');
|
|
30
|
+
return candidate;
|
|
31
|
+
}
|
|
32
|
+
export function normalizePortablePath(value) {
|
|
33
|
+
return path.posix.normalize(value.replace(/\\/g, '/'));
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=path-safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-safety.js","sourceRoot":"","sources":["../../../../packages/core/src/path-safety.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,KAAa;IAChE,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,qBAAqB,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,+DAA+D,CAAC,CAAC;IAC3F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,IAAI,CAAC;QACH,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxC,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5F,MAAM,SAAS,GAAG,IAAI,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC;IAC/F,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC9C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;AACzD,CAAC"}
|