sdd-agent-platform 0.2.0 → 0.3.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.
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ import { existsSync, readFileSync } from 'node:fs';
2
3
  import { readFile } from 'node:fs/promises';
3
- import { writeArtifact, archiveRun, applyAiToolEntries, applySyncBack, createWorktreeLifecycle, createRun, doctor, evaluateLifecycleDecisionGate, extractLifecycleRiskSignalsFromText, evaluateGovernancePolicy, getProjectStatus, getDelegationStateMachine, getSddInstructions, initProject, inspectRun, claimResidentWorkerRuntime, heartbeatResidentWorkerRuntime, inspectSddTask, inspectToolPluginContract, inspectToolCapability, inspectDelegationQueueItem, inspectSyncBack, inspectTaskGraph, inspectWavePlan, inspectWaveExecutor, inspectBackgroundExecutor, inspectResidentWorkerRuntime, inspectArtifactResultIngestions, inspectWorktreeLifecycle, inspectWorkerAdapterContract, inspectWorktreeIsolation, inspectGovernancePolicy, inspectWorkflowGate, inspectAgentRegistryEntry, inspectQueryStatusContract, inspectSkillAgentEvalContract, inspectHarnessLearningContract, inspectProjectContextPackContract, inspectAgentSkillTeamRuntime, inspectSkillCapability, inspectCapabilitySource, inspectExternalAgentPackImport, inspectTeamModePolicy, keepWorktreeLifecycle, removeWorktreeLifecycle, listRuns, rebuildLocalRunIndex, inspectLocalRunIndex, queryLocalRunIndex, listToolPluginContracts, listToolCapabilities, listDelegationQueueItems, listWorkerAdapterContracts, listResidentWorkerRuntimes, listWorkflowGates, listAgentRegistry, listSkillCapabilities, listCapabilitySources, ingestArtifactResult, parseSddBranch, readRunState, resolveSddContext, recordLifecycleDecision, renderDoctorReport, renderGoalVerifyResult, renderLifecycleDecisionGate, renderSddResultArtifactTemplate, renderSddInstructions, renderSingleTaskLoopResult, renderTaskGapReport, renderTaskInspect, renderTaskList, runGoalVerify, runSingleTaskLoop, runBackgroundExecutor, runWaveExecutor, SDD_VERSION, summarizeAiProjectionStatus, validateSddResultArtifact, validateWorkflowGates, validateAgentRegistry, validateQueryStatusContract, validateSkillAgentEvalContract, validateHarnessLearningContract, validateProjectContextPackContract, routeSddTask, validateAgentSkillTeamRuntime, toArtifactRootRelativePath } from '../../core/src/index.js';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { writeArtifact, archiveRun, applyAiToolEntries, applySyncBack, createWorktreeLifecycle, createRun, doctor, buildContextBuildPackage, buildEvidenceSummaryProjection, evaluateLifecycleDecisionGate, extractLifecycleRiskSignalsFromText, evaluateGovernancePolicy, getProjectStatus, getDelegationStateMachine, getSddInstructions, initProject, inspectRun, claimResidentWorkerRuntime, heartbeatResidentWorkerRuntime, inspectSddTask, inspectToolPluginContract, inspectToolCapability, inspectDelegationQueueItem, inspectSyncBack, inspectTaskGraph, inspectWavePlan, inspectWaveExecutor, inspectBackgroundExecutor, inspectResidentWorkerRuntime, inspectArtifactResultIngestions, inspectWorktreeLifecycle, inspectWorkerAdapterContract, inspectWorktreeIsolation, inspectGovernancePolicy, inspectWorkflowGate, inspectAgentRegistryEntry, inspectQueryStatusContract, inspectSkillAgentEvalContract, inspectHarnessLearningContract, inspectProjectContextPackContract, inspectAgentSkillTeamRuntime, inspectSkillCapability, inspectCapabilitySource, inspectExternalAgentPackImport, inspectTeamModePolicy, keepWorktreeLifecycle, removeWorktreeLifecycle, listRuns, rebuildLocalRunIndex, inspectLocalRunIndex, queryLocalRunIndex, listToolPluginContracts, listToolCapabilities, listDelegationQueueItems, listWorkerAdapterContracts, listResidentWorkerRuntimes, listWorkflowGates, listAgentRegistry, listSkillCapabilities, listCapabilitySources, ingestArtifactResult, parseSddBranch, readRunState, resolveSddContext, recordLifecycleDecision, parseContextProfile, renderDoctorReport, renderGoalVerifyResult, renderLifecycleDecisionGate, renderSddResultArtifactTemplate, renderSddInstructions, renderSingleTaskLoopResult, renderTaskGapReport, renderTaskInspect, renderTaskList, runGoalVerify, runSingleTaskLoop, runBackgroundExecutor, runWaveExecutor, SDD_VERSION, summarizeAiProjectionStatus, validateSddResultArtifact, validateWorkflowGates, validateAgentRegistry, validateQueryStatusContract, validateSkillAgentEvalContract, validateHarnessLearningContract, validateProjectContextPackContract, routeSddTask, validateAgentSkillTeamRuntime, toArtifactRootRelativePath } from '../../core/src/index.js';
4
7
  import { readOption, readPositiveIntegerOption, readRepeatedOption, readRepeatedOptions } from './options.js';
5
8
  async function main(args) {
6
9
  const projectRoot = process.cwd();
@@ -17,10 +20,11 @@ async function main(args) {
17
20
  output: helpText(subcommand)
18
21
  };
19
22
  }
20
- if (command === '--version' || command === '-v') {
23
+ if (command === '--version' || command === '-v' || command === 'version') {
24
+ const identity = getCliIdentity();
21
25
  return {
22
26
  exitCode: 0,
23
- output: SDD_VERSION
27
+ output: wantsJson(args) ? jsonOutput(identity, args) : identity.version
24
28
  };
25
29
  }
26
30
  if (command === 'init') {
@@ -61,12 +65,13 @@ async function main(args) {
61
65
  if (doctorArgs.includes('--latest-only') && doctorArgs.includes('--all-runs')) {
62
66
  return {
63
67
  exitCode: 2,
64
- error: 'Usage: sdd doctor [--latest-only] [--all-runs] (choose only one scope flag)'
68
+ error: 'Usage: sdd doctor [--latest-only] [--all-runs] [--branch <branch>] (choose only one scope flag)'
65
69
  };
66
70
  }
67
71
  const report = await doctor(projectRoot, {
68
72
  latestOnly: doctorArgs.includes('--latest-only'),
69
- allRuns: doctorArgs.includes('--all-runs')
73
+ allRuns: doctorArgs.includes('--all-runs'),
74
+ branch: readBranchOption(doctorArgs)
70
75
  });
71
76
  const json = wantsJson(doctorArgs);
72
77
  return {
@@ -182,6 +187,46 @@ async function main(args) {
182
187
  output: JSON.stringify({ runId: state.runId, status: state.status, updatedAt: state.updatedAt }, null, 2)
183
188
  };
184
189
  }
190
+ if (command === 'evidence' && subcommand === 'summary') {
191
+ const runId = rest.find((item) => !item.startsWith('--'));
192
+ if (!runId) {
193
+ return {
194
+ exitCode: 2,
195
+ error: 'Usage: sdd evidence summary <run_id> [--task <task_id>] [--json|--compact-json]'
196
+ };
197
+ }
198
+ const summary = await buildEvidenceSummaryProjection(projectRoot, {
199
+ runId,
200
+ taskId: readOption(rest, '--task') ?? undefined
201
+ });
202
+ const json = wantsJson(rest);
203
+ return {
204
+ exitCode: 0,
205
+ output: json ? jsonOutput(summary, rest) : renderEvidenceSummaryProjection(summary)
206
+ };
207
+ }
208
+ if (command === 'context' && subcommand === 'build') {
209
+ const taskId = readOption(rest, '--task') ?? undefined;
210
+ const mode = readContextBuildMode(rest, '--mode');
211
+ if (!taskId || !mode) {
212
+ return {
213
+ exitCode: 2,
214
+ error: 'Usage: sdd context build --task <task_id> --mode do|verify|sync-back|doctor [--agent <agent>] [--branch <branch>] [--profile brief|normal|forensic] [--json|--compact-json]'
215
+ };
216
+ }
217
+ const contextPackage = await buildContextBuildPackage(projectRoot, {
218
+ taskId,
219
+ branch: readBranchOption(rest),
220
+ mode,
221
+ agent: readOption(rest, '--agent') ?? undefined,
222
+ profile: parseContextProfile(readOption(rest, '--profile'))
223
+ });
224
+ const json = wantsJson(rest);
225
+ return {
226
+ exitCode: 0,
227
+ output: json ? jsonOutput(contextPackage, rest) : renderContextBuildPackage(contextPackage)
228
+ };
229
+ }
185
230
  if (command === 'sync-back' && subcommand === 'inspect') {
186
231
  const runId = readOptionalPositionalArgument(rest);
187
232
  const taskId = readOption(rest, '--task') ?? undefined;
@@ -263,13 +308,15 @@ async function main(args) {
263
308
  if (!taskId) {
264
309
  return {
265
310
  exitCode: 2,
266
- error: 'Usage: sdd tasks route <task_id> [--branch <branch>] [--team-mode [auto|force|off]] [--no-team-mode] [--json]'
311
+ error: 'Usage: sdd tasks route <task_id> [--branch <branch>] [--team-mode [auto|force|off]] [--no-team-mode] [--profile] [--cache] [--json]'
267
312
  };
268
313
  }
269
314
  const decision = await routeSddTask(projectRoot, {
270
315
  taskId,
271
316
  branch: readBranchOption(rest),
272
- teamModeActivation: readTeamModeActivation(rest)
317
+ teamModeActivation: readTeamModeActivation(rest),
318
+ profile: rest.includes('--profile'),
319
+ cache: rest.includes('--cache'),
273
320
  });
274
321
  return {
275
322
  exitCode: decision.blockedReason ? 1 : 0,
@@ -955,14 +1002,15 @@ async function main(args) {
955
1002
  error: 'Usage: sdd artifact template <artifacts/path.md> --task <task_id> --agent <agent> [--run <run_id> --write] [--branch <branch>] [--status <status>]'
956
1003
  };
957
1004
  }
1005
+ const runId = readOption(rest, '--run');
958
1006
  const template = await renderSddResultArtifactTemplate(projectRoot, {
959
1007
  artifactPath,
960
1008
  taskId,
961
1009
  agent,
962
1010
  branch: readBranchOption(rest),
1011
+ runId: runId ?? undefined,
963
1012
  status: readSddResultStatus(rest, '--status') ?? 'PASS'
964
1013
  });
965
- const runId = readOption(rest, '--run');
966
1014
  if (rest.includes('--write')) {
967
1015
  if (!runId) {
968
1016
  return {
@@ -1063,6 +1111,8 @@ Evidence helpers:
1063
1111
  sdd run index rebuild|inspect|query [options] [--json|--compact-json]
1064
1112
  sdd artifact template <path> --task <task_id> --agent <agent> [--run <run_id> --write]
1065
1113
  sdd artifact validate <run_id> <path> [--task <task_id>] [--agent <agent>] [--json|--compact-json]
1114
+ sdd evidence summary <run_id> [--task <task_id>] [--json|--compact-json]
1115
+ sdd context build --task <task_id> --mode do|verify|sync-back|doctor [--agent <agent>] [--branch <branch>] [--profile brief|normal|forensic] [--json|--compact-json]
1066
1116
 
1067
1117
  Generated AI entries:
1068
1118
  sdd update [--check] [--ai <mode>]
@@ -1136,6 +1186,101 @@ function wantsJson(args) {
1136
1186
  function jsonOutput(value, args) {
1137
1187
  return JSON.stringify(value, null, args.includes('--compact-json') ? 0 : 2);
1138
1188
  }
1189
+ function getCliIdentity() {
1190
+ const cliEntryPath = fileURLToPath(import.meta.url);
1191
+ const packageRoot = findPackageRoot(path.dirname(cliEntryPath));
1192
+ const packageJsonPath = packageRoot ? path.join(packageRoot, 'package.json') : null;
1193
+ return {
1194
+ version: readPackageVersion(packageJsonPath) ?? SDD_VERSION,
1195
+ cliEntryPath,
1196
+ packageRoot,
1197
+ packageJsonPath
1198
+ };
1199
+ }
1200
+ function findPackageRoot(startDir) {
1201
+ let current = startDir;
1202
+ while (true) {
1203
+ const packageJsonPath = path.join(current, 'package.json');
1204
+ if (existsSync(packageJsonPath) && isCliPackageRoot(packageJsonPath)) {
1205
+ return current;
1206
+ }
1207
+ const parent = path.dirname(current);
1208
+ if (parent === current) {
1209
+ return null;
1210
+ }
1211
+ current = parent;
1212
+ }
1213
+ }
1214
+ function isCliPackageRoot(packageJsonPath) {
1215
+ try {
1216
+ const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
1217
+ return parsed.name === '@sdd-agent-platform/cli' || parsed.name === 'sdd-agent-platform';
1218
+ }
1219
+ catch {
1220
+ return false;
1221
+ }
1222
+ }
1223
+ function readPackageVersion(packageJsonPath) {
1224
+ if (!packageJsonPath) {
1225
+ return null;
1226
+ }
1227
+ try {
1228
+ const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
1229
+ return typeof parsed.version === 'string' ? parsed.version : null;
1230
+ }
1231
+ catch {
1232
+ return null;
1233
+ }
1234
+ }
1235
+ function readContextBuildMode(args, name) {
1236
+ const value = readOption(args, name);
1237
+ return value === 'do' || value === 'verify' || value === 'sync-back' || value === 'doctor' ? value : null;
1238
+ }
1239
+ function renderEvidenceSummaryProjection(summary) {
1240
+ const lines = [`Evidence summary ${summary.runId}`];
1241
+ lines.push(`task=${summary.taskId ?? 'none'} authoritative=${summary.authoritative} usable_for_pass=${summary.usableForPass}`);
1242
+ lines.push(`pass=${summary.passCount} blocked=${summary.blockedCount} fail=${summary.failCount} issues=${summary.issueCodes.join(',') || 'none'}`);
1243
+ lines.push('highlights');
1244
+ for (const highlight of summary.highlights.slice(0, 8)) {
1245
+ lines.push(`- ${highlight}`);
1246
+ }
1247
+ lines.push('sources');
1248
+ for (const source of summary.sources.slice(0, 12)) {
1249
+ lines.push(`- ${source.kind}:${source.path} hash=${source.hash.slice(0, 12)}`);
1250
+ }
1251
+ if (summary.sources.length > 12) {
1252
+ lines.push(`- omitted_sources=${summary.sources.length - 12}`);
1253
+ }
1254
+ return lines.join('\n');
1255
+ }
1256
+ function renderContextBuildPackage(contextPackage) {
1257
+ const lines = [`Context package ${contextPackage.taskId}`];
1258
+ lines.push(`mode=${contextPackage.mode} agent=${contextPackage.agent ?? 'none'} profile=${contextPackage.profile} branch=${contextPackage.branch}`);
1259
+ lines.push(`authoritative=${contextPackage.authoritative} usable_for_pass=${contextPackage.usableForPass}`);
1260
+ renderContextRefs(lines, 'must_read', contextPackage.mustRead, 10);
1261
+ renderContextRefs(lines, 'optional_read', contextPackage.optionalRead, 8);
1262
+ renderContextRefs(lines, 'deferred', contextPackage.doNotReadUnlessNeeded, 6);
1263
+ lines.push('next_commands');
1264
+ for (const command of contextPackage.nextCommands) {
1265
+ lines.push(`- ${command}`);
1266
+ }
1267
+ if (contextPackage.warnings.length > 0) {
1268
+ lines.push('warnings');
1269
+ for (const warning of contextPackage.warnings.slice(0, 6)) {
1270
+ lines.push(`- ${warning}`);
1271
+ }
1272
+ }
1273
+ return lines.join('\n');
1274
+ }
1275
+ function renderContextRefs(lines, label, refs, limit) {
1276
+ lines.push(label);
1277
+ for (const ref of refs.slice(0, limit)) {
1278
+ lines.push(`- ${ref.kind}:${ref.path} hash=${ref.hash.slice(0, 12)}`);
1279
+ }
1280
+ if (refs.length > limit) {
1281
+ lines.push(`- omitted_${label}=${refs.length - limit}`);
1282
+ }
1283
+ }
1139
1284
  function renderTextOrJson(args, value, renderText) {
1140
1285
  return wantsJson(args) ? jsonOutput(value, args) : renderText(value);
1141
1286
  }
@@ -1472,8 +1617,21 @@ function renderAgentRouterDecision(decision) {
1472
1617
  lines.push(`approval=${decision.toolPermission.approvalPolicy}`);
1473
1618
  }
1474
1619
  lines.push(`model_policy=${decision.modelPolicy.id} category=${decision.modelPolicy.category}`);
1475
- lines.push(`team_mode=${decision.teamMode.decision} mode=${decision.teamMode.mode} activation=${decision.teamMode.activation} cost=${decision.teamMode.costClass} waves=${decision.teamMode.waveRecommendation.join(',') || 'none'}`);
1620
+ lines.push(`team_mode=${decision.teamMode.decision} mode=${decision.teamMode.mode} activation=${decision.teamMode.activation} cost=${decision.teamMode.costClass} cost_route=${decision.teamMode.costRoute} waves=${decision.teamMode.waveRecommendation.join(',') || 'none'}`);
1476
1621
  lines.push(`team_mode_reason=${decision.teamMode.reason}`);
1622
+ if (decision.teamMode.downgradeReason) {
1623
+ lines.push(`team_mode_downgrade=${decision.teamMode.downgradeReason}`);
1624
+ }
1625
+ lines.push(`trust_policy_enforced=${decision.teamMode.trustPolicyEnforced}`);
1626
+ if (decision.cache) {
1627
+ lines.push(`route_cache=${decision.cache.status} key=${decision.cache.key} authoritative=${decision.cache.authoritative}`);
1628
+ }
1629
+ if (decision.profile && decision.profile.length > 0) {
1630
+ lines.push('profile');
1631
+ for (const span of decision.profile) {
1632
+ lines.push(`- ${span.name}: ${span.durationMs}ms`);
1633
+ }
1634
+ }
1477
1635
  lines.push(`required_artifacts=${decision.requiredArtifacts.join(',') || 'none'}`);
1478
1636
  if (decision.blockedReason) {
1479
1637
  lines.push(`blocked_reason=${decision.blockedReason}`);