@structured-vibe-coding/core 0.21.0 → 0.23.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.
@@ -26,10 +26,11 @@ import {
26
26
  renderProtocolMd,
27
27
  renderThinAgent,
28
28
  writeAgentHandoff
29
- } from "./chunk-5GLH6ZWU.js";
30
- import "./chunk-AERAWOAK.js";
29
+ } from "./chunk-GP477MAV.js";
30
+ import "./chunk-RXQH2THQ.js";
31
31
  import "./chunk-TNWFMRIA.js";
32
- import "./chunk-MHODNFIL.js";
32
+ import "./chunk-OY47H6R5.js";
33
+ import "./chunk-4BRO7BOJ.js";
33
34
  import "./chunk-O5SP6X5R.js";
34
35
  export {
35
36
  AGENT_INTEGRATIONS,
@@ -6,7 +6,7 @@ import {
6
6
  loadConfig,
7
7
  readRole,
8
8
  readTeamConfig
9
- } from "./chunk-AERAWOAK.js";
9
+ } from "./chunk-RXQH2THQ.js";
10
10
  import {
11
11
  buildContext,
12
12
  defaultMemoryDir,
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-TNWFMRIA.js";
15
15
  import {
16
16
  SddError
17
- } from "./chunk-MHODNFIL.js";
17
+ } from "./chunk-OY47H6R5.js";
18
18
  import {
19
19
  configPath,
20
20
  guidancePaths,
@@ -4,7 +4,7 @@ import {
4
4
  gitUserName,
5
5
  loadConfig,
6
6
  readTeamConfig
7
- } from "./chunk-AERAWOAK.js";
7
+ } from "./chunk-RXQH2THQ.js";
8
8
  import {
9
9
  ChangeMetaSchema,
10
10
  activeStages,
@@ -137,6 +137,61 @@ function isSubstantiveArtifactContent(content) {
137
137
  const meaningful = stripped.replace(/[-–—_.\s|#*`]/g, "").replace(/\{\{[^}]*\}\}/g, "").replace(/\b(TBD|TODO|N\/A|none|n\/a)\b/gi, "");
138
138
  return meaningful.length >= 32;
139
139
  }
140
+ function h2Title(line) {
141
+ const trimmed = line.trim();
142
+ if (!trimmed.startsWith("##") || trimmed.startsWith("###")) return null;
143
+ const rest = trimmed.slice(2);
144
+ if (!rest.startsWith(" ") && !rest.startsWith(" ")) return null;
145
+ const text = rest.trim();
146
+ return text.length > 0 ? text : null;
147
+ }
148
+ function isTaskStub(line) {
149
+ const text = line.replace(/^\s*(?:[-*+]|\d+\.)\s+/, "").replace(/^\[[ xX]\]\s*/, "").trim();
150
+ return /^Task \d+$/i.test(text);
151
+ }
152
+ function h2Sections(content) {
153
+ const buffers = /* @__PURE__ */ new Map();
154
+ let current = null;
155
+ for (const line of content.split(/\r?\n/)) {
156
+ const title = h2Title(line);
157
+ if (title) {
158
+ current = title;
159
+ if (!buffers.has(current)) buffers.set(current, []);
160
+ continue;
161
+ }
162
+ if (current) buffers.get(current)?.push(line);
163
+ }
164
+ const sections = /* @__PURE__ */ new Map();
165
+ for (const [heading, lines] of buffers) sections.set(heading, lines.join("\n"));
166
+ return sections;
167
+ }
168
+ function sectionHasLine(body) {
169
+ const rawLines = body.split(/\r?\n/);
170
+ for (let i = 0; i < rawLines.length; i++) {
171
+ const line = rawLines[i] ?? "";
172
+ const trimmed = line.trim();
173
+ if (!trimmed || /^Request:/.test(trimmed) || /^#{1,6}\s+/.test(trimmed)) continue;
174
+ if (isTableRow(trimmed)) {
175
+ const next = rawLines[i + 1]?.trim() ?? "";
176
+ if (isSeparatorRow(trimmed) || isSeparatorRow(next)) continue;
177
+ const kept = tableRowToText(trimmed);
178
+ if (!kept || isTaskStub(kept) || isInstructionalLine(kept)) continue;
179
+ return true;
180
+ }
181
+ if (isInstructionalLine(line) || isTaskStub(line)) continue;
182
+ return true;
183
+ }
184
+ return false;
185
+ }
186
+ function headingsFilled(content, headings) {
187
+ if (headings.length === 0) return true;
188
+ const sections = h2Sections(content);
189
+ for (const heading of headings) {
190
+ const body = sections.get(heading);
191
+ if (body === void 0 || !sectionHasLine(body)) return false;
192
+ }
193
+ return true;
194
+ }
140
195
  function incompleteArtifactReason(path, content) {
141
196
  if (content == null) {
142
197
  return `Missing required artifact: ${path}`;
@@ -970,7 +1025,7 @@ async function createChange(input) {
970
1025
  await materializeStageArtifacts(projectRoot, config, id, workflow, meta, firstStage);
971
1026
  await setActiveChange(projectRoot, config, id);
972
1027
  try {
973
- const { refreshActiveAgentContext } = await import("./agents-U5RVEZTX.js");
1028
+ const { refreshActiveAgentContext } = await import("./agents-SEF4S6EW.js");
974
1029
  await refreshActiveAgentContext(projectRoot);
975
1030
  } catch {
976
1031
  }
@@ -1072,7 +1127,7 @@ async function advanceStage(projectRoot, config, changeId, opts) {
1072
1127
  stage2
1073
1128
  );
1074
1129
  try {
1075
- const { refreshActiveAgentContext } = await import("./agents-U5RVEZTX.js");
1130
+ const { refreshActiveAgentContext } = await import("./agents-SEF4S6EW.js");
1076
1131
  await refreshActiveAgentContext(projectRoot);
1077
1132
  } catch {
1078
1133
  }
@@ -1129,7 +1184,7 @@ async function advanceStage(projectRoot, config, changeId, opts) {
1129
1184
  stage
1130
1185
  );
1131
1186
  try {
1132
- const { refreshActiveAgentContext } = await import("./agents-U5RVEZTX.js");
1187
+ const { refreshActiveAgentContext } = await import("./agents-SEF4S6EW.js");
1133
1188
  await refreshActiveAgentContext(projectRoot);
1134
1189
  } catch {
1135
1190
  }
@@ -1262,7 +1317,7 @@ async function completeChange(projectRoot, config, changeId) {
1262
1317
  let promoted;
1263
1318
  if (ctx.meta.workflow === "greenfield" || ctx.meta.flags?.greenfield === true) {
1264
1319
  try {
1265
- const { promoteGreenfieldToMemory: promoteGreenfieldToMemory2 } = await import("./greenfield-QTMU2MH6.js");
1320
+ const { promoteGreenfieldToMemory: promoteGreenfieldToMemory2 } = await import("./greenfield-6I2ML2ZB.js");
1266
1321
  promoted = await promoteGreenfieldToMemory2(projectRoot, config, changeId);
1267
1322
  } catch {
1268
1323
  }
@@ -1555,6 +1610,8 @@ export {
1555
1610
  assertSessionLogAllowed,
1556
1611
  importSessionMetrics,
1557
1612
  isSubstantiveArtifactContent,
1613
+ h2Title,
1614
+ headingsFilled,
1558
1615
  recordSignoff,
1559
1616
  recordDecisionRequest,
1560
1617
  incompletePriorStageErrors,
@@ -0,0 +1,153 @@
1
+ import {
2
+ interpolate
3
+ } from "./chunk-4BRO7BOJ.js";
4
+
5
+ // src/errors.ts
6
+ var SddError = class extends Error {
7
+ code;
8
+ hint;
9
+ exitCode;
10
+ constructor(message, options) {
11
+ super(message, options?.cause !== void 0 ? { cause: options.cause } : void 0);
12
+ this.name = "SddError";
13
+ this.code = options?.code ?? "SDD_ERROR";
14
+ this.hint = options?.hint;
15
+ this.exitCode = options?.exitCode ?? 1;
16
+ }
17
+ };
18
+ function isSddError(err) {
19
+ return err instanceof SddError;
20
+ }
21
+ function errorMessage(err) {
22
+ if (err instanceof Error) return err.message;
23
+ return String(err);
24
+ }
25
+
26
+ // src/env.ts
27
+ function toProcessEnv(base, extra) {
28
+ const out = {};
29
+ for (const [k, v] of Object.entries(base)) {
30
+ if (v !== void 0) out[k] = String(v);
31
+ }
32
+ if (extra) {
33
+ for (const [k, v] of Object.entries(extra)) {
34
+ if (v !== void 0) out[k] = String(v);
35
+ }
36
+ }
37
+ return out;
38
+ }
39
+
40
+ // src/version.ts
41
+ var SDD_CORE_VERSION = "0.23.0" ? "0.23.0" : "0.0.0-dev";
42
+
43
+ // src/mcp/client.ts
44
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
45
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
46
+ function mcpTimeoutMs() {
47
+ const raw = process.env.SDD_MCP_TIMEOUT_MS;
48
+ if (raw) {
49
+ const n = Number(raw);
50
+ if (Number.isFinite(n) && n > 0) return n;
51
+ }
52
+ return 3e4;
53
+ }
54
+ function contentToText(result) {
55
+ const parts = result.content ?? [];
56
+ return parts.map((p) => p.type === "text" ? p.text ?? "" : JSON.stringify(p)).join("\n").trim();
57
+ }
58
+ async function withTimeout(promise, ms, label) {
59
+ let timer;
60
+ try {
61
+ return await Promise.race([
62
+ promise,
63
+ new Promise((_, reject) => {
64
+ timer = setTimeout(() => {
65
+ reject(
66
+ new SddError(`MCP ${label} timed out after ${ms}ms`, {
67
+ code: "MCP_TIMEOUT",
68
+ hint: "Raise SDD_MCP_TIMEOUT_MS or fix the source server."
69
+ })
70
+ );
71
+ }, ms);
72
+ })
73
+ ]);
74
+ } finally {
75
+ if (timer) clearTimeout(timer);
76
+ }
77
+ }
78
+ async function withMcpSource(source, projectRoot, fn) {
79
+ const vars = { projectRoot };
80
+ const cwd = source.cwd ? interpolate(source.cwd, vars) : projectRoot;
81
+ const env = toProcessEnv(process.env, {
82
+ ...source.env,
83
+ SDD_PROJECT_ROOT: projectRoot
84
+ });
85
+ const transport = new StdioClientTransport({
86
+ command: source.command,
87
+ args: source.args,
88
+ cwd,
89
+ env
90
+ });
91
+ const client = new Client({
92
+ name: "sdd-mcp-client",
93
+ version: SDD_CORE_VERSION
94
+ });
95
+ const ms = mcpTimeoutMs();
96
+ await withTimeout(client.connect(transport), ms, `connect (${source.id})`);
97
+ try {
98
+ return await withTimeout(fn(client), ms, `call (${source.id})`);
99
+ } finally {
100
+ try {
101
+ await client.close();
102
+ } catch {
103
+ }
104
+ }
105
+ }
106
+ async function listMcpSourceTools(source, projectRoot) {
107
+ return withMcpSource(source, projectRoot, async (client) => {
108
+ const listed = await client.listTools();
109
+ return listed.tools.map((t) => ({
110
+ name: t.name,
111
+ description: t.description
112
+ }));
113
+ });
114
+ }
115
+ async function callMcpSourceTool(source, projectRoot, tool, args) {
116
+ try {
117
+ if (source.tools?.length && !source.tools.includes(tool)) {
118
+ return {
119
+ ok: false,
120
+ text: "",
121
+ error: `Tool "${tool}" not in allowlist for source ${source.id}: ${source.tools.join(", ")}`
122
+ };
123
+ }
124
+ return await withMcpSource(source, projectRoot, async (client) => {
125
+ const result = await client.callTool({ name: tool, arguments: args });
126
+ const text = contentToText(result);
127
+ const isError = Boolean(result.isError);
128
+ return {
129
+ ok: !isError,
130
+ text: text || (isError ? "(empty error result)" : "(empty)"),
131
+ error: isError ? text || "tool returned isError" : void 0
132
+ };
133
+ });
134
+ } catch (err) {
135
+ return {
136
+ ok: false,
137
+ text: "",
138
+ error: err instanceof Error ? err.message : String(err)
139
+ };
140
+ }
141
+ }
142
+
143
+ export {
144
+ SddError,
145
+ isSddError,
146
+ errorMessage,
147
+ toProcessEnv,
148
+ SDD_CORE_VERSION,
149
+ mcpTimeoutMs,
150
+ withMcpSource,
151
+ listMcpSourceTools,
152
+ callMcpSourceTool
153
+ };
@@ -1,130 +1,10 @@
1
1
  import {
2
- interpolate,
2
+ callMcpSourceTool
3
+ } from "./chunk-OY47H6R5.js";
4
+ import {
3
5
  interpolateArgs,
4
6
  loadMcpConfig
5
7
  } from "./chunk-4BRO7BOJ.js";
6
- import {
7
- SddError
8
- } from "./chunk-MHODNFIL.js";
9
-
10
- // src/mcp/client.ts
11
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
12
- import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
13
-
14
- // src/env.ts
15
- function toProcessEnv(base, extra) {
16
- const out = {};
17
- for (const [k, v] of Object.entries(base)) {
18
- if (v !== void 0) out[k] = String(v);
19
- }
20
- if (extra) {
21
- for (const [k, v] of Object.entries(extra)) {
22
- if (v !== void 0) out[k] = String(v);
23
- }
24
- }
25
- return out;
26
- }
27
-
28
- // src/version.ts
29
- var SDD_CORE_VERSION = "0.21.0" ? "0.21.0" : "0.0.0-dev";
30
-
31
- // src/mcp/client.ts
32
- function mcpTimeoutMs() {
33
- const raw = process.env.SDD_MCP_TIMEOUT_MS;
34
- if (raw) {
35
- const n = Number(raw);
36
- if (Number.isFinite(n) && n > 0) return n;
37
- }
38
- return 3e4;
39
- }
40
- function contentToText(result) {
41
- const parts = result.content ?? [];
42
- return parts.map((p) => p.type === "text" ? p.text ?? "" : JSON.stringify(p)).join("\n").trim();
43
- }
44
- async function withTimeout(promise, ms, label) {
45
- let timer;
46
- try {
47
- return await Promise.race([
48
- promise,
49
- new Promise((_, reject) => {
50
- timer = setTimeout(() => {
51
- reject(
52
- new SddError(`MCP ${label} timed out after ${ms}ms`, {
53
- code: "MCP_TIMEOUT",
54
- hint: "Raise SDD_MCP_TIMEOUT_MS or fix the source server."
55
- })
56
- );
57
- }, ms);
58
- })
59
- ]);
60
- } finally {
61
- if (timer) clearTimeout(timer);
62
- }
63
- }
64
- async function withMcpSource(source, projectRoot, fn) {
65
- const vars = { projectRoot };
66
- const cwd = source.cwd ? interpolate(source.cwd, vars) : projectRoot;
67
- const env = toProcessEnv(process.env, {
68
- ...source.env,
69
- SDD_PROJECT_ROOT: projectRoot
70
- });
71
- const transport = new StdioClientTransport({
72
- command: source.command,
73
- args: source.args,
74
- cwd,
75
- env
76
- });
77
- const client = new Client({
78
- name: "sdd-mcp-client",
79
- version: SDD_CORE_VERSION
80
- });
81
- const ms = mcpTimeoutMs();
82
- await withTimeout(client.connect(transport), ms, `connect (${source.id})`);
83
- try {
84
- return await withTimeout(fn(client), ms, `call (${source.id})`);
85
- } finally {
86
- try {
87
- await client.close();
88
- } catch {
89
- }
90
- }
91
- }
92
- async function listMcpSourceTools(source, projectRoot) {
93
- return withMcpSource(source, projectRoot, async (client) => {
94
- const listed = await client.listTools();
95
- return listed.tools.map((t) => ({
96
- name: t.name,
97
- description: t.description
98
- }));
99
- });
100
- }
101
- async function callMcpSourceTool(source, projectRoot, tool, args) {
102
- try {
103
- if (source.tools?.length && !source.tools.includes(tool)) {
104
- return {
105
- ok: false,
106
- text: "",
107
- error: `Tool "${tool}" not in allowlist for source ${source.id}: ${source.tools.join(", ")}`
108
- };
109
- }
110
- return await withMcpSource(source, projectRoot, async (client) => {
111
- const result = await client.callTool({ name: tool, arguments: args });
112
- const text = contentToText(result);
113
- const isError = Boolean(result.isError);
114
- return {
115
- ok: !isError,
116
- text: text || (isError ? "(empty error result)" : "(empty)"),
117
- error: isError ? text || "tool returned isError" : void 0
118
- };
119
- });
120
- } catch (err) {
121
- return {
122
- ok: false,
123
- text: "",
124
- error: err instanceof Error ? err.message : String(err)
125
- };
126
- }
127
- }
128
8
 
129
9
  // src/mcp/match.ts
130
10
  function includesCI(list, value) {
@@ -266,12 +146,6 @@ function listMatchingSourceIds(sources, match) {
266
146
  }
267
147
 
268
148
  export {
269
- toProcessEnv,
270
- SDD_CORE_VERSION,
271
- mcpTimeoutMs,
272
- withMcpSource,
273
- listMcpSourceTools,
274
- callMcpSourceTool,
275
149
  matchMcpSources,
276
150
  explainMatch,
277
151
  gatherMcpContext,