@jstn-sdk/ma 0.1.11 → 0.1.12

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 (133) hide show
  1. package/.agents/plugins/marketplace.json +0 -0
  2. package/README.md +136 -29
  3. package/bin/ma.js +23 -67
  4. package/docs/README.md +4 -1
  5. package/docs/assets/image/Screenshot(1).png +0 -0
  6. package/docs/assets/image/Screenshot(2).png +0 -0
  7. package/docs/assets/image/Screenshot(3).png +0 -0
  8. package/docs/assets/image/Screenshot(4).png +0 -0
  9. package/docs/assets/image/Screenshot(5).png +0 -0
  10. package/docs/assets/image/Screenshot(6).png +0 -0
  11. package/docs/assets/image/Screenshot(7).png +0 -0
  12. package/docs/assets/image/Screenshot(8).png +0 -0
  13. package/docs/assets/image/Screenshot(9).png +0 -0
  14. package/docs/assets/meta-architect-logo.png +0 -0
  15. package/docs/assets/meta-architect-logo.svg +0 -0
  16. package/docs/getting-started.md +74 -19
  17. package/docs/installed-sdk.md +23 -0
  18. package/docs/mcp-setup.md +30 -1
  19. package/docs/qa/{release-readiness-0.1.11.md → release-readiness-0.1.12.md} +29 -8
  20. package/docs/qa/release-readiness-0.1.5.md +0 -0
  21. package/docs/reference/native-engineering-patterns.md +35 -0
  22. package/docs/reference/native-security-playbooks.md +21 -0
  23. package/docs/reference/native-source-selection.md +21 -0
  24. package/docs/reference/native-style-and-deslop.md +20 -0
  25. package/docs/release-spec.md +21 -10
  26. package/docs/skills-publishing.md +25 -1
  27. package/docs/skills.md +24 -12
  28. package/mcp/local/code-intel.js +113 -0
  29. package/mcp/local/memory.js +46 -0
  30. package/mcp/local/playbooks.js +168 -0
  31. package/mcp/local/state.js +71 -0
  32. package/mcp/local/team-run.js +66 -0
  33. package/mcp/local/trace.js +60 -0
  34. package/mcp/local-capabilities.json +56 -0
  35. package/mcp/native-playbooks.json +117 -0
  36. package/mcp/servers.json +10 -0
  37. package/package.json +4 -1
  38. package/plugins/meta-architect/.app.json +1 -1
  39. package/plugins/meta-architect/.codex-plugin/plugin.json +4 -4
  40. package/plugins/meta-architect/.mcp.json +1 -1
  41. package/plugins/meta-architect/README.md +27 -1
  42. package/plugins/meta-architect/skills/align/SKILL.md +24 -0
  43. package/plugins/meta-architect/skills/align/agents/openai.yaml +4 -0
  44. package/plugins/meta-architect/skills/align/references/shared-language.md +24 -0
  45. package/plugins/meta-architect/skills/arch/SKILL.md +0 -0
  46. package/plugins/meta-architect/skills/arch/agents/openai.yaml +0 -0
  47. package/plugins/meta-architect/skills/build/SKILL.md +0 -0
  48. package/plugins/meta-architect/skills/build/agents/openai.yaml +0 -0
  49. package/plugins/meta-architect/skills/cleanup/SKILL.md +23 -0
  50. package/plugins/meta-architect/skills/cleanup/agents/openai.yaml +4 -0
  51. package/plugins/meta-architect/skills/cleanup/references/style-and-deslop.md +18 -0
  52. package/plugins/meta-architect/skills/diagnose/SKILL.md +24 -0
  53. package/plugins/meta-architect/skills/diagnose/agents/openai.yaml +4 -0
  54. package/plugins/meta-architect/skills/flow/SKILL.md +0 -0
  55. package/plugins/meta-architect/skills/flow/agents/openai.yaml +0 -0
  56. package/plugins/meta-architect/skills/maestro/SKILL.md +36 -3
  57. package/plugins/meta-architect/skills/maestro/agents/openai.yaml +2 -2
  58. package/plugins/meta-architect/skills/{meta-architect → maestro}/references/core-release-rules.md +0 -0
  59. package/plugins/meta-architect/skills/maestro/references/native-ingest-map.md +44 -0
  60. package/plugins/meta-architect/skills/sage/SKILL.md +3 -1
  61. package/plugins/meta-architect/skills/sage/agents/openai.yaml +0 -0
  62. package/plugins/meta-architect/skills/sage/references/source-selection.md +28 -0
  63. package/plugins/meta-architect/skills/tdd/SKILL.md +24 -0
  64. package/plugins/meta-architect/skills/tdd/agents/openai.yaml +4 -0
  65. package/plugins/meta-architect/skills/vet/SKILL.md +3 -1
  66. package/plugins/meta-architect/skills/vet/agents/openai.yaml +0 -0
  67. package/plugins/meta-architect/skills/vet/references/security-playbooks.md +23 -0
  68. package/plugins/meta-architect/skills/vibe/SKILL.md +0 -0
  69. package/plugins/meta-architect/skills/vibe/agents/openai.yaml +0 -0
  70. package/scripts/biome-staged.js +0 -0
  71. package/scripts/build-linux-packages.mjs +328 -0
  72. package/scripts/doctor.js +19 -0
  73. package/scripts/linux-package-lib.mjs +40 -0
  74. package/scripts/linux-package-smoke.mjs +103 -0
  75. package/scripts/plugin-sync.js +0 -0
  76. package/scripts/postinstall.js +0 -0
  77. package/scripts/release-metadata.js +0 -0
  78. package/scripts/release-sync.js +13 -6
  79. package/scripts/release-verify.js +0 -0
  80. package/scripts/setup-npmrc.js +0 -0
  81. package/skills/align/SKILL.md +24 -0
  82. package/skills/align/agents/openai.yaml +4 -0
  83. package/skills/align/references/shared-language.md +24 -0
  84. package/skills/arch/SKILL.md +0 -0
  85. package/skills/arch/agents/openai.yaml +0 -0
  86. package/skills/build/SKILL.md +0 -0
  87. package/skills/build/agents/openai.yaml +0 -0
  88. package/skills/cleanup/SKILL.md +23 -0
  89. package/skills/cleanup/agents/openai.yaml +4 -0
  90. package/skills/cleanup/references/style-and-deslop.md +18 -0
  91. package/skills/diagnose/SKILL.md +24 -0
  92. package/skills/diagnose/agents/openai.yaml +4 -0
  93. package/skills/flow/SKILL.md +0 -0
  94. package/skills/flow/agents/openai.yaml +0 -0
  95. package/skills/index.json +21 -6
  96. package/skills/maestro/SKILL.md +36 -3
  97. package/skills/maestro/agents/openai.yaml +2 -2
  98. package/skills/{meta-architect → maestro}/references/core-release-rules.md +0 -0
  99. package/skills/maestro/references/native-ingest-map.md +44 -0
  100. package/skills/sage/SKILL.md +3 -1
  101. package/skills/sage/agents/openai.yaml +0 -0
  102. package/skills/sage/references/source-selection.md +28 -0
  103. package/skills/tdd/SKILL.md +24 -0
  104. package/skills/tdd/agents/openai.yaml +4 -0
  105. package/skills/vet/SKILL.md +3 -1
  106. package/skills/vet/agents/openai.yaml +0 -0
  107. package/skills/vet/references/security-playbooks.md +23 -0
  108. package/skills/vibe/SKILL.md +0 -0
  109. package/skills/vibe/agents/openai.yaml +0 -0
  110. package/src/bootstrap.js +124 -24
  111. package/src/decision-log.js +12 -9
  112. package/src/launcher.js +0 -0
  113. package/src/mcp-config.js +130 -8
  114. package/src/mcp-live-client.js +1 -1
  115. package/src/paths.js +33 -1
  116. package/src/release-state.js +30 -1
  117. package/src/runtime/build-readiness.js +38 -0
  118. package/src/runtime/continuity-notes.js +79 -0
  119. package/src/runtime/guidance-stack.js +42 -0
  120. package/src/runtime/maestro-manager.js +586 -0
  121. package/src/runtime/orchestrator.js +158 -0
  122. package/src/runtime/runtime-state.js +382 -0
  123. package/src/runtime/signal-hooks.js +52 -0
  124. package/src/runtime/startup-path.js +14 -0
  125. package/src/runtime/workspaces.js +25 -0
  126. package/src/runtime-artifacts.js +190 -30
  127. package/src/skill-installer.js +53 -5
  128. package/src/skills.js +633 -49
  129. package/src/state-sync.js +51 -8
  130. package/plugins/meta-architect/skills/meta-architect/SKILL.md +0 -32
  131. package/plugins/meta-architect/skills/meta-architect/agents/openai.yaml +0 -4
  132. package/skills/meta-architect/SKILL.md +0 -32
  133. package/skills/meta-architect/agents/openai.yaml +0 -4
@@ -0,0 +1,158 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { ensureDir, readJson, writeFileIfMissing, writeJson } from "../fs-utils.js";
3
+ import { getRuntimeSubsystemPath } from "../paths.js";
4
+ import { guardLeaderMutation } from "./runtime-state.js";
5
+
6
+ export function getTaskRoot() {
7
+ return getRuntimeSubsystemPath("tasks");
8
+ }
9
+
10
+ export function getTaskRegistryPath() {
11
+ return getRuntimeSubsystemPath("tasks", "registry.json");
12
+ }
13
+
14
+ export function getTaskMailboxRoot() {
15
+ return getRuntimeSubsystemPath("tasks", "mailbox");
16
+ }
17
+
18
+ export function getTaskLockRoot() {
19
+ return getRuntimeSubsystemPath("tasks", "locks");
20
+ }
21
+
22
+ function validateTaskRegistry(registry) {
23
+ if (
24
+ !registry ||
25
+ typeof registry !== "object" ||
26
+ typeof registry.leader !== "string" ||
27
+ !Array.isArray(registry.workers) ||
28
+ !Array.isArray(registry.tasks)
29
+ ) {
30
+ throw new Error("Task registry must contain leader, workers, and tasks");
31
+ }
32
+
33
+ return registry;
34
+ }
35
+
36
+ function normalizeTask(task) {
37
+ const title = task?.title?.trim();
38
+ if (!title) {
39
+ throw new Error("team_run.submit_task requires a task title");
40
+ }
41
+
42
+ const metadata =
43
+ task?.metadata && typeof task.metadata === "object" && !Array.isArray(task.metadata)
44
+ ? { ...task.metadata }
45
+ : {};
46
+
47
+ return {
48
+ id: task.id ?? `task-${randomUUID()}`,
49
+ title,
50
+ status: task.status ?? "queued",
51
+ owner: task.owner ?? null,
52
+ createdAt: task.createdAt ?? new Date().toISOString(),
53
+ updatedAt: new Date().toISOString(),
54
+ metadata: {
55
+ classification: metadata.classification ?? "durable-team-task",
56
+ ...metadata,
57
+ },
58
+ };
59
+ }
60
+
61
+ export async function seedOrchestratorArtifacts() {
62
+ await ensureDir(getTaskRoot());
63
+ await ensureDir(getTaskMailboxRoot());
64
+ await ensureDir(getTaskLockRoot());
65
+ await writeFileIfMissing(
66
+ getTaskRegistryPath(),
67
+ `${JSON.stringify(
68
+ {
69
+ schemaVersion: "0.1.0",
70
+ leader: "leader",
71
+ workers: [],
72
+ tasks: [],
73
+ },
74
+ null,
75
+ 2,
76
+ )}\n`,
77
+ );
78
+ }
79
+
80
+ export async function loadTaskRegistry() {
81
+ return validateTaskRegistry(await readJson(getTaskRegistryPath()));
82
+ }
83
+
84
+ export async function saveTaskRegistry(registry) {
85
+ validateTaskRegistry(registry);
86
+ await writeJson(getTaskRegistryPath(), registry);
87
+ return registry;
88
+ }
89
+
90
+ export async function submitTask(task, options = {}) {
91
+ const guard = await guardLeaderMutation({
92
+ actor: options.actor,
93
+ kind: "team-run-submit",
94
+ payload: task,
95
+ });
96
+ if (!guard.allowed) {
97
+ return { proposed: true, proposalPath: guard.proposalPath };
98
+ }
99
+
100
+ const registry = await loadTaskRegistry();
101
+ const nextTask = normalizeTask(task);
102
+ registry.tasks.push(nextTask);
103
+ await saveTaskRegistry(registry);
104
+ return { proposed: false, proposalPath: null, task: nextTask };
105
+ }
106
+
107
+ export async function getTask(taskId) {
108
+ const registry = await loadTaskRegistry();
109
+ const task = registry.tasks.find((entry) => entry.id === taskId);
110
+ if (!task) {
111
+ throw new Error(`Unknown task: ${taskId}`);
112
+ }
113
+
114
+ return task;
115
+ }
116
+
117
+ export async function listTasks() {
118
+ const registry = await loadTaskRegistry();
119
+ return registry.tasks;
120
+ }
121
+
122
+ export async function listMaestroTasks() {
123
+ const tasks = await listTasks();
124
+ return tasks.filter((task) => task.metadata?.managerOwner === "$maestro");
125
+ }
126
+
127
+ export async function controlTask(taskId, action, options = {}) {
128
+ const guard = await guardLeaderMutation({
129
+ actor: options.actor,
130
+ kind: "team-run-control",
131
+ payload: { taskId, action },
132
+ });
133
+ if (!guard.allowed) {
134
+ return { proposed: true, proposalPath: guard.proposalPath };
135
+ }
136
+
137
+ const registry = await loadTaskRegistry();
138
+ const task = registry.tasks.find((entry) => entry.id === taskId);
139
+ if (!task) {
140
+ throw new Error(`Unknown task: ${taskId}`);
141
+ }
142
+
143
+ const statusByAction = {
144
+ start: "running",
145
+ complete: "done",
146
+ block: "blocked",
147
+ cancel: "cancelled",
148
+ };
149
+ const nextStatus = statusByAction[action];
150
+ if (!nextStatus) {
151
+ throw new Error(`Unsupported team_run control action: ${action}`);
152
+ }
153
+
154
+ task.status = nextStatus;
155
+ task.updatedAt = new Date().toISOString();
156
+ await saveTaskRegistry(registry);
157
+ return { proposed: false, proposalPath: null, task };
158
+ }
@@ -0,0 +1,382 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { readJson, writeJson } from "../fs-utils.js";
5
+ import { getRuntimeReadPath } from "../paths.js";
6
+ import { createDefaultReleaseState, validateReleaseState } from "../release-state.js";
7
+ import {
8
+ getContinuityIndexPath,
9
+ getContinuityNotesPath,
10
+ seedContinuityArtifacts,
11
+ } from "./continuity-notes.js";
12
+ import {
13
+ getGuidanceIncludeGraphPath,
14
+ getMergedGuidancePath,
15
+ seedGuidanceStackArtifacts,
16
+ } from "./guidance-stack.js";
17
+ import { getManagerRunsPath, seedMaestroManagerArtifacts } from "./maestro-manager.js";
18
+ import {
19
+ getTaskLockRoot,
20
+ getTaskMailboxRoot,
21
+ getTaskRegistryPath,
22
+ seedOrchestratorArtifacts,
23
+ } from "./orchestrator.js";
24
+ import {
25
+ getRuntimeHooksAuditPath,
26
+ getRuntimeHooksConfigPath,
27
+ seedSignalHookArtifacts,
28
+ } from "./signal-hooks.js";
29
+ import { getWorkspacesIndexPath, seedWorkspaceArtifacts } from "./workspaces.js";
30
+
31
+ const runtimeSubsystemSeeders = [
32
+ seedGuidanceStackArtifacts,
33
+ seedContinuityArtifacts,
34
+ seedSignalHookArtifacts,
35
+ seedOrchestratorArtifacts,
36
+ seedWorkspaceArtifacts,
37
+ seedMaestroManagerArtifacts,
38
+ ];
39
+ const defaultMergedGuidance = {
40
+ schemaVersion: "0.1.0",
41
+ sources: [],
42
+ content: "",
43
+ };
44
+ const defaultGuidanceGraph = {
45
+ schemaVersion: "0.1.0",
46
+ roots: [],
47
+ edges: [],
48
+ };
49
+ const defaultContinuityIndex = {
50
+ schemaVersion: "0.1.0",
51
+ sessionCount: 0,
52
+ lastUpdatedAt: null,
53
+ };
54
+ const defaultHookConfig = {
55
+ schemaVersion: "0.1.0",
56
+ compatibilityNamespace: ["prebuild", "prerelease"],
57
+ runtimeNamespace: [
58
+ "prompt_submit",
59
+ "pre_action",
60
+ "post_action",
61
+ "failure",
62
+ "session_start",
63
+ "cwd_changed",
64
+ "file_changed",
65
+ "workspace_created",
66
+ ],
67
+ hooks: [],
68
+ };
69
+ const defaultTaskRegistry = {
70
+ schemaVersion: "0.1.0",
71
+ leader: "leader",
72
+ workers: [],
73
+ tasks: [],
74
+ };
75
+ const defaultWorkspaceIndex = {
76
+ schemaVersion: "0.1.0",
77
+ items: [],
78
+ };
79
+ const defaultDecisions = {
80
+ schemaVersion: "0.1.0",
81
+ decisions: [],
82
+ };
83
+ const defaultManagerRuns = {
84
+ schemaVersion: "0.1.0",
85
+ runs: [],
86
+ };
87
+ const terminalManagerStates = new Set(["completed", "blocked", "failed", "cancelled"]);
88
+
89
+ function coerceValidated(value, fallback, label, predicate, invalidArtifacts) {
90
+ if (predicate(value)) {
91
+ return value;
92
+ }
93
+
94
+ invalidArtifacts.push(label);
95
+ return fallback;
96
+ }
97
+
98
+ export async function ensureRuntimeSubsystems() {
99
+ for (const seedRuntimeSubsystem of runtimeSubsystemSeeders) {
100
+ await seedRuntimeSubsystem();
101
+ }
102
+ }
103
+
104
+ function getMailboxProposalPath(kind) {
105
+ return path.join(getTaskMailboxRoot(), `${Date.now()}-${kind}-${randomUUID()}.json`);
106
+ }
107
+
108
+ export function isLeaderActor(actor = "leader") {
109
+ return actor === "leader";
110
+ }
111
+
112
+ export async function loadLeaderAuthority() {
113
+ try {
114
+ const registry = await readJson(getTaskRegistryPath());
115
+ const isValidRegistry =
116
+ registry &&
117
+ typeof registry === "object" &&
118
+ typeof registry.leader === "string" &&
119
+ Array.isArray(registry.workers) &&
120
+ Array.isArray(registry.tasks);
121
+
122
+ if (!isValidRegistry) {
123
+ return { state: "invalid", leaderActor: null };
124
+ }
125
+
126
+ return { state: "ok", leaderActor: registry.leader };
127
+ } catch (error) {
128
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
129
+ return { state: "missing", leaderActor: "leader" };
130
+ }
131
+
132
+ return { state: "invalid", leaderActor: null };
133
+ }
134
+ }
135
+
136
+ export async function assertLeaderAuthority(actor) {
137
+ const authority = await loadLeaderAuthority();
138
+ if (authority.state === "invalid") {
139
+ throw new Error("Invalid runtime authority: tasks.registry");
140
+ }
141
+
142
+ const leaderActor = authority.leaderActor ?? "leader";
143
+ const effectiveActor = actor ?? leaderActor;
144
+ if (effectiveActor !== leaderActor) {
145
+ throw new Error("Leader authority required");
146
+ }
147
+
148
+ return authority;
149
+ }
150
+
151
+ export async function queueMailboxProposal({ actor, kind, payload }) {
152
+ const proposal = {
153
+ schemaVersion: "0.1.0",
154
+ actor,
155
+ kind,
156
+ payload,
157
+ proposedAt: new Date().toISOString(),
158
+ };
159
+ const target = getMailboxProposalPath(kind);
160
+ await writeJson(target, proposal);
161
+ return target;
162
+ }
163
+
164
+ export async function guardLeaderMutation({ actor, kind, payload }) {
165
+ const authority = await loadLeaderAuthority();
166
+ if (authority.state === "invalid") {
167
+ throw new Error("Invalid runtime authority: tasks.registry");
168
+ }
169
+ const leaderActor = authority.leaderActor ?? "leader";
170
+ const effectiveActor = actor ?? leaderActor;
171
+ if (effectiveActor === leaderActor) {
172
+ return { allowed: true, proposalPath: null };
173
+ }
174
+
175
+ const proposalPath = await queueMailboxProposal({ actor: effectiveActor, kind, payload });
176
+ return { allowed: false, proposalPath };
177
+ }
178
+
179
+ export async function loadRuntimeSnapshot() {
180
+ const missingArtifacts = [];
181
+ const invalidArtifacts = [];
182
+ const readJsonWithStatus = async (filePath, fallback, label) => {
183
+ try {
184
+ return await readJson(filePath);
185
+ } catch (error) {
186
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
187
+ missingArtifacts.push(label);
188
+ } else {
189
+ invalidArtifacts.push(label);
190
+ }
191
+ return fallback;
192
+ }
193
+ };
194
+ const readTextWithStatus = async (filePath, fallback, label) => {
195
+ try {
196
+ return await fs.readFile(filePath, "utf8");
197
+ } catch (error) {
198
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
199
+ missingArtifacts.push(label);
200
+ } else {
201
+ invalidArtifacts.push(label);
202
+ }
203
+ return fallback;
204
+ }
205
+ };
206
+ const mailboxEntries = await fs.readdir(getTaskMailboxRoot()).catch(() => {
207
+ missingArtifacts.push("tasks.mailbox");
208
+ return [];
209
+ });
210
+ await fs.access(getRuntimeHooksAuditPath()).catch(() => {
211
+ missingArtifacts.push("hooks.audit");
212
+ });
213
+ await fs.access(getTaskLockRoot()).catch(() => {
214
+ missingArtifacts.push("tasks.locks");
215
+ });
216
+
217
+ const [
218
+ mergedGuidance,
219
+ guidanceGraph,
220
+ continuityIndex,
221
+ continuityNotes,
222
+ hookConfig,
223
+ taskRegistry,
224
+ workspaceIndex,
225
+ release,
226
+ decisions,
227
+ managerRuns,
228
+ ] = await Promise.all([
229
+ readJsonWithStatus(getMergedGuidancePath(), defaultMergedGuidance, "guidance.merged"),
230
+ readJsonWithStatus(
231
+ getGuidanceIncludeGraphPath(),
232
+ defaultGuidanceGraph,
233
+ "guidance.includeGraph",
234
+ ),
235
+ readJsonWithStatus(getContinuityIndexPath(), defaultContinuityIndex, "memory.index"),
236
+ readTextWithStatus(getContinuityNotesPath(), "", "memory.notes"),
237
+ readJsonWithStatus(getRuntimeHooksConfigPath(), defaultHookConfig, "hooks.config"),
238
+ readJsonWithStatus(getTaskRegistryPath(), defaultTaskRegistry, "tasks.registry"),
239
+ readJsonWithStatus(getWorkspacesIndexPath(), defaultWorkspaceIndex, "workspaces.index"),
240
+ (async () => {
241
+ try {
242
+ return validateReleaseState(
243
+ JSON.parse(await fs.readFile(getRuntimeReadPath("release.json"), "utf8")),
244
+ );
245
+ } catch (error) {
246
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
247
+ missingArtifacts.push("runtime.release");
248
+ } else {
249
+ invalidArtifacts.push("runtime.release");
250
+ }
251
+
252
+ return createDefaultReleaseState();
253
+ }
254
+ })(),
255
+ readJsonWithStatus(getRuntimeReadPath("decisions.json"), defaultDecisions, "runtime.decisions"),
256
+ readJsonWithStatus(getManagerRunsPath(), defaultManagerRuns, "runtime.managerRuns"),
257
+ ]);
258
+ const validatedMergedGuidance = coerceValidated(
259
+ mergedGuidance,
260
+ defaultMergedGuidance,
261
+ "guidance.merged",
262
+ (value) =>
263
+ value &&
264
+ typeof value === "object" &&
265
+ Array.isArray(value.sources) &&
266
+ typeof value.content === "string",
267
+ invalidArtifacts,
268
+ );
269
+ const validatedGuidanceGraph = coerceValidated(
270
+ guidanceGraph,
271
+ defaultGuidanceGraph,
272
+ "guidance.includeGraph",
273
+ (value) =>
274
+ value &&
275
+ typeof value === "object" &&
276
+ Array.isArray(value.roots) &&
277
+ Array.isArray(value.edges),
278
+ invalidArtifacts,
279
+ );
280
+ const validatedContinuityIndex = coerceValidated(
281
+ continuityIndex,
282
+ defaultContinuityIndex,
283
+ "memory.index",
284
+ (value) =>
285
+ value &&
286
+ typeof value === "object" &&
287
+ typeof value.sessionCount === "number" &&
288
+ "lastUpdatedAt" in value,
289
+ invalidArtifacts,
290
+ );
291
+ const validatedHookConfig = coerceValidated(
292
+ hookConfig,
293
+ defaultHookConfig,
294
+ "hooks.config",
295
+ (value) =>
296
+ value &&
297
+ typeof value === "object" &&
298
+ Array.isArray(value.compatibilityNamespace) &&
299
+ Array.isArray(value.runtimeNamespace) &&
300
+ Array.isArray(value.hooks),
301
+ invalidArtifacts,
302
+ );
303
+ const validatedTaskRegistry = coerceValidated(
304
+ taskRegistry,
305
+ defaultTaskRegistry,
306
+ "tasks.registry",
307
+ (value) =>
308
+ value &&
309
+ typeof value === "object" &&
310
+ typeof value.leader === "string" &&
311
+ Array.isArray(value.workers) &&
312
+ Array.isArray(value.tasks),
313
+ invalidArtifacts,
314
+ );
315
+ const validatedWorkspaceIndex = coerceValidated(
316
+ workspaceIndex,
317
+ defaultWorkspaceIndex,
318
+ "workspaces.index",
319
+ (value) => value && typeof value === "object" && Array.isArray(value.items),
320
+ invalidArtifacts,
321
+ );
322
+ const validatedDecisions = coerceValidated(
323
+ decisions,
324
+ defaultDecisions,
325
+ "runtime.decisions",
326
+ (value) => value && typeof value === "object" && Array.isArray(value.decisions),
327
+ invalidArtifacts,
328
+ );
329
+ const validatedManagerRuns = coerceValidated(
330
+ managerRuns,
331
+ defaultManagerRuns,
332
+ "runtime.managerRuns",
333
+ (value) => value && typeof value === "object" && Array.isArray(value.runs),
334
+ invalidArtifacts,
335
+ );
336
+
337
+ return {
338
+ mergedGuidance: validatedMergedGuidance,
339
+ guidanceGraph: validatedGuidanceGraph,
340
+ continuityIndex: validatedContinuityIndex,
341
+ continuityNotes,
342
+ hookConfig: validatedHookConfig,
343
+ taskRegistry: validatedTaskRegistry,
344
+ mailboxEntries,
345
+ workspaceIndex: validatedWorkspaceIndex,
346
+ release,
347
+ decisions: validatedDecisions,
348
+ managerRuns: validatedManagerRuns,
349
+ missingArtifacts,
350
+ invalidArtifacts,
351
+ };
352
+ }
353
+
354
+ export function createRuntimeSummary(snapshot) {
355
+ const trimmedNotes = snapshot.continuityNotes.trim();
356
+ return {
357
+ guidanceSourceCount: snapshot.mergedGuidance.sources.length,
358
+ guidanceIncludeRoots: snapshot.guidanceGraph.roots.length,
359
+ continuitySessionCount: snapshot.continuityIndex.sessionCount,
360
+ continuityHasNotes:
361
+ trimmedNotes.length > 0 &&
362
+ trimmedNotes !== "# Continuity Notes\n\nNo continuity notes captured yet.",
363
+ compatibilityHookCount: snapshot.hookConfig.compatibilityNamespace.length,
364
+ runtimeHookCount: snapshot.hookConfig.runtimeNamespace.length,
365
+ configuredRuntimeHookCount: snapshot.hookConfig.hooks.length,
366
+ workerCount: snapshot.taskRegistry.workers.length,
367
+ taskCount: snapshot.taskRegistry.tasks.length,
368
+ pendingMailboxCount: snapshot.mailboxEntries.length,
369
+ workspaceCount: snapshot.workspaceIndex.items.length,
370
+ decisionCount: snapshot.decisions.decisions.length,
371
+ managerRunCount: snapshot.managerRuns.runs.length,
372
+ activeManagerRunCount: snapshot.managerRuns.runs.filter(
373
+ (run) => !terminalManagerStates.has(run.state),
374
+ ).length,
375
+ waitingReviewManagerRunCount: snapshot.managerRuns.runs.filter(
376
+ (run) => run.state === "waiting-review",
377
+ ).length,
378
+ buildStatus: snapshot.release.build_status,
379
+ missingArtifacts: snapshot.missingArtifacts,
380
+ invalidArtifacts: snapshot.invalidArtifacts,
381
+ };
382
+ }
@@ -0,0 +1,52 @@
1
+ import fs from "node:fs/promises";
2
+ import { ensureDir, readJson, writeFileIfMissing } from "../fs-utils.js";
3
+ import { getRuntimeSubsystemPath } from "../paths.js";
4
+
5
+ const runtimeEvents = [
6
+ "prompt_submit",
7
+ "pre_action",
8
+ "post_action",
9
+ "failure",
10
+ "session_start",
11
+ "cwd_changed",
12
+ "file_changed",
13
+ "workspace_created",
14
+ ];
15
+
16
+ export function getRuntimeHooksRoot() {
17
+ return getRuntimeSubsystemPath("hooks");
18
+ }
19
+
20
+ export function getRuntimeHooksConfigPath() {
21
+ return getRuntimeSubsystemPath("hooks", "config.json");
22
+ }
23
+
24
+ export function getRuntimeHooksAuditPath() {
25
+ return getRuntimeSubsystemPath("hooks", "audit.log");
26
+ }
27
+
28
+ export async function seedSignalHookArtifacts() {
29
+ await ensureDir(getRuntimeHooksRoot());
30
+ await writeFileIfMissing(
31
+ getRuntimeHooksConfigPath(),
32
+ `${JSON.stringify(
33
+ {
34
+ schemaVersion: "0.1.0",
35
+ compatibilityNamespace: ["prebuild", "prerelease"],
36
+ runtimeNamespace: runtimeEvents,
37
+ hooks: [],
38
+ },
39
+ null,
40
+ 2,
41
+ )}\n`,
42
+ );
43
+ await writeFileIfMissing(getRuntimeHooksAuditPath(), "");
44
+ }
45
+
46
+ export async function loadRuntimeHooksConfig() {
47
+ return readJson(getRuntimeHooksConfigPath());
48
+ }
49
+
50
+ export async function loadRuntimeHooksAuditLog() {
51
+ return fs.readFile(getRuntimeHooksAuditPath(), "utf8");
52
+ }
@@ -0,0 +1,14 @@
1
+ export function createStartupCheckpoint(name, startedAt = Date.now()) {
2
+ return {
3
+ name,
4
+ startedAt,
5
+ };
6
+ }
7
+
8
+ export function completeStartupCheckpoint(checkpoint, endedAt = Date.now()) {
9
+ return {
10
+ ...checkpoint,
11
+ endedAt,
12
+ durationMs: endedAt - checkpoint.startedAt,
13
+ };
14
+ }
@@ -0,0 +1,25 @@
1
+ import { ensureDir, writeFileIfMissing } from "../fs-utils.js";
2
+ import { getRuntimeSubsystemPath } from "../paths.js";
3
+
4
+ export function getWorkspacesRoot() {
5
+ return getRuntimeSubsystemPath("workspaces");
6
+ }
7
+
8
+ export function getWorkspacesIndexPath() {
9
+ return getRuntimeSubsystemPath("workspaces", "index.json");
10
+ }
11
+
12
+ export async function seedWorkspaceArtifacts() {
13
+ await ensureDir(getWorkspacesRoot());
14
+ await writeFileIfMissing(
15
+ getWorkspacesIndexPath(),
16
+ `${JSON.stringify(
17
+ {
18
+ schemaVersion: "0.1.0",
19
+ items: [],
20
+ },
21
+ null,
22
+ 2,
23
+ )}\n`,
24
+ );
25
+ }