@stdd/plugin 0.9.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 (80) hide show
  1. package/.claude-plugin/plugin.json +9 -0
  2. package/.codex-plugin/plugin.json +21 -0
  3. package/LICENSE +21 -0
  4. package/README.md +47 -0
  5. package/extensions/stdd.mjs +77 -0
  6. package/hooks/claude-hooks.json +28 -0
  7. package/hooks/codex-hooks.json +28 -0
  8. package/package.json +38 -0
  9. package/runtime/adapters/README.md +158 -0
  10. package/runtime/cli/check.mjs +555 -0
  11. package/runtime/cli/ci.mjs +190 -0
  12. package/runtime/cli/claude-hooks.mjs +689 -0
  13. package/runtime/cli/config.mjs +27 -0
  14. package/runtime/cli/evidence.mjs +249 -0
  15. package/runtime/cli/generated-files.mjs +1693 -0
  16. package/runtime/cli/held-fs.mjs +415 -0
  17. package/runtime/cli/init.mjs +883 -0
  18. package/runtime/cli/ledger.mjs +1470 -0
  19. package/runtime/cli/lib.mjs +909 -0
  20. package/runtime/cli/path-bytes.mjs +83 -0
  21. package/runtime/cli/policy.mjs +112 -0
  22. package/runtime/cli/recorders.mjs +188 -0
  23. package/runtime/cli/review-fs.mjs +825 -0
  24. package/runtime/cli/review.mjs +1065 -0
  25. package/runtime/cli/runtime.mjs +32 -0
  26. package/runtime/cli/scope.mjs +185 -0
  27. package/runtime/cli/snapshot.mjs +897 -0
  28. package/runtime/cli/state-validation.mjs +168 -0
  29. package/runtime/cli/status.mjs +580 -0
  30. package/runtime/cli/stdd.mjs +536 -0
  31. package/runtime/cli/worker-fs.mjs +971 -0
  32. package/runtime/cli/worker-metadata.mjs +139 -0
  33. package/runtime/cli/worker.mjs +779 -0
  34. package/runtime/method/README.md +634 -0
  35. package/runtime/method/reference-commands.md +147 -0
  36. package/runtime/method/reference-generated-state.md +151 -0
  37. package/runtime/method/reference-integration.md +233 -0
  38. package/runtime/package.json +65 -0
  39. package/runtime/playbooks/brainstorming.md +46 -0
  40. package/runtime/playbooks/debugging.md +36 -0
  41. package/runtime/playbooks/delegate-slice.md +129 -0
  42. package/runtime/playbooks/finish-change.md +46 -0
  43. package/runtime/playbooks/implement.md +26 -0
  44. package/runtime/playbooks/investigation.md +33 -0
  45. package/runtime/playbooks/managed-playbooks.json +14 -0
  46. package/runtime/playbooks/planning.md +177 -0
  47. package/runtime/playbooks/pr-green.md +50 -0
  48. package/runtime/playbooks/start-change.md +37 -0
  49. package/runtime/playbooks/worktrees.md +45 -0
  50. package/runtime/prebuilds/stdd-fs/darwin-arm64/stdd-fs +0 -0
  51. package/runtime/prebuilds/stdd-fs/darwin-x64/stdd-fs +0 -0
  52. package/runtime/prebuilds/stdd-fs/linux-arm64/stdd-fs +0 -0
  53. package/runtime/prebuilds/stdd-fs/linux-x64/stdd-fs +0 -0
  54. package/runtime/prebuilds/stdd-fs/manifest.json +47 -0
  55. package/runtime/prebuilds/stdd-fs/win32-arm64/stdd-fs.exe +0 -0
  56. package/runtime/prebuilds/stdd-fs/win32-x64/stdd-fs.exe +0 -0
  57. package/runtime/sdk/adapters.mjs +279 -0
  58. package/runtime/sdk/file-observation.mjs +12 -0
  59. package/runtime/sdk/index.d.ts +140 -0
  60. package/runtime/sdk/index.mjs +31 -0
  61. package/runtime/sdk/native-fs.mjs +1235 -0
  62. package/runtime/sdk/path.mjs +71 -0
  63. package/runtime/sdk/text.mjs +42 -0
  64. package/runtime/sdk/workflow.mjs +294 -0
  65. package/runtime/templates/deferred-design.md +47 -0
  66. package/runtime/templates/github-stdd.yml +42 -0
  67. package/runtime/templates/gitlab-stdd.yml +72 -0
  68. package/runtime/templates/pr-description.md +35 -0
  69. package/scripts/adopting-root.mjs +42 -0
  70. package/scripts/stdd-hook.mjs +72 -0
  71. package/skills/stdd-brainstorming/SKILL.md +48 -0
  72. package/skills/stdd-debugging/SKILL.md +38 -0
  73. package/skills/stdd-delegate-slice/SKILL.md +118 -0
  74. package/skills/stdd-finish-change/SKILL.md +40 -0
  75. package/skills/stdd-implement/SKILL.md +28 -0
  76. package/skills/stdd-investigation/SKILL.md +35 -0
  77. package/skills/stdd-planning/SKILL.md +165 -0
  78. package/skills/stdd-pr-green/SKILL.md +52 -0
  79. package/skills/stdd-start-change/SKILL.md +39 -0
  80. package/skills/stdd-worktrees/SKILL.md +46 -0
@@ -0,0 +1,279 @@
1
+ import { assertRepoRelativePath, assertSkillName } from "./path.mjs";
2
+ import { assertPrintableSingleLine } from "./text.mjs";
3
+
4
+ const SEMVER_PATTERN =
5
+ /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u;
6
+ const CI_STAMP_PLACEHOLDER = "__STAMP__";
7
+ const CI_VERSION_PLACEHOLDER = "__VERSION__";
8
+ const CI_PLACEHOLDER_PATTERN = /__[A-Z][A-Z0-9_]*__/u;
9
+ export const CROSS_CLI_REVIEW_VIA_TOKEN = "{{STDD_CROSS_CLI_REVIEW_VIA}}";
10
+ const CROSS_CLI_REVIEW_VIAS = new Set(["claude", "codex"]);
11
+
12
+ const deepFreeze = (value) => {
13
+ for (const child of Object.values(value)) {
14
+ if (child && typeof child === "object") deepFreeze(child);
15
+ }
16
+ return Object.freeze(value);
17
+ };
18
+
19
+ export const MANDATORY_ROUTING_SKILLS = deepFreeze([
20
+ "stdd-start-change",
21
+ "stdd-implement",
22
+ "stdd-finish-change",
23
+ ]);
24
+
25
+ function requireString(value, field) {
26
+ if (typeof value !== "string" || value === "") {
27
+ throw new TypeError(`${field} must be a non-empty string`);
28
+ }
29
+ return value;
30
+ }
31
+
32
+ function requireCommentText(value, field) {
33
+ const candidate = assertPrintableSingleLine(value, field);
34
+ if (candidate.includes("-->")) {
35
+ throw new TypeError(`${field} must not close an HTML comment`);
36
+ }
37
+ return candidate;
38
+ }
39
+
40
+ function requireInlineCode(value, field) {
41
+ const candidate = assertPrintableSingleLine(value, field);
42
+ if (candidate.includes("`")) {
43
+ throw new TypeError(`${field} must not contain backticks`);
44
+ }
45
+ return candidate;
46
+ }
47
+
48
+ export function assertSemanticVersion(value, field) {
49
+ const candidate = assertPrintableSingleLine(value, field);
50
+ const match = SEMVER_PATTERN.exec(candidate);
51
+ const hasZeroPaddedPrereleaseNumber = match?.[1]
52
+ ?.split(".")
53
+ .some(
54
+ (identifier) => identifier.length > 1 && identifier.startsWith("0") && /^\d+$/u.test(identifier),
55
+ );
56
+ if (!match || hasZeroPaddedPrereleaseNumber) {
57
+ throw new TypeError(`${field} must be a semantic version`);
58
+ }
59
+ return candidate;
60
+ }
61
+
62
+ function requireRepoPath(value, field) {
63
+ return assertRepoRelativePath(value, field);
64
+ }
65
+
66
+ function requirePrefix(value) {
67
+ const prefix = assertPrintableSingleLine(value, "agent adapter explicitPrefix");
68
+ if (/\s|`/u.test(prefix)) {
69
+ throw new TypeError(
70
+ "agent adapter explicitPrefix must not contain whitespace, controls, or backticks",
71
+ );
72
+ }
73
+ return prefix;
74
+ }
75
+
76
+ export function defineAgentAdapter(adapter) {
77
+ const crossCliReviewVia = adapter?.crossCliReviewVia ?? null;
78
+ if (crossCliReviewVia !== null && !CROSS_CLI_REVIEW_VIAS.has(crossCliReviewVia)) {
79
+ throw new TypeError('agent adapter crossCliReviewVia must be "claude", "codex", or null');
80
+ }
81
+ const copy = {
82
+ id: assertSkillName(adapter?.id, "agent adapter id"),
83
+ skillRoot: requireRepoPath(adapter?.skillRoot, "agent adapter skillRoot"),
84
+ instructionsFile: requireRepoPath(adapter?.instructionsFile, "agent adapter instructionsFile"),
85
+ snippetFile: requireRepoPath(adapter?.snippetFile, "agent adapter snippetFile"),
86
+ explicitPrefix: requirePrefix(adapter?.explicitPrefix),
87
+ hooksFile: requireRepoPath(adapter?.hooksFile, "agent adapter hooksFile"),
88
+ crossCliReviewVia,
89
+ };
90
+ return deepFreeze(copy);
91
+ }
92
+
93
+ export function defineCiAdapter(adapter) {
94
+ const id = assertSkillName(adapter?.id, "CI adapter id");
95
+ const outputIsNull = adapter?.outputFile === null;
96
+ const templateIsNull = adapter?.templateFile === null;
97
+ if (outputIsNull !== templateIsNull) {
98
+ throw new TypeError("CI adapter outputFile and templateFile must both be null or both be paths");
99
+ }
100
+ const copy = {
101
+ id,
102
+ outputFile: outputIsNull ? null : requireRepoPath(adapter?.outputFile, "CI adapter outputFile"),
103
+ templateFile: templateIsNull
104
+ ? null
105
+ : requireRepoPath(adapter?.templateFile, "CI adapter templateFile"),
106
+ };
107
+ return deepFreeze(copy);
108
+ }
109
+
110
+ export const AGENT_ADAPTERS = deepFreeze({
111
+ claude: defineAgentAdapter({
112
+ id: "claude",
113
+ skillRoot: ".claude/skills",
114
+ instructionsFile: "CLAUDE.md",
115
+ snippetFile: ".stdd/CLAUDE-snippet.md",
116
+ explicitPrefix: "/",
117
+ hooksFile: ".claude/settings.json",
118
+ crossCliReviewVia: "codex",
119
+ }),
120
+ codex: defineAgentAdapter({
121
+ id: "codex",
122
+ skillRoot: ".agents/skills",
123
+ instructionsFile: "AGENTS.md",
124
+ snippetFile: ".stdd/AGENTS-snippet.md",
125
+ explicitPrefix: "$",
126
+ hooksFile: ".codex/hooks.json",
127
+ crossCliReviewVia: "claude",
128
+ }),
129
+ pi: defineAgentAdapter({
130
+ id: "pi",
131
+ skillRoot: ".agents/skills",
132
+ instructionsFile: ".pi/APPEND_SYSTEM.md",
133
+ snippetFile: ".stdd/PI-snippet.md",
134
+ explicitPrefix: "/skill:",
135
+ hooksFile: ".pi/extensions/stdd.js",
136
+ crossCliReviewVia: "claude",
137
+ }),
138
+ });
139
+
140
+ export const CI_ADAPTERS = deepFreeze({
141
+ github: defineCiAdapter({
142
+ id: "github",
143
+ outputFile: ".github/workflows/stdd.yml",
144
+ templateFile: "github-stdd.yml",
145
+ }),
146
+ gitlab: defineCiAdapter({
147
+ id: "gitlab",
148
+ outputFile: ".gitlab/stdd.gitlab-ci.yml",
149
+ templateFile: "gitlab-stdd.yml",
150
+ }),
151
+ generic: defineCiAdapter({
152
+ id: "generic",
153
+ outputFile: null,
154
+ templateFile: null,
155
+ }),
156
+ });
157
+
158
+ export function getAgentAdapter(id) {
159
+ if (!Object.hasOwn(AGENT_ADAPTERS, id)) {
160
+ throw new Error(`unknown agent adapter ${JSON.stringify(id)}`);
161
+ }
162
+ return AGENT_ADAPTERS[id];
163
+ }
164
+
165
+ export function getCiAdapter(id) {
166
+ if (!Object.hasOwn(CI_ADAPTERS, id)) {
167
+ throw new Error(`unknown CI adapter ${JSON.stringify(id)}`);
168
+ }
169
+ return CI_ADAPTERS[id];
170
+ }
171
+
172
+ function resolveAgentAdapter(adapter) {
173
+ return typeof adapter === "string" ? getAgentAdapter(adapter) : defineAgentAdapter(adapter);
174
+ }
175
+
176
+ export function renderAgentSkill({ adapter: adapterInput, name, description, when, body, stamp }) {
177
+ const safeName = assertSkillName(name, "agent skill name");
178
+ const safeDescription = assertPrintableSingleLine(description, "agent skill description");
179
+ let safeBody = requireString(body, "agent skill body");
180
+ const safeStamp = requireCommentText(stamp, "agent skill stamp");
181
+ const safeWhen = when === undefined ? null : assertPrintableSingleLine(when, "agent skill when");
182
+ const adapter = adapterInput === undefined ? null : resolveAgentAdapter(adapterInput);
183
+ if (safeBody.includes(CROSS_CLI_REVIEW_VIA_TOKEN)) {
184
+ if (!adapter?.crossCliReviewVia) {
185
+ throw new TypeError(
186
+ "agent skill adapter must define crossCliReviewVia to resolve the cross-CLI reviewer token",
187
+ );
188
+ }
189
+ safeBody = safeBody.replaceAll(CROSS_CLI_REVIEW_VIA_TOKEN, adapter.crossCliReviewVia);
190
+ }
191
+ const routedDescription = safeWhen ? `${safeDescription}. Use when: ${safeWhen}` : safeDescription;
192
+ return (
193
+ `---\nname: ${safeName}\ndescription: ${JSON.stringify(routedDescription)}\n---\n\n` +
194
+ `<!-- ${safeStamp} -->\n\n${safeBody}`
195
+ );
196
+ }
197
+
198
+ export function renderAgentInstructions({
199
+ adapter: adapterInput,
200
+ stamp,
201
+ npmRunner,
202
+ crossCli,
203
+ projectLogEnabled = true,
204
+ }) {
205
+ const adapter = resolveAgentAdapter(adapterInput);
206
+ const safeStamp = requireCommentText(stamp, "agent instructions stamp");
207
+ const safeNpmRunner = requireInlineCode(npmRunner, "agent instructions npmRunner");
208
+ if (typeof crossCli !== "boolean") {
209
+ throw new TypeError("agent instructions crossCli must be a boolean");
210
+ }
211
+ if (typeof projectLogEnabled !== "boolean") {
212
+ throw new TypeError("agent instructions projectLogEnabled must be a boolean");
213
+ }
214
+ const invoke = (name) => `\`${adapter.explicitPrefix}${name}\``;
215
+ const [startChange, implement, finishChange] = MANDATORY_ROUTING_SKILLS;
216
+ return [
217
+ `<!-- ${safeStamp} -->`,
218
+ "",
219
+ "## STDD",
220
+ "",
221
+ "This repository follows `.stdd/method.md`. Before any repository change",
222
+ "(behavior, implementation-only work, fixes, refactors, or investigation),",
223
+ `invoke ${invoke(startChange)}; use ${invoke(implement)} for`,
224
+ `the docs/red/green/verify slice and ${invoke(finishChange)} to close it.`,
225
+ "",
226
+ ...(projectLogEnabled
227
+ ? [
228
+ "Do not search the project log (dated entries marked",
229
+ "`authority: non-canonical`, e.g. `docs/project/`) unless the user",
230
+ "explicitly asks for historical rationale or deferred work.",
231
+ ]
232
+ : [
233
+ "This repository does not use a project log. Do not create or search",
234
+ "dated decision, design, or deferred-work archives. Keep current behavior",
235
+ "in canonical docs; use PR descriptions and git history for rationale.",
236
+ ]),
237
+ "",
238
+ "If `stdd` is not on PATH, use the project-local runner",
239
+ `(\`pnpm exec stdd\`, \`${safeNpmRunner}\`). Installed npm fallbacks must pin`,
240
+ "the exact scoped `@stdd/cli` version. Never resolve the unrelated",
241
+ "unscoped registry package `stdd`.",
242
+ "",
243
+ "Read project policy with `stdd policy show` before asking for a decision",
244
+ "it may already answer. That view is the enforcing one: it lists only the",
245
+ "grants this kit honors, each naming a condition to verify before acting.",
246
+ "Reading `.stdd/policy.md` directly trusts whatever the file happens to say;",
247
+ "there, only `## Permissions` entries ever grant authority.",
248
+ ...(crossCli
249
+ ? adapter.id === "pi"
250
+ ? [
251
+ "",
252
+ "Pi and Claude Code may invoke each other for a bounded, read-only",
253
+ "review or delegated slice when the applicable skill requests it.",
254
+ ]
255
+ : [
256
+ "",
257
+ "Claude Code and Codex may invoke each other for a bounded, read-only",
258
+ "review or delegated slice when the applicable skill requests it.",
259
+ ]
260
+ : []),
261
+ "",
262
+ ].join("\n");
263
+ }
264
+
265
+ export function renderCiTemplate(template, { stamp, version }) {
266
+ const safeTemplate = requireString(template, "CI template");
267
+ const safeStamp = assertPrintableSingleLine(stamp, "CI stamp");
268
+ const safeVersion = assertSemanticVersion(version, "CI version");
269
+ if (!safeTemplate.includes(CI_STAMP_PLACEHOLDER) || !safeTemplate.includes(CI_VERSION_PLACEHOLDER)) {
270
+ throw new TypeError("CI template must contain __STAMP__ and __VERSION__ placeholders");
271
+ }
272
+ const rendered = safeTemplate.replace(/__STAMP__|__VERSION__/gu, (placeholder) =>
273
+ placeholder === CI_STAMP_PLACEHOLDER ? safeStamp : safeVersion,
274
+ );
275
+ if (CI_PLACEHOLDER_PATTERN.test(rendered)) {
276
+ throw new TypeError("CI template contains an unresolved placeholder");
277
+ }
278
+ return rendered;
279
+ }
@@ -0,0 +1,12 @@
1
+ export function sameFileIdentity(left, right) {
2
+ return left?.dev === right?.dev && left?.ino === right?.ino;
3
+ }
4
+
5
+ export function sameFileObservation(left, right) {
6
+ return ["dev", "ino", "mode", "nlink", "size", "mtimeNs", "ctimeNs"].every(
7
+ (field) =>
8
+ typeof left?.[field] === "bigint" &&
9
+ typeof right?.[field] === "bigint" &&
10
+ left[field] === right[field],
11
+ );
12
+ }
@@ -0,0 +1,140 @@
1
+ export interface StddCapabilities {
2
+ subagents: boolean;
3
+ crossCli: boolean;
4
+ worktrees: boolean;
5
+ }
6
+
7
+ export interface StddConfig {
8
+ forbiddenArtifacts: string[];
9
+ canonicalDocs: string[];
10
+ temporalPhrases: string[];
11
+ readiness: { required: Array<{ path: string; hint?: string }> };
12
+ contentRules: Array<{
13
+ name: string;
14
+ files: string;
15
+ forbid?: string;
16
+ require?: string;
17
+ message?: string;
18
+ newFilesOnly?: boolean;
19
+ }>;
20
+ projectLog: { enabled: boolean };
21
+ capabilities: StddCapabilities;
22
+ review: { via: "subagent" | "codex" | "claude"; maxRounds: number };
23
+ baseRef?: string;
24
+ redPattern?: string | null;
25
+ branchPattern?: string | null;
26
+ }
27
+
28
+ export type StddConfigInput = Partial<Omit<StddConfig, "capabilities" | "projectLog" | "review">> & {
29
+ capabilities?: Partial<StddCapabilities>;
30
+ projectLog?: Partial<StddConfig["projectLog"]>;
31
+ review?: Partial<StddConfig["review"]>;
32
+ };
33
+
34
+ export type DeepReadonly<T> =
35
+ T extends ReadonlyArray<infer Item>
36
+ ? ReadonlyArray<DeepReadonly<Item>>
37
+ : T extends object
38
+ ? { readonly [Key in keyof T]: DeepReadonly<T[Key]> }
39
+ : T;
40
+
41
+ export const STDD_VERSION: string;
42
+ export const DEFAULT_CONFIG: DeepReadonly<StddConfig>;
43
+ export interface AgentAdapter {
44
+ readonly id: string;
45
+ readonly skillRoot: string;
46
+ readonly instructionsFile: string;
47
+ readonly snippetFile: string;
48
+ readonly explicitPrefix: string;
49
+ readonly hooksFile: string;
50
+ readonly crossCliReviewVia?: "codex" | "claude" | null;
51
+ }
52
+ export interface CiAdapter {
53
+ readonly id: string;
54
+ readonly outputFile: string | null;
55
+ readonly templateFile: string | null;
56
+ }
57
+ export const AGENT_ADAPTERS: DeepReadonly<Record<"claude" | "codex" | "pi", AgentAdapter>>;
58
+ export const CI_ADAPTERS: DeepReadonly<Record<"github" | "gitlab" | "generic", CiAdapter>>;
59
+ export function defineAgentAdapter(adapter: AgentAdapter): DeepReadonly<AgentAdapter>;
60
+ export function defineCiAdapter(adapter: CiAdapter): DeepReadonly<CiAdapter>;
61
+ export function getAgentAdapter(id: string): AgentAdapter;
62
+ export function getCiAdapter(id: string): CiAdapter;
63
+ export function renderAgentSkill(input: {
64
+ adapter?: string | AgentAdapter;
65
+ name: string;
66
+ description: string;
67
+ when?: string;
68
+ body: string;
69
+ stamp: string;
70
+ }): string;
71
+ export function renderAgentInstructions(input: {
72
+ adapter: string | AgentAdapter;
73
+ stamp: string;
74
+ npmRunner: string;
75
+ crossCli: boolean;
76
+ projectLogEnabled?: boolean;
77
+ }): string;
78
+ export function renderCiTemplate(template: string, input: { stamp: string; version: string }): string;
79
+ export function assertSkillName(name: string, label?: string): string;
80
+ export function isPrintableSingleLine(value: unknown): value is string;
81
+ export function assertPrintableSingleLine(value: unknown, label?: string): string;
82
+ export function resolveRepoPath(root: string, relative: string, label?: string): string;
83
+ export function resolveWritableRepoPath(root: string, relative: string, label?: string): string;
84
+ export function deriveLoopState(
85
+ events: Array<Record<string, unknown>>,
86
+ currentSnapshot: string,
87
+ nonDocChanged?: boolean,
88
+ ): {
89
+ lastRedIdx: number;
90
+ redEvent: Record<string, unknown> | null;
91
+ redLegacy: boolean;
92
+ recordedVerify: Record<string, unknown> | null;
93
+ verifyEvent: Record<string, unknown> | null;
94
+ verifyStale: boolean;
95
+ implementationObserved: boolean;
96
+ loop: {
97
+ red: Record<string, unknown> & { done: boolean };
98
+ impl: { done: boolean };
99
+ verify: Record<string, unknown> & { done: boolean; stale?: boolean };
100
+ };
101
+ };
102
+ export function deriveTaskState(events: unknown):
103
+ | { state: "legacy"; task: null }
104
+ | { state: "idle"; task: null; boundary: Record<string, unknown> }
105
+ | {
106
+ state: "invalid";
107
+ task: null;
108
+ boundary: unknown;
109
+ reason: string;
110
+ }
111
+ | {
112
+ state: "active";
113
+ task: {
114
+ id: string;
115
+ name: string;
116
+ branch: string | undefined;
117
+ startedAt: string | undefined;
118
+ planBaseline: string | null;
119
+ };
120
+ boundary: Record<string, unknown>;
121
+ };
122
+ export function scopeTaskEvents(events: unknown): {
123
+ state: ReturnType<typeof deriveTaskState>;
124
+ events: Array<Record<string, unknown>>;
125
+ };
126
+ export function mergeConfig(config: StddConfigInput): StddConfig;
127
+ export function extractDocPaths(content: string): string[];
128
+ export function parseLedger(text: string): Array<Record<string, unknown>>;
129
+ export function parsePlan(text: string): {
130
+ items: Array<{
131
+ line: number;
132
+ checked: boolean;
133
+ text: string;
134
+ red: string | null;
135
+ review: boolean;
136
+ }>;
137
+ deferred: string[];
138
+ mode: "inline" | "delegated" | null;
139
+ };
140
+ export function sha256(content: string | Uint8Array): string;
@@ -0,0 +1,31 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ export {
6
+ DEFAULT_CONFIG,
7
+ extractDocPaths,
8
+ mergeConfig,
9
+ parseLedger,
10
+ parsePlan,
11
+ sha256,
12
+ } from "../cli/lib.mjs";
13
+ export {
14
+ AGENT_ADAPTERS,
15
+ CI_ADAPTERS,
16
+ defineAgentAdapter,
17
+ defineCiAdapter,
18
+ getAgentAdapter,
19
+ getCiAdapter,
20
+ renderAgentInstructions,
21
+ renderAgentSkill,
22
+ renderCiTemplate,
23
+ } from "./adapters.mjs";
24
+ export { assertSkillName, resolveRepoPath, resolveWritableRepoPath } from "./path.mjs";
25
+ export { assertPrintableSingleLine, isPrintableSingleLine } from "./text.mjs";
26
+ export { deriveLoopState, deriveTaskState, scopeTaskEvents } from "./workflow.mjs";
27
+
28
+ const SDK_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
29
+ export const STDD_VERSION = JSON.parse(
30
+ fs.readFileSync(path.join(SDK_ROOT, "package.json"), "utf8"),
31
+ ).version;