@kontextmind/kxm 0.6.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 (227) hide show
  1. package/.claude-plugin/marketplace.json +19 -0
  2. package/.kxm/README.md +14 -0
  3. package/.kxm/assets/README.md +5 -0
  4. package/.kxm/assets/retrospectives/README.md +5 -0
  5. package/.kxm/config/README.md +5 -0
  6. package/.kxm/config/agents.json +43 -0
  7. package/.kxm/config/env.example +56 -0
  8. package/.kxm/config/update.example.yaml +9 -0
  9. package/.kxm/config/workflows/fix.json +160 -0
  10. package/.kxm/config/workflows/jira-development.json +116 -0
  11. package/.kxm/config/workflows/provenance-quorum.json +150 -0
  12. package/.kxm/config/workflows/v04-dogfood.json +72 -0
  13. package/CHANGELOG.md +465 -0
  14. package/LICENSE +21 -0
  15. package/README.md +306 -0
  16. package/SECURITY.md +72 -0
  17. package/docs/README.md +48 -0
  18. package/docs/agent-communication-envelopes-and-gates.md +553 -0
  19. package/docs/architecture.md +242 -0
  20. package/docs/assignment-runner.md +241 -0
  21. package/docs/configuration.md +361 -0
  22. package/docs/continuous-improvement.md +114 -0
  23. package/docs/getting-started.md +253 -0
  24. package/docs/kxm-handbook.md +1090 -0
  25. package/docs/operations.md +205 -0
  26. package/docs/provenance-gates.md +291 -0
  27. package/docs/skills.md +45 -0
  28. package/docs/templates/README.md +95 -0
  29. package/docs/templates/adr.md +88 -0
  30. package/docs/templates/architecture.md +120 -0
  31. package/docs/templates/bug-fix.md +109 -0
  32. package/docs/templates/feature.md +108 -0
  33. package/docs/templates/handoff.md +72 -0
  34. package/docs/templates/postmortem.md +77 -0
  35. package/docs/templates/research.md +100 -0
  36. package/docs/templates/review.md +85 -0
  37. package/docs/templates/runbook.md +73 -0
  38. package/docs/templates/test-plan.md +87 -0
  39. package/docs/templates/test-report.md +72 -0
  40. package/docs/test-matrix.md +121 -0
  41. package/docs/troubleshooting.md +249 -0
  42. package/docs/vnext/README.md +62 -0
  43. package/docs/vnext/architecture.md +185 -0
  44. package/docs/vnext/effects-and-recovery.md +172 -0
  45. package/docs/vnext/lifecycles.md +235 -0
  46. package/docs/vnext/migration.md +220 -0
  47. package/docs/vnext/routing.md +184 -0
  48. package/docs/vnext/synchronization.md +172 -0
  49. package/docs/vnext/terminology.md +240 -0
  50. package/docs/vnext/validation.md +335 -0
  51. package/docs/webhook-workflows.md +240 -0
  52. package/docs/workflow-guide.md +1150 -0
  53. package/examples/README.md +102 -0
  54. package/examples/provenance-workflow.json +40 -0
  55. package/examples/requester.ts +30 -0
  56. package/examples/reviewer-agent.ts +29 -0
  57. package/examples/roundtrip.ts +46 -0
  58. package/examples/vnext/.kxm/agents/coordinator.yaml +16 -0
  59. package/examples/vnext/.kxm/agents/critic-1.yaml +16 -0
  60. package/examples/vnext/.kxm/agents/critic-2.yaml +15 -0
  61. package/examples/vnext/.kxm/agents/critic-3.yaml +15 -0
  62. package/examples/vnext/.kxm/agents/implementer.yaml +15 -0
  63. package/examples/vnext/.kxm/agents/planner.yaml +13 -0
  64. package/examples/vnext/.kxm/agents/reproducer.yaml +15 -0
  65. package/examples/vnext/.kxm/agents/reviewer.yaml +15 -0
  66. package/examples/vnext/.kxm/gates.yaml +8 -0
  67. package/examples/vnext/.kxm/models/critic-claude.yaml +11 -0
  68. package/examples/vnext/.kxm/models/critic-gemini.yaml +11 -0
  69. package/examples/vnext/.kxm/models/critic-grok.yaml +12 -0
  70. package/examples/vnext/.kxm/models/implementation.yaml +14 -0
  71. package/examples/vnext/.kxm/models/primary.yaml +17 -0
  72. package/examples/vnext/.kxm/prices.yaml +111 -0
  73. package/examples/vnext/.kxm/project/env.yaml +7 -0
  74. package/examples/vnext/.kxm/project.yaml +32 -0
  75. package/examples/vnext/.kxm/repo/repo.yaml +8 -0
  76. package/examples/vnext/.kxm/workflows/default.yaml +92 -0
  77. package/examples/vnext/.kxm/workflows/fix.yaml +376 -0
  78. package/examples/vnext/.kxm/workflows/improve.yaml +57 -0
  79. package/examples/vnext/README.md +53 -0
  80. package/examples/vnext/records/assignment-result-recorded.json +63 -0
  81. package/examples/vnext/records/assignment-result.json +46 -0
  82. package/examples/vnext/records/context-candidate.json +42 -0
  83. package/examples/vnext/records/delivery-manifest.json +66 -0
  84. package/examples/vnext/records/effect-uncertainty-resolved-sync.json +67 -0
  85. package/examples/vnext/records/effect-uncertainty-resolved.json +62 -0
  86. package/examples/vnext/records/run-created.json +54 -0
  87. package/examples/vnext/records/sync-event.json +65 -0
  88. package/examples/vnext/repositories/api/.kxm/repo/env.yaml +7 -0
  89. package/examples/vnext/repositories/api/.kxm/repo/repo.yaml +8 -0
  90. package/examples/vnext/repositories/web/.kxm/repo/repo.yaml +8 -0
  91. package/examples/workflow-signal.ts +63 -0
  92. package/package.json +129 -0
  93. package/plugins/kxm/.claude-plugin/plugin.json +73 -0
  94. package/plugins/kxm/.mcp.json +19 -0
  95. package/plugins/kxm/README.md +93 -0
  96. package/plugins/kxm/dist/cli.js +42853 -0
  97. package/plugins/kxm/dist/client.js +416 -0
  98. package/plugins/kxm/dist/core.js +1823 -0
  99. package/plugins/kxm/dist/extension.js +3797 -0
  100. package/plugins/kxm/dist/mcp-server.js +17104 -0
  101. package/plugins/kxm/dist/runtime.js +23361 -0
  102. package/plugins/kxm/dist/server.js +13640 -0
  103. package/plugins/kxm/dist/vnext-runtime-supervisor.js +21109 -0
  104. package/plugins/kxm/package.json +12 -0
  105. package/plugins/kxm/skills/kxm/SKILL.md +97 -0
  106. package/plugins/kxm/skills/kxm/references/protocol.md +103 -0
  107. package/plugins/kxm/skills/kxm-session/SKILL.md +53 -0
  108. package/plugins/kxm/src/arbiter.ts +355 -0
  109. package/plugins/kxm/src/artifacts-exist.ts +62 -0
  110. package/plugins/kxm/src/autocomplete.ts +236 -0
  111. package/plugins/kxm/src/cli.ts +3707 -0
  112. package/plugins/kxm/src/client.ts +614 -0
  113. package/plugins/kxm/src/commands.ts +1063 -0
  114. package/plugins/kxm/src/config.ts +290 -0
  115. package/plugins/kxm/src/context/providers.ts +101 -0
  116. package/plugins/kxm/src/context-packet.ts +332 -0
  117. package/plugins/kxm/src/context.ts +499 -0
  118. package/plugins/kxm/src/core.ts +6 -0
  119. package/plugins/kxm/src/database.ts +563 -0
  120. package/plugins/kxm/src/diagnostics.ts +184 -0
  121. package/plugins/kxm/src/envelope.ts +118 -0
  122. package/plugins/kxm/src/extension.ts +895 -0
  123. package/plugins/kxm/src/external-effects.ts +299 -0
  124. package/plugins/kxm/src/github-watch.ts +255 -0
  125. package/plugins/kxm/src/hub-binding.ts +160 -0
  126. package/plugins/kxm/src/hub.ts +2502 -0
  127. package/plugins/kxm/src/improve.ts +383 -0
  128. package/plugins/kxm/src/inbox.ts +10 -0
  129. package/plugins/kxm/src/kxm-install-kind.ts +113 -0
  130. package/plugins/kxm/src/kxm-update-config.ts +39 -0
  131. package/plugins/kxm/src/kxm-update.ts +238 -0
  132. package/plugins/kxm/src/local-snapshot.ts +406 -0
  133. package/plugins/kxm/src/logger.ts +198 -0
  134. package/plugins/kxm/src/mcp-server.ts +143 -0
  135. package/plugins/kxm/src/memory.ts +385 -0
  136. package/plugins/kxm/src/nous-pi.ts +287 -0
  137. package/plugins/kxm/src/nous-provider.ts +729 -0
  138. package/plugins/kxm/src/price-calc.ts +87 -0
  139. package/plugins/kxm/src/prices.ts +121 -0
  140. package/plugins/kxm/src/protocol.ts +172 -0
  141. package/plugins/kxm/src/recovery.ts +211 -0
  142. package/plugins/kxm/src/redact.ts +26 -0
  143. package/plugins/kxm/src/retrospective.ts +400 -0
  144. package/plugins/kxm/src/routing.ts +830 -0
  145. package/plugins/kxm/src/runtime.ts +9 -0
  146. package/plugins/kxm/src/server.ts +117 -0
  147. package/plugins/kxm/src/session-work.ts +571 -0
  148. package/plugins/kxm/src/session.ts +184 -0
  149. package/plugins/kxm/src/skills.ts +535 -0
  150. package/plugins/kxm/src/state.ts +326 -0
  151. package/plugins/kxm/src/store.ts +637 -0
  152. package/plugins/kxm/src/studio-layout.ts +268 -0
  153. package/plugins/kxm/src/suggest.ts +162 -0
  154. package/plugins/kxm/src/task-manager.ts +244 -0
  155. package/plugins/kxm/src/telemetry.ts +116 -0
  156. package/plugins/kxm/src/tui.ts +1046 -0
  157. package/plugins/kxm/src/vnext-bindings.ts +403 -0
  158. package/plugins/kxm/src/vnext-config.ts +1646 -0
  159. package/plugins/kxm/src/vnext-engine-artifacts.ts +86 -0
  160. package/plugins/kxm/src/vnext-engine-command.ts +533 -0
  161. package/plugins/kxm/src/vnext-engine-compile.ts +722 -0
  162. package/plugins/kxm/src/vnext-engine-evidence.ts +273 -0
  163. package/plugins/kxm/src/vnext-engine-fold.ts +1400 -0
  164. package/plugins/kxm/src/vnext-engine-gate-records.ts +583 -0
  165. package/plugins/kxm/src/vnext-engine-plan.ts +717 -0
  166. package/plugins/kxm/src/vnext-engine.ts +2458 -0
  167. package/plugins/kxm/src/vnext-gate-hash.ts +10 -0
  168. package/plugins/kxm/src/vnext-harness.ts +1142 -0
  169. package/plugins/kxm/src/vnext-init.ts +430 -0
  170. package/plugins/kxm/src/vnext-migrate.ts +1848 -0
  171. package/plugins/kxm/src/vnext-oneshot-producer.ts +424 -0
  172. package/plugins/kxm/src/vnext-permission.ts +936 -0
  173. package/plugins/kxm/src/vnext-pi-producer.ts +628 -0
  174. package/plugins/kxm/src/vnext-repair.ts +1094 -0
  175. package/plugins/kxm/src/vnext-runtime-owner.ts +320 -0
  176. package/plugins/kxm/src/vnext-runtime-store.ts +1560 -0
  177. package/plugins/kxm/src/vnext-runtime-supervisor.ts +586 -0
  178. package/plugins/kxm/src/vnext-runtime.ts +663 -0
  179. package/plugins/kxm/src/vnext-template.ts +247 -0
  180. package/plugins/kxm/src/wiki.ts +313 -0
  181. package/plugins/kxm/src/workflow.ts +1548 -0
  182. package/schemas/vnext/README.md +46 -0
  183. package/schemas/vnext/agent.schema.json +40 -0
  184. package/schemas/vnext/assignment-result.schema.json +66 -0
  185. package/schemas/vnext/backup-manifest.schema.json +89 -0
  186. package/schemas/vnext/candidate.schema.json +109 -0
  187. package/schemas/vnext/common.schema.json +422 -0
  188. package/schemas/vnext/context-candidate.schema.json +76 -0
  189. package/schemas/vnext/context-packet.schema.json +192 -0
  190. package/schemas/vnext/delivery-manifest.schema.json +159 -0
  191. package/schemas/vnext/environment.schema.json +66 -0
  192. package/schemas/vnext/gate-registry.schema.json +109 -0
  193. package/schemas/vnext/handoff-manifest.schema.json +146 -0
  194. package/schemas/vnext/init-operation.schema.json +61 -0
  195. package/schemas/vnext/local-repository-bindings.schema.json +30 -0
  196. package/schemas/vnext/memory-record.schema.json +45 -0
  197. package/schemas/vnext/migration-decision.schema.json +26 -0
  198. package/schemas/vnext/migration-plan.schema.json +123 -0
  199. package/schemas/vnext/migration-receipt.schema.json +52 -0
  200. package/schemas/vnext/model.schema.json +42 -0
  201. package/schemas/vnext/permission-diff.schema.json +57 -0
  202. package/schemas/vnext/prices.schema.json +115 -0
  203. package/schemas/vnext/project.schema.json +85 -0
  204. package/schemas/vnext/repository.schema.json +24 -0
  205. package/schemas/vnext/run-event.schema.json +460 -0
  206. package/schemas/vnext/session-brief.schema.json +153 -0
  207. package/schemas/vnext/sync-event.schema.json +234 -0
  208. package/schemas/vnext/template-provenance.schema.json +38 -0
  209. package/schemas/vnext/workflow.schema.json +248 -0
  210. package/scripts/assignment-run.d.mts +354 -0
  211. package/scripts/assignment-run.mjs +4451 -0
  212. package/scripts/build-runtime.mjs +56 -0
  213. package/scripts/check-generated.mjs +77 -0
  214. package/scripts/check-versions.mjs +34 -0
  215. package/scripts/emit-codex-artifacts.d.mts +9 -0
  216. package/scripts/emit-codex-artifacts.mjs +91 -0
  217. package/scripts/harness-run.d.mts +83 -0
  218. package/scripts/harness-run.mjs +2095 -0
  219. package/scripts/kxm-hub.mjs +105 -0
  220. package/scripts/kxm-publish-npm.mjs +327 -0
  221. package/scripts/kxm-release-github.mjs +472 -0
  222. package/scripts/kxm-runtime-supervisor.mjs +7 -0
  223. package/scripts/kxm-worker.mjs +1127 -0
  224. package/scripts/kxm.mjs +27 -0
  225. package/scripts/roster-policy.d.mts +20 -0
  226. package/scripts/roster-policy.mjs +161 -0
  227. package/scripts/smoke-multi-pi.mjs +479 -0
@@ -0,0 +1,332 @@
1
+ /**
2
+ * KXM Formal Context Packet (v2) & Structured Handoff Manifest (v1)
3
+ * Governs per-step role-bounded context assembly and inter-role transitions.
4
+ */
5
+
6
+ import { randomUUID } from "node:crypto";
7
+ import type { ContextItem } from "./context.ts";
8
+
9
+ export const CONTEXT_PACKET_SCHEMA = "kxm.context-packet.v2" as const;
10
+ export const HANDOFF_MANIFEST_SCHEMA = "kxm.handoff-manifest.v1" as const;
11
+
12
+ export interface ContextPacketTask {
13
+ taskId: string;
14
+ stepId: string;
15
+ stepAttempt: number;
16
+ objective: string;
17
+ allowedOutcomes: string[];
18
+ permissionCeiling: "read-only" | "edit" | "admin";
19
+ }
20
+
21
+ export interface ContextPacketAcceptanceCriterion {
22
+ id: string;
23
+ description: string;
24
+ verificationKind: "gate" | "witness" | "critic" | "human";
25
+ targetRef?: string | undefined;
26
+ required: boolean;
27
+ }
28
+
29
+ export interface ContextPacketPlan {
30
+ planHash: string;
31
+ activeStepIndex: number;
32
+ totalSteps: number;
33
+ settledDecisions: string[];
34
+ }
35
+
36
+ export interface ContextPacketArtifact {
37
+ name: string;
38
+ kind: "patch" | "report" | "log" | "plan" | "repro_script" | "doc";
39
+ artifactRef: string;
40
+ contentSnippet?: string | undefined;
41
+ }
42
+
43
+ export interface ContextPacketPredecessor {
44
+ stepId: string;
45
+ role: string;
46
+ status: "passed" | "warning" | "failed" | "settled";
47
+ summary: string;
48
+ settledAt: string;
49
+ artifacts: ContextPacketArtifact[];
50
+ decisions: string[];
51
+ }
52
+
53
+ export interface ContextPacketEnvironment {
54
+ sharedDefaults: Array<{ id: string; summary: string }>;
55
+ projectKnowledge: ContextItem[];
56
+ currentState: ContextItem[];
57
+ contradictions: ContextItem[];
58
+ activeSkills: ContextItem[];
59
+ }
60
+
61
+ export interface ContextPacketBudget {
62
+ allocatedTokens: number;
63
+ estimatedTokens: number;
64
+ unresolvedGaps: string[];
65
+ provenanceSummary: Record<string, number>;
66
+ }
67
+
68
+ export interface FormalContextPacketV2 {
69
+ schema: typeof CONTEXT_PACKET_SCHEMA;
70
+ packetId: string;
71
+ project: string;
72
+ generatedAt: string;
73
+ targetRole: string;
74
+ task: ContextPacketTask;
75
+ acceptanceCriteria: ContextPacketAcceptanceCriterion[];
76
+ plan: ContextPacketPlan;
77
+ predecessors: ContextPacketPredecessor[];
78
+ environment: ContextPacketEnvironment;
79
+ budget: ContextPacketBudget;
80
+ }
81
+
82
+ export interface CriticVerdict {
83
+ critic: string;
84
+ verdict: "PASS" | "FAIL" | "WARN" | "UNKNOWN";
85
+ summary?: string | undefined;
86
+ }
87
+
88
+ export interface HandoffDeliverables {
89
+ patches: string[];
90
+ reports: string[];
91
+ artifacts: Array<{ name: string; artifactRef: string }>;
92
+ }
93
+
94
+ export interface HandoffVerificationEvidence {
95
+ witnessExitCode: number;
96
+ witnessPassed: boolean;
97
+ criticVerdicts: CriticVerdict[];
98
+ }
99
+
100
+ export interface HandoffManifestV1 {
101
+ schema: typeof HANDOFF_MANIFEST_SCHEMA;
102
+ handoffId: string;
103
+ taskId: string;
104
+ workflowRunId: string;
105
+ reworkOf?: string | null | undefined;
106
+ source: {
107
+ role: string;
108
+ agentId: string;
109
+ harness: string;
110
+ model?: string | undefined;
111
+ stepId: string;
112
+ attemptId: string;
113
+ };
114
+ target: {
115
+ role: string;
116
+ permission: "read-only" | "edit" | "admin";
117
+ };
118
+ intent: "request_review" | "dispatch_fix" | "request_approval" | "complete_workflow";
119
+ status: "pending" | "accepted" | "rejected" | "superseded";
120
+ baseCommit: string;
121
+ candidateTreeHash?: string | undefined;
122
+ deliverables: HandoffDeliverables;
123
+ verificationEvidence: HandoffVerificationEvidence;
124
+ openQuestions?: string[] | undefined;
125
+ suggestedNextStep?: {
126
+ stepId?: string | undefined;
127
+ action?: string | undefined;
128
+ } | undefined;
129
+ createdAt: string;
130
+ }
131
+
132
+ /**
133
+ * Builds a formal context packet for a step execution.
134
+ */
135
+ export function buildFormalContextPacket(input: {
136
+ project: string;
137
+ targetRole: string;
138
+ task: ContextPacketTask;
139
+ acceptanceCriteria?: ContextPacketAcceptanceCriterion[] | undefined;
140
+ plan: ContextPacketPlan;
141
+ predecessors?: ContextPacketPredecessor[] | undefined;
142
+ environment?: Partial<ContextPacketEnvironment> | undefined;
143
+ tokenBudget?: number | undefined;
144
+ arbitratedItems?: ContextItem[] | undefined;
145
+ }): FormalContextPacketV2 {
146
+ const packetId = `ctxpkt_${randomUUID().replaceAll("-", "").slice(0, 16)}`;
147
+ const now = new Date().toISOString();
148
+
149
+ const items = input.arbitratedItems ?? [];
150
+ const sharedDefaults: Array<{ id: string; summary: string }> = [];
151
+ const projectKnowledge: ContextItem[] = [];
152
+ const currentState: ContextItem[] = [];
153
+ const contradictions: ContextItem[] = [];
154
+ const activeSkills: ContextItem[] = [];
155
+ const provenanceSummary: Record<string, number> = {};
156
+
157
+ for (const item of items) {
158
+ provenanceSummary[item.kind] = (provenanceSummary[item.kind] ?? 0) + 1;
159
+ if (item.project === "_shared") {
160
+ sharedDefaults.push({ id: item.id, summary: item.summary });
161
+ } else if (item.kind === "knowledge") {
162
+ projectKnowledge.push(item);
163
+ } else if (item.kind === "state" || item.kind === "episode") {
164
+ currentState.push(item);
165
+ } else if (item.kind === "skill") {
166
+ activeSkills.push(item);
167
+ } else {
168
+ projectKnowledge.push(item);
169
+ }
170
+ }
171
+
172
+ // Merge explicitly provided environment items
173
+ if (input.environment) {
174
+ if (input.environment.sharedDefaults) sharedDefaults.push(...input.environment.sharedDefaults);
175
+ if (input.environment.projectKnowledge) projectKnowledge.push(...input.environment.projectKnowledge);
176
+ if (input.environment.currentState) currentState.push(...input.environment.currentState);
177
+ if (input.environment.contradictions) contradictions.push(...input.environment.contradictions);
178
+ if (input.environment.activeSkills) activeSkills.push(...input.environment.activeSkills);
179
+ }
180
+
181
+ const allocatedTokens = input.tokenBudget ?? 16000;
182
+ // Estimate tokens (roughly 4 chars per token)
183
+ const estimatedTokens = Math.ceil(
184
+ (JSON.stringify(input.task).length +
185
+ JSON.stringify(input.plan).length +
186
+ JSON.stringify(input.predecessors ?? []).length +
187
+ JSON.stringify(items).length) /
188
+ 4,
189
+ );
190
+
191
+ return {
192
+ schema: CONTEXT_PACKET_SCHEMA,
193
+ packetId,
194
+ project: input.project,
195
+ generatedAt: now,
196
+ targetRole: input.targetRole,
197
+ task: input.task,
198
+ acceptanceCriteria: input.acceptanceCriteria ?? [],
199
+ plan: input.plan,
200
+ predecessors: input.predecessors ?? [],
201
+ environment: {
202
+ sharedDefaults,
203
+ projectKnowledge,
204
+ currentState,
205
+ contradictions,
206
+ activeSkills,
207
+ },
208
+ budget: {
209
+ allocatedTokens,
210
+ estimatedTokens,
211
+ unresolvedGaps: [],
212
+ provenanceSummary,
213
+ },
214
+ };
215
+ }
216
+
217
+ /**
218
+ * Formats a formal context packet into clean, bounded Markdown for injection into agent prompts.
219
+ */
220
+ export function formatContextPacketForPrompt(packet: FormalContextPacketV2): string {
221
+ const sections: string[] = [];
222
+
223
+ sections.push(`# Context Packet [${packet.packetId}]`);
224
+ sections.push(`**Project:** ${packet.project} | **Role:** ${packet.targetRole} | **Step:** ${packet.task.stepId} (Attempt ${packet.task.stepAttempt})`);
225
+ sections.push(`**Permission:** ${packet.task.permissionCeiling} | **Allowed Outcomes:** ${packet.task.allowedOutcomes.join(", ")}`);
226
+ sections.push("");
227
+
228
+ sections.push(`## 1. Objective`);
229
+ sections.push(packet.task.objective);
230
+ sections.push("");
231
+
232
+ if (packet.acceptanceCriteria.length > 0) {
233
+ sections.push(`## 2. Acceptance Criteria`);
234
+ for (const c of packet.acceptanceCriteria) {
235
+ sections.push(`- [ ] **${c.id}** (${c.verificationKind}${c.required ? ", required" : ""}): ${c.description}${c.targetRef ? ` [${c.targetRef}]` : ""}`);
236
+ }
237
+ sections.push("");
238
+ }
239
+
240
+ sections.push(`## 3. Plan Pointer`);
241
+ sections.push(`Plan Hash: \`${packet.plan.planHash}\` | Step ${packet.plan.activeStepIndex + 1} of ${packet.plan.totalSteps}`);
242
+ if (packet.plan.settledDecisions.length > 0) {
243
+ sections.push(`Settled Decisions:`);
244
+ for (const d of packet.plan.settledDecisions) {
245
+ sections.push(` - ${d}`);
246
+ }
247
+ }
248
+ sections.push("");
249
+
250
+ if (packet.predecessors.length > 0) {
251
+ sections.push(`## 4. Predecessor Outputs`);
252
+ for (const p of packet.predecessors) {
253
+ sections.push(`### Predecessor: ${p.stepId} (${p.role}) - ${p.status}`);
254
+ sections.push(p.summary);
255
+ if (p.artifacts.length > 0) {
256
+ sections.push(`Artifacts:`);
257
+ for (const a of p.artifacts) {
258
+ sections.push(` - \`${a.name}\` [${a.kind}] (${a.artifactRef})`);
259
+ if (a.contentSnippet) {
260
+ sections.push(` \`\`\`\n ${a.contentSnippet.trim()}\n \`\`\``);
261
+ }
262
+ }
263
+ }
264
+ }
265
+ sections.push("");
266
+ }
267
+
268
+ if (packet.environment.projectKnowledge.length > 0 || packet.environment.sharedDefaults.length > 0) {
269
+ sections.push(`## 5. Environment & Memory`);
270
+ if (packet.environment.sharedDefaults.length > 0) {
271
+ sections.push(`### Shared Defaults`);
272
+ for (const d of packet.environment.sharedDefaults) {
273
+ sections.push(`- ${d.summary}`);
274
+ }
275
+ }
276
+ if (packet.environment.projectKnowledge.length > 0) {
277
+ sections.push(`### Project Knowledge`);
278
+ for (const k of packet.environment.projectKnowledge.slice(0, 5)) {
279
+ sections.push(`- [${k.authority}] ${k.summary}`);
280
+ }
281
+ }
282
+ if (packet.environment.contradictions.length > 0) {
283
+ sections.push(`### Active Contradictions`);
284
+ for (const c of packet.environment.contradictions) {
285
+ sections.push(`- ⚠️ ${c.summary}`);
286
+ }
287
+ }
288
+ sections.push("");
289
+ }
290
+
291
+ return sections.join("\n").trim();
292
+ }
293
+
294
+ /**
295
+ * Builds a structured handoff manifest between workflow roles.
296
+ */
297
+ export function buildHandoffManifest(input: {
298
+ taskId: string;
299
+ workflowRunId: string;
300
+ reworkOf?: string | null | undefined;
301
+ source: HandoffManifestV1["source"];
302
+ target: HandoffManifestV1["target"];
303
+ intent: HandoffManifestV1["intent"];
304
+ baseCommit: string;
305
+ candidateTreeHash?: string | undefined;
306
+ deliverables: HandoffDeliverables;
307
+ verificationEvidence: HandoffVerificationEvidence;
308
+ openQuestions?: string[] | undefined;
309
+ suggestedNextStep?: HandoffManifestV1["suggestedNextStep"];
310
+ }): HandoffManifestV1 {
311
+ const handoffId = `hnd_${randomUUID().replaceAll("-", "").slice(0, 16)}`;
312
+ const createdAt = new Date().toISOString();
313
+
314
+ return {
315
+ schema: HANDOFF_MANIFEST_SCHEMA,
316
+ handoffId,
317
+ taskId: input.taskId,
318
+ workflowRunId: input.workflowRunId,
319
+ reworkOf: input.reworkOf ?? null,
320
+ source: input.source,
321
+ target: input.target,
322
+ intent: input.intent,
323
+ status: "pending",
324
+ baseCommit: input.baseCommit,
325
+ ...(input.candidateTreeHash ? { candidateTreeHash: input.candidateTreeHash } : {}),
326
+ deliverables: input.deliverables,
327
+ verificationEvidence: input.verificationEvidence,
328
+ openQuestions: input.openQuestions ?? [],
329
+ ...(input.suggestedNextStep ? { suggestedNextStep: input.suggestedNextStep } : {}),
330
+ createdAt,
331
+ };
332
+ }