@structured-vibe-coding/core 0.17.1 → 0.18.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.
Files changed (31) hide show
  1. package/defaults/prices.yaml +9 -0
  2. package/defaults/search.yaml +18 -0
  3. package/dist/{agents-CLTJJVOD.js → agents-AKSUXQHN.js} +18 -7
  4. package/dist/{change-context-W4HDO2IK.js → change-context-REE7UKU7.js} +2 -4
  5. package/dist/chunk-44LQ5BKZ.js +2628 -0
  6. package/dist/{chunk-KYWETNFU.js → chunk-4BRO7BOJ.js} +2 -4
  7. package/dist/chunk-4PIRWYRA.js +1125 -0
  8. package/dist/{chunk-72QJHR53.js → chunk-LHSR7JG2.js} +569 -39
  9. package/dist/{chunk-EPFURATC.js → chunk-O5SP6X5R.js} +89 -0
  10. package/dist/{chunk-BGM6KS64.js → chunk-QGP43XCN.js} +2 -2
  11. package/dist/{chunk-A752UVPF.js → chunk-QHV5KZKX.js} +193 -28
  12. package/dist/{gather-S4A5YR7X.js → gather-ZNV2NAUN.js} +3 -4
  13. package/dist/{greenfield-QQJH3XL3.js → greenfield-I5S5OS2D.js} +5 -6
  14. package/dist/index.d.ts +1034 -40
  15. package/dist/index.js +2927 -988
  16. package/dist/{sources-PF45EUH2.js → sources-3TXUPU6V.js} +2 -3
  17. package/package.json +11 -3
  18. package/vendor/tree-sitter/NOTICE +29 -0
  19. package/vendor/tree-sitter/tree-sitter-javascript.wasm +0 -0
  20. package/vendor/tree-sitter/tree-sitter-python.wasm +0 -0
  21. package/vendor/tree-sitter/tree-sitter-rust.wasm +0 -0
  22. package/vendor/tree-sitter/tree-sitter-tsx.wasm +0 -0
  23. package/vendor/tree-sitter/tree-sitter-typescript.wasm +0 -0
  24. package/dist/chunk-67AUAGNV.js +0 -150
  25. package/dist/chunk-7MJYPJMR.js +0 -51
  26. package/dist/chunk-BVCTVKBD.js +0 -538
  27. package/dist/chunk-WHDG6OTG.js +0 -46
  28. package/dist/chunk-WPAGUBZ5.js +0 -139
  29. package/dist/config-X5VDBVR4.js +0 -16
  30. package/dist/fs-J6DIV6CX.js +0 -28
  31. package/dist/paths-64GA32IZ.js +0 -28
@@ -1,3 +1,73 @@
1
+ // src/paths.ts
2
+ import { join } from "pathe";
3
+ var SDD_DIR = ".sdd";
4
+ function sddRoot(projectRoot) {
5
+ return join(projectRoot, SDD_DIR);
6
+ }
7
+ function configPath(projectRoot) {
8
+ return join(sddRoot(projectRoot), "config.yaml");
9
+ }
10
+ function workflowsDir(projectRoot) {
11
+ return join(sddRoot(projectRoot), "workflows");
12
+ }
13
+ function templatesDir(projectRoot) {
14
+ return join(sddRoot(projectRoot), "templates");
15
+ }
16
+ function memoryDir(projectRoot, config) {
17
+ return join(projectRoot, config.memory_path);
18
+ }
19
+ function stripTrailingSlashes(value) {
20
+ let end = value.length;
21
+ while (end > 0 && value.charCodeAt(end - 1) === 47) end -= 1;
22
+ return value.slice(0, end);
23
+ }
24
+ function memoryPathRel(config) {
25
+ return stripTrailingSlashes(config.memory_path) || "memory";
26
+ }
27
+ function changesPathRel(config) {
28
+ return stripTrailingSlashes(config.changes_path) || "changes";
29
+ }
30
+ function displayArchivePath(config, changeId) {
31
+ return `${stripTrailingSlashes(config.archive_path) || "archive"}/${changeId}`;
32
+ }
33
+ function displayChangePath(config, changeId) {
34
+ return `${changesPathRel(config)}/${changeId}`;
35
+ }
36
+ function guidancePaths(config) {
37
+ const memory = memoryPathRel(config);
38
+ const changes = changesPathRel(config);
39
+ return {
40
+ memory,
41
+ changes,
42
+ constitution: `${memory}/constitution.md`,
43
+ memoryIndex: `${memory}/index.md`
44
+ };
45
+ }
46
+ function changesDir(projectRoot, config) {
47
+ return join(projectRoot, config.changes_path);
48
+ }
49
+ function archiveDir(projectRoot, config) {
50
+ return join(projectRoot, config.archive_path);
51
+ }
52
+ function domainsDir(projectRoot, config) {
53
+ return join(projectRoot, config.domains_path);
54
+ }
55
+ function changePath(projectRoot, config, changeId) {
56
+ return join(changesDir(projectRoot, config), changeId);
57
+ }
58
+ function changeMetaPath(projectRoot, config, changeId) {
59
+ return join(changePath(projectRoot, config, changeId), "meta.yaml");
60
+ }
61
+ function activePointerPath(projectRoot, config) {
62
+ return join(changesDir(projectRoot, config), ".active");
63
+ }
64
+ function searchConfigPath(projectRoot) {
65
+ return join(sddRoot(projectRoot), "search.yaml");
66
+ }
67
+ function indexDbPath(projectRoot) {
68
+ return join(sddRoot(projectRoot), "index.db");
69
+ }
70
+
1
71
  // src/fs.ts
2
72
  import { promises as fs } from "fs";
3
73
  import { dirname } from "pathe";
@@ -81,6 +151,25 @@ async function removePath(path) {
81
151
  }
82
152
 
83
153
  export {
154
+ SDD_DIR,
155
+ sddRoot,
156
+ configPath,
157
+ workflowsDir,
158
+ templatesDir,
159
+ memoryDir,
160
+ memoryPathRel,
161
+ changesPathRel,
162
+ displayArchivePath,
163
+ displayChangePath,
164
+ guidancePaths,
165
+ changesDir,
166
+ archiveDir,
167
+ domainsDir,
168
+ changePath,
169
+ changeMetaPath,
170
+ activePointerPath,
171
+ searchConfigPath,
172
+ indexDbPath,
84
173
  pathExists,
85
174
  ensureDir,
86
175
  readText,
@@ -2,7 +2,7 @@ import {
2
2
  interpolate,
3
3
  interpolateArgs,
4
4
  loadMcpConfig
5
- } from "./chunk-KYWETNFU.js";
5
+ } from "./chunk-4BRO7BOJ.js";
6
6
  import {
7
7
  SddError
8
8
  } from "./chunk-MHODNFIL.js";
@@ -26,7 +26,7 @@ function toProcessEnv(base, extra) {
26
26
  }
27
27
 
28
28
  // src/version.ts
29
- var SDD_CORE_VERSION = "0.17.1" ? "0.17.1" : "0.0.0-dev";
29
+ var SDD_CORE_VERSION = "0.18.0" ? "0.18.0" : "0.0.0-dev";
30
30
 
31
31
  // src/mcp/client.ts
32
32
  function mcpTimeoutMs() {
@@ -1,28 +1,198 @@
1
- import {
2
- ChangeMetaSchema,
3
- WorkflowSchema
4
- } from "./chunk-67AUAGNV.js";
5
1
  import {
6
2
  activePointerPath,
7
3
  changeMetaPath,
8
4
  changePath,
9
5
  changesDir,
10
- workflowsDir
11
- } from "./chunk-7MJYPJMR.js";
12
- import {
6
+ displayChangePath,
13
7
  ensureDir,
14
8
  listDirs,
15
9
  listFiles,
16
10
  pathExists,
17
11
  readText,
18
12
  readYaml,
13
+ workflowsDir,
19
14
  writeText,
20
15
  writeYaml
21
- } from "./chunk-EPFURATC.js";
16
+ } from "./chunk-O5SP6X5R.js";
17
+
18
+ // src/schemas.ts
19
+ import { z } from "zod";
20
+ var GateSchema = z.object({
21
+ type: z.enum(["none", "soft", "hard"]).default("soft"),
22
+ mode: z.enum(["none", "human_approval", "checklist"]).default("checklist"),
23
+ checklist: z.array(z.string()).default([]),
24
+ overridable: z.boolean().default(true)
25
+ });
26
+ var ArtifactDefSchema = z.object({
27
+ id: z.string(),
28
+ path: z.string(),
29
+ template: z.string().optional(),
30
+ required: z.boolean().default(true)
31
+ });
32
+ var VerifyCommandSchema = z.object({
33
+ name: z.string(),
34
+ run: z.string(),
35
+ required: z.boolean().default(false)
36
+ });
37
+ var StageSchema = z.object({
38
+ id: z.string(),
39
+ title: z.string().optional(),
40
+ summary: z.string().optional(),
41
+ /**
42
+ * standard — normal work stage
43
+ * brainstorm — optional multi-approach exploration (before design)
44
+ * clarify — optional Q&A before leaving a major stage
45
+ */
46
+ kind: z.enum(["standard", "brainstorm", "clarify"]).default("standard"),
47
+ /** When true, stage is optional (skippable); agents may skip if not needed */
48
+ optional: z.boolean().default(false),
49
+ artifacts: z.array(ArtifactDefSchema).default([]),
50
+ gate: GateSchema.default({}),
51
+ skippable: z.boolean().default(true),
52
+ skip_when: z.object({
53
+ flags: z.array(z.string()).optional()
54
+ }).optional(),
55
+ verify: z.object({
56
+ commands: z.array(VerifyCommandSchema).default([]),
57
+ evidence_dir: z.string().optional()
58
+ }).optional(),
59
+ agent_context: z.object({
60
+ include: z.array(z.string()).default([]),
61
+ instructions: z.string().optional()
62
+ }).optional()
63
+ });
64
+ var WorkflowSchema = z.object({
65
+ name: z.string(),
66
+ description: z.string().optional(),
67
+ version: z.number().default(1),
68
+ stages: z.array(StageSchema).min(1),
69
+ recommendation: z.object({
70
+ when: z.object({
71
+ labels: z.array(z.string()).optional(),
72
+ keywords: z.array(z.string()).optional(),
73
+ max_complexity: z.enum(["low", "medium", "high"]).optional(),
74
+ min_complexity: z.enum(["low", "medium", "high"]).optional()
75
+ }).optional(),
76
+ priority: z.number().default(0)
77
+ }).optional(),
78
+ on_complete: z.object({
79
+ archive: z.boolean().default(false),
80
+ domain_sync: z.enum(["never", "recommend", "require"]).default("never")
81
+ }).optional()
82
+ });
83
+ var ConfigSchema = z.object({
84
+ version: z.number().default(1),
85
+ metrics: z.object({
86
+ enabled: z.boolean().default(true),
87
+ exclude: z.array(z.string().min(1)).default([])
88
+ }).default({}),
89
+ memory_path: z.string().default("memory"),
90
+ changes_path: z.string().default("changes"),
91
+ archive_path: z.string().default("archive"),
92
+ domains_path: z.string().default("domains"),
93
+ default_workflow: z.string().default("recommend"),
94
+ allowed_workflows: z.array(z.string()).optional(),
95
+ per_change: z.object({
96
+ allow_skip: z.boolean().default(true),
97
+ allow_gate_override: z.enum(["true", "false", "soft_only"]).default("soft_only"),
98
+ allow_custom_stages: z.boolean().default(true),
99
+ require_reason_on_skip: z.boolean().default(true)
100
+ }).default({}),
101
+ persistence: z.object({
102
+ default: z.enum(["change_only", "domain_sync"]).default("change_only"),
103
+ archive_on_complete: z.boolean().default(false),
104
+ domain_sync: z.object({
105
+ mode: z.enum(["never", "recommend", "require"]).default("never"),
106
+ anchored_domains: z.array(z.string()).default([])
107
+ }).default({})
108
+ }).default({}),
109
+ policy: z.object({
110
+ gates: z.enum(["soft", "hard"]).default("soft")
111
+ }).default({})
112
+ });
113
+ var ChangeMetaSchema = z.object({
114
+ id: z.string(),
115
+ title: z.string(),
116
+ workflow: z.string(),
117
+ created: z.string(),
118
+ updated: z.string().optional(),
119
+ status: z.enum(["in_progress", "blocked", "completed", "abandoned"]).default("in_progress"),
120
+ stage: z.string(),
121
+ branch: z.string().optional(),
122
+ /** Epic key such as issue-37. Stories in one epic share a dependency graph. */
123
+ epic: z.string().optional(),
124
+ /** Story id such as S-001. */
125
+ story: z.string().optional(),
126
+ depends: z.array(z.string()).optional(),
127
+ domain: z.string().optional(),
128
+ flags: z.record(z.union([z.boolean(), z.string(), z.number()])).default({}),
129
+ overrides: z.object({
130
+ skip_stages: z.array(z.string()).default([]),
131
+ gates: z.record(z.enum(["none", "soft", "hard"])).default({}),
132
+ extra_stages: z.array(StageSchema).default([])
133
+ }).default({}),
134
+ skipped: z.array(
135
+ z.object({
136
+ stage: z.string(),
137
+ reason: z.string(),
138
+ at: z.string()
139
+ })
140
+ ).default([]),
141
+ gates: z.record(
142
+ z.object({
143
+ status: z.enum(["pending", "approved", "failed", "waived"]),
144
+ note: z.string().optional(),
145
+ at: z.string().optional()
146
+ })
147
+ ).default({}),
148
+ /** Results from `sdd verify` keyed by stage id */
149
+ verify_results: z.record(
150
+ z.object({
151
+ ok: z.boolean(),
152
+ /** pass | fail | not_run (absent in metas written before 0.17.3) */
153
+ status: z.enum(["pass", "fail", "not_run"]).optional(),
154
+ head_sha: z.string().regex(/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/i).optional(),
155
+ at: z.string(),
156
+ results: z.array(
157
+ z.object({
158
+ name: z.string(),
159
+ exitCode: z.number().nullable()
160
+ })
161
+ ).default([])
162
+ })
163
+ ).default({}),
164
+ pr: z.object({
165
+ number: z.number().optional(),
166
+ url: z.string().optional()
167
+ }).optional(),
168
+ completed_at: z.string().optional()
169
+ });
22
170
 
23
171
  // src/slug.ts
172
+ var SLUG_MAX = 60;
173
+ function trailingIssueRef(input) {
174
+ return input.match(/#\s*(\d+)\s*\)?\s*$/)?.[1];
175
+ }
24
176
  function slugify(input) {
25
- return input.toLowerCase().trim().replace(/['"]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60).replace(/-+$/g, "");
177
+ const normalized = input.toLowerCase().trim().replace(/['"]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
178
+ if (normalized.length <= SLUG_MAX) return normalized;
179
+ const issue = trailingIssueRef(input);
180
+ const tokens = normalized.split("-").filter(Boolean);
181
+ const body = issue && tokens.at(-1) === issue ? tokens.slice(0, -1) : tokens;
182
+ const reserve = issue && issue.length <= SLUG_MAX ? issue.length + 1 : 0;
183
+ const kept = [];
184
+ let length = 0;
185
+ for (const token of body) {
186
+ const next = length === 0 ? token.length : length + 1 + token.length;
187
+ if (next + reserve > SLUG_MAX) break;
188
+ kept.push(token);
189
+ length = next;
190
+ }
191
+ if (reserve && issue) {
192
+ if (kept.length === 0) return issue;
193
+ return `${kept.join("-")}-${issue}`;
194
+ }
195
+ return kept.join("-");
26
196
  }
27
197
  function todayIsoDate(d = /* @__PURE__ */ new Date()) {
28
198
  return d.toISOString().slice(0, 10);
@@ -232,6 +402,7 @@ async function buildContext(projectRoot, config, changeId) {
232
402
  return {
233
403
  id: changeId,
234
404
  path: changePath(projectRoot, config, changeId),
405
+ displayPath: displayChangePath(config, changeId),
235
406
  meta,
236
407
  workflow,
237
408
  stages: resolveStages(workflow, meta),
@@ -252,20 +423,7 @@ async function getActiveChangeId(projectRoot, config) {
252
423
  await writeText(pointer, "");
253
424
  }
254
425
  }
255
- const all = await listChanges(projectRoot, config);
256
- const inProgress = [];
257
- for (const id of all) {
258
- try {
259
- const meta = await loadChangeMeta(projectRoot, config, id);
260
- if (meta.status === "in_progress" || meta.status === "blocked") {
261
- inProgress.push({ id, updated: meta.updated ?? meta.created });
262
- }
263
- } catch {
264
- }
265
- }
266
- if (!inProgress.length) return null;
267
- inProgress.sort((a, b) => b.updated.localeCompare(a.updated));
268
- return inProgress[0].id;
426
+ return null;
269
427
  }
270
428
  async function clearActiveIf(projectRoot, config, changeId) {
271
429
  const pointer = activePointerPath(projectRoot, config);
@@ -290,6 +448,18 @@ async function resolveChangeId(projectRoot, config, changeId) {
290
448
  }
291
449
 
292
450
  export {
451
+ GateSchema,
452
+ ArtifactDefSchema,
453
+ VerifyCommandSchema,
454
+ StageSchema,
455
+ WorkflowSchema,
456
+ ConfigSchema,
457
+ ChangeMetaSchema,
458
+ slugify,
459
+ todayIsoDate,
460
+ nowIso,
461
+ changeDirName,
462
+ uniqueChangeDirName,
293
463
  listWorkflowNames,
294
464
  loadWorkflow,
295
465
  resolveStages,
@@ -301,11 +471,6 @@ export {
301
471
  firstActiveStageId,
302
472
  inferComplexity,
303
473
  recommendWorkflow,
304
- slugify,
305
- todayIsoDate,
306
- nowIso,
307
- changeDirName,
308
- uniqueChangeDirName,
309
474
  loadChangeMeta,
310
475
  saveChangeMeta,
311
476
  buildContext,
@@ -3,11 +3,10 @@ import {
3
3
  gatherMcpContext,
4
4
  gatherMcpContextForChange,
5
5
  listMatchingSourceIds
6
- } from "./chunk-BGM6KS64.js";
7
- import "./chunk-KYWETNFU.js";
6
+ } from "./chunk-QGP43XCN.js";
7
+ import "./chunk-4BRO7BOJ.js";
8
8
  import "./chunk-MHODNFIL.js";
9
- import "./chunk-7MJYPJMR.js";
10
- import "./chunk-EPFURATC.js";
9
+ import "./chunk-O5SP6X5R.js";
11
10
  export {
12
11
  formatMcpContextForHandoff,
13
12
  gatherMcpContext,
@@ -6,12 +6,11 @@ import {
6
6
  startFeatureFromBacklog,
7
7
  startGreenfield,
8
8
  updateFeatureStatus
9
- } from "./chunk-72QJHR53.js";
10
- import "./chunk-WPAGUBZ5.js";
11
- import "./chunk-A752UVPF.js";
12
- import "./chunk-67AUAGNV.js";
13
- import "./chunk-7MJYPJMR.js";
14
- import "./chunk-EPFURATC.js";
9
+ } from "./chunk-LHSR7JG2.js";
10
+ import "./chunk-44LQ5BKZ.js";
11
+ import "./chunk-QHV5KZKX.js";
12
+ import "./chunk-MHODNFIL.js";
13
+ import "./chunk-O5SP6X5R.js";
15
14
  export {
16
15
  findFeaturesBacklogPath,
17
16
  listBacklogFeatures,