@tiic-tech/openworkflow 0.1.0 → 0.1.2

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 (217) hide show
  1. package/README.md +10 -0
  2. package/dist/adapters/codex/src/cleanCodexAdapter.d.ts +7 -0
  3. package/dist/adapters/codex/src/cleanCodexAdapter.js +99 -0
  4. package/dist/adapters/codex/src/cleanCodexAdapter.js.map +1 -0
  5. package/dist/adapters/codex/src/constants.d.ts +1 -0
  6. package/dist/adapters/codex/src/constants.js +2 -0
  7. package/dist/adapters/codex/src/constants.js.map +1 -0
  8. package/dist/adapters/codex/src/generateCommands.js +14 -9
  9. package/dist/adapters/codex/src/generateCommands.js.map +1 -1
  10. package/dist/adapters/codex/src/generateSkills.js +13 -0
  11. package/dist/adapters/codex/src/generateSkills.js.map +1 -1
  12. package/dist/adapters/codex/src/generatedFiles.js +1 -1
  13. package/dist/adapters/codex/src/manifest.js +11 -2
  14. package/dist/adapters/codex/src/manifest.js.map +1 -1
  15. package/dist/adapters/codex/src/templates.d.ts +0 -1
  16. package/dist/adapters/codex/src/templates.js +0 -1
  17. package/dist/adapters/codex/src/templates.js.map +1 -1
  18. package/dist/adapters/src/registry.d.ts +20 -0
  19. package/dist/adapters/src/registry.js +81 -0
  20. package/dist/adapters/src/registry.js.map +1 -0
  21. package/dist/cli/src/commands/brief.d.ts +46 -0
  22. package/dist/cli/src/commands/brief.js +294 -0
  23. package/dist/cli/src/commands/brief.js.map +1 -0
  24. package/dist/cli/src/commands/check.d.ts +42 -0
  25. package/dist/cli/src/commands/check.js +326 -0
  26. package/dist/cli/src/commands/check.js.map +1 -0
  27. package/dist/cli/src/commands/clean.d.ts +1 -0
  28. package/dist/cli/src/commands/clean.js +98 -0
  29. package/dist/cli/src/commands/clean.js.map +1 -0
  30. package/dist/cli/src/commands/context.d.ts +1 -0
  31. package/dist/cli/src/commands/context.js +471 -0
  32. package/dist/cli/src/commands/context.js.map +1 -0
  33. package/dist/cli/src/commands/doctor.js +122 -12
  34. package/dist/cli/src/commands/doctor.js.map +1 -1
  35. package/dist/cli/src/commands/draft.d.ts +1 -0
  36. package/dist/cli/src/commands/draft.js +175 -0
  37. package/dist/cli/src/commands/draft.js.map +1 -0
  38. package/dist/cli/src/commands/gitAutomation.d.ts +1 -0
  39. package/dist/cli/src/commands/gitAutomation.js +378 -0
  40. package/dist/cli/src/commands/gitAutomation.js.map +1 -0
  41. package/dist/cli/src/commands/handoff.d.ts +22 -0
  42. package/dist/cli/src/commands/handoff.js +122 -0
  43. package/dist/cli/src/commands/handoff.js.map +1 -0
  44. package/dist/cli/src/commands/init.js +52 -1
  45. package/dist/cli/src/commands/init.js.map +1 -1
  46. package/dist/cli/src/commands/inspect.d.ts +23 -0
  47. package/dist/cli/src/commands/inspect.js +157 -0
  48. package/dist/cli/src/commands/inspect.js.map +1 -0
  49. package/dist/cli/src/commands/register.d.ts +1 -0
  50. package/dist/cli/src/commands/register.js +251 -0
  51. package/dist/cli/src/commands/register.js.map +1 -0
  52. package/dist/cli/src/commands/resume.d.ts +59 -0
  53. package/dist/cli/src/commands/resume.js +280 -0
  54. package/dist/cli/src/commands/resume.js.map +1 -0
  55. package/dist/cli/src/commands/shared.js +6 -2
  56. package/dist/cli/src/commands/shared.js.map +1 -1
  57. package/dist/cli/src/commands/summaries.d.ts +1 -0
  58. package/dist/cli/src/commands/summaries.js +77 -0
  59. package/dist/cli/src/commands/summaries.js.map +1 -0
  60. package/dist/cli/src/commands/summarize.d.ts +1 -0
  61. package/dist/cli/src/commands/summarize.js +316 -0
  62. package/dist/cli/src/commands/summarize.js.map +1 -0
  63. package/dist/cli/src/commands/sync.js +135 -12
  64. package/dist/cli/src/commands/sync.js.map +1 -1
  65. package/dist/cli/src/commands/validate.js +25 -1
  66. package/dist/cli/src/commands/validate.js.map +1 -1
  67. package/dist/cli/src/dev/verifyAgentE2E.d.ts +2 -0
  68. package/dist/cli/src/dev/verifyAgentE2E.js +391 -0
  69. package/dist/cli/src/dev/verifyAgentE2E.js.map +1 -0
  70. package/dist/cli/src/dev/verifyCleanCommand.d.ts +2 -0
  71. package/dist/cli/src/dev/verifyCleanCommand.js +338 -0
  72. package/dist/cli/src/dev/verifyCleanCommand.js.map +1 -0
  73. package/dist/cli/src/dev/verifyRuntimeSurface.js +4940 -54
  74. package/dist/cli/src/dev/verifyRuntimeSurface.js.map +1 -1
  75. package/dist/cli/src/dev/verifyWorkflowE2E.js +477 -45
  76. package/dist/cli/src/dev/verifyWorkflowE2E.js.map +1 -1
  77. package/dist/cli/src/index.js +189 -5
  78. package/dist/cli/src/index.js.map +1 -1
  79. package/dist/cli/src/report.d.ts +26 -0
  80. package/dist/cli/src/report.js +17 -0
  81. package/dist/cli/src/report.js.map +1 -0
  82. package/dist/core/src/artifacts/readiness.d.ts +7 -0
  83. package/dist/core/src/artifacts/readiness.js +240 -0
  84. package/dist/core/src/artifacts/readiness.js.map +1 -0
  85. package/dist/core/src/artifacts/registry.d.ts +9 -2
  86. package/dist/core/src/artifacts/registry.js +687 -60
  87. package/dist/core/src/artifacts/registry.js.map +1 -1
  88. package/dist/core/src/commands/registry.js +1425 -146
  89. package/dist/core/src/commands/registry.js.map +1 -1
  90. package/dist/core/src/contracts/index.d.ts +1 -1
  91. package/dist/core/src/fs/index.d.ts +24 -0
  92. package/dist/core/src/fs/index.js +48 -1
  93. package/dist/core/src/fs/index.js.map +1 -1
  94. package/dist/core/src/git/autonomousSimulator.d.ts +46 -0
  95. package/dist/core/src/git/autonomousSimulator.js +163 -0
  96. package/dist/core/src/git/autonomousSimulator.js.map +1 -0
  97. package/dist/core/src/git/branchIdentity.d.ts +19 -0
  98. package/dist/core/src/git/branchIdentity.js +75 -0
  99. package/dist/core/src/git/branchIdentity.js.map +1 -0
  100. package/dist/core/src/git/draftPrPilot.d.ts +47 -0
  101. package/dist/core/src/git/draftPrPilot.js +196 -0
  102. package/dist/core/src/git/draftPrPilot.js.map +1 -0
  103. package/dist/core/src/git/localEvidenceReader.d.ts +21 -0
  104. package/dist/core/src/git/localEvidenceReader.js +142 -0
  105. package/dist/core/src/git/localEvidenceReader.js.map +1 -0
  106. package/dist/core/src/git/localGitAutomation.d.ts +68 -0
  107. package/dist/core/src/git/localGitAutomation.js +470 -0
  108. package/dist/core/src/git/localGitAutomation.js.map +1 -0
  109. package/dist/core/src/git/mergeReadinessCheckpoint.d.ts +31 -0
  110. package/dist/core/src/git/mergeReadinessCheckpoint.js +110 -0
  111. package/dist/core/src/git/mergeReadinessCheckpoint.js.map +1 -0
  112. package/dist/core/src/git/prReadySummary.d.ts +16 -0
  113. package/dist/core/src/git/prReadySummary.js +144 -0
  114. package/dist/core/src/git/prReadySummary.js.map +1 -0
  115. package/dist/core/src/git/remoteReadonlyPlanner.d.ts +60 -0
  116. package/dist/core/src/git/remoteReadonlyPlanner.js +223 -0
  117. package/dist/core/src/git/remoteReadonlyPlanner.js.map +1 -0
  118. package/dist/core/src/onboarding/agentsGuide.d.ts +32 -0
  119. package/dist/core/src/onboarding/agentsGuide.js +164 -0
  120. package/dist/core/src/onboarding/agentsGuide.js.map +1 -0
  121. package/dist/core/src/validators/validateOpenWorkflow.js +1331 -15
  122. package/dist/core/src/validators/validateOpenWorkflow.js.map +1 -1
  123. package/dist/core/src/validators/validateRepositoryContracts.js +2327 -306
  124. package/dist/core/src/validators/validateRepositoryContracts.js.map +1 -1
  125. package/dist/core/src/workflow/cleanOpenWorkflow.d.ts +18 -0
  126. package/dist/core/src/workflow/cleanOpenWorkflow.js +124 -0
  127. package/dist/core/src/workflow/cleanOpenWorkflow.js.map +1 -0
  128. package/dist/core/src/workflow/doctorOpenWorkflow.d.ts +7 -0
  129. package/dist/core/src/workflow/doctorOpenWorkflow.js +26 -0
  130. package/dist/core/src/workflow/doctorOpenWorkflow.js.map +1 -0
  131. package/dist/core/src/workflow/initOpenWorkflow.d.ts +7 -0
  132. package/dist/core/src/workflow/initOpenWorkflow.js +96 -8
  133. package/dist/core/src/workflow/initOpenWorkflow.js.map +1 -1
  134. package/dist/core/src/workflow/planningQueueResume.d.ts +105 -0
  135. package/dist/core/src/workflow/planningQueueResume.js +596 -0
  136. package/dist/core/src/workflow/planningQueueResume.js.map +1 -0
  137. package/dist/core/src/workflow/readWorkflowConfig.d.ts +6 -0
  138. package/dist/core/src/workflow/readWorkflowConfig.js +28 -0
  139. package/dist/core/src/workflow/readWorkflowConfig.js.map +1 -0
  140. package/dist/core/src/workflow/summaryHealth.d.ts +60 -0
  141. package/dist/core/src/workflow/summaryHealth.js +713 -0
  142. package/dist/core/src/workflow/summaryHealth.js.map +1 -0
  143. package/dist/core/src/workflow/syncOpenWorkflow.d.ts +22 -0
  144. package/dist/core/src/workflow/syncOpenWorkflow.js +235 -0
  145. package/dist/core/src/workflow/syncOpenWorkflow.js.map +1 -0
  146. package/package.json +4 -2
  147. package/references/artifact-authoring-templates.md +14 -12
  148. package/references/artifact-instruction-envelope.md +133 -0
  149. package/references/coder-continuous-growth-loop.md +68 -0
  150. package/references/gh-operation-governance.md +114 -0
  151. package/references/git-automation-governance.md +324 -0
  152. package/references/git-version-control-governance.md +227 -0
  153. package/references/internal-coder-protocol.md +202 -0
  154. package/references/issue-governance.md +115 -0
  155. package/references/planning-artifact-contracts.md +595 -0
  156. package/references/planning-skill-runtime-exposure.md +159 -0
  157. package/references/proto-redesign-artifact-contracts.md +217 -0
  158. package/references/proto2html-artifact-contracts.md +113 -0
  159. package/references/skill-system-lifecycle.md +198 -0
  160. package/references/validation-trust-domains.md +286 -0
  161. package/references/workflow-blueprint-runtime-alignment.md +287 -0
  162. package/schemas/atom-tasks.schema.json +101 -0
  163. package/schemas/candidate-changes.schema.json +323 -0
  164. package/schemas/current-state.schema.json +113 -0
  165. package/schemas/html-prototype.schema.json +288 -0
  166. package/schemas/openworkflow-contract.schema.json +9 -1
  167. package/schemas/proto-prompt-pack.schema.json +1333 -0
  168. package/schemas/prototype-evidence.schema.json +684 -142
  169. package/schemas/selected-change.schema.json +104 -0
  170. package/schemas/validation-target.schema.json +187 -1
  171. package/schemas/validation.schema.json +187 -1
  172. package/schemas/vision-session.schema.json +151 -0
  173. package/skills/analyze-changes/SKILL.md +92 -0
  174. package/skills/analyze-changes/agents/openai.yaml +4 -0
  175. package/skills/analyze-changes/references/analysis-protocol.md +116 -0
  176. package/skills/build-proto-prompt/SKILL.md +125 -0
  177. package/skills/build-proto-prompt/references/output-boundary.md +54 -0
  178. package/skills/build-proto-prompt/references/prompt-pack-compiler-protocol.md +80 -0
  179. package/skills/build-prototype/SKILL.md +162 -38
  180. package/skills/build-prototype/agents/openai.yaml +2 -2
  181. package/skills/build-prototype/references/philosophy-engine.md +61 -0
  182. package/skills/build-prototype/references/strategic-prompt-pack-protocol.md +365 -0
  183. package/skills/build-prototype/references/vision2prompt/01_input_contract.md +84 -0
  184. package/skills/build-prototype/references/vision2prompt/02_vision_decomposition.md +108 -0
  185. package/skills/build-prototype/references/vision2prompt/03_strategy_hypothesis_generation.md +89 -0
  186. package/skills/build-prototype/references/vision2prompt/04_product_system_extraction.md +78 -0
  187. package/skills/build-prototype/references/vision2prompt/05_prototype_prompt_schema.md +189 -0
  188. package/skills/build-prototype/references/vision2prompt/06_output_templates.md +125 -0
  189. package/skills/build-prototype/references/vision2prompt/07_quality_rubric.md +171 -0
  190. package/skills/build-validation/SKILL.md +136 -54
  191. package/skills/build-validation/references/prototype-validation-target-rubric.md +35 -0
  192. package/skills/build-validation/references/return-to-vision-gate.md +32 -0
  193. package/skills/build-vision/SKILL.md +192 -0
  194. package/skills/build-vision/references/proto-readiness-rubric.md +48 -0
  195. package/skills/build-vision/references/vision-interview-protocol.md +48 -0
  196. package/skills/coder/SKILL.md +204 -0
  197. package/skills/decompose-to-changes/SKILL.md +176 -0
  198. package/skills/decompose-to-changes/agents/openai.yaml +4 -0
  199. package/skills/decompose-to-changes/references/decomposition-protocol.md +278 -0
  200. package/skills/prompt2proto/SKILL.md +157 -0
  201. package/skills/prompt2proto/agents/openai.yaml +4 -0
  202. package/skills/prompt2proto/references/00_role_philosophy_engine.md +96 -0
  203. package/skills/prompt2proto/references/01_input_contract.md +53 -0
  204. package/skills/prompt2proto/references/02_prompt_pack_readiness.md +50 -0
  205. package/skills/prompt2proto/references/03_visual_translation_workflow.md +64 -0
  206. package/skills/prompt2proto/references/04_output_contract.md +67 -0
  207. package/skills/prompt2proto/references/05_quality_rubric.md +46 -0
  208. package/skills/proto2html/SKILL.md +136 -0
  209. package/skills/proto2html/agents/openai.yaml +4 -0
  210. package/skills/proto2html/references/proto2html-protocol.md +115 -0
  211. package/skills/run-team/SKILL.md +4 -0
  212. package/skills/select-change/SKILL.md +200 -0
  213. package/skills/select-change/agents/openai.yaml +4 -0
  214. package/skills/select-change/references/selection-protocol.md +281 -0
  215. package/skills/tune-prototype/SKILL.md +121 -0
  216. package/skills/tune-prototype/agents/openai.yaml +4 -0
  217. package/skills/tune-prototype/references/refined-prompt-pack-protocol.md +161 -0
@@ -0,0 +1,713 @@
1
+ import { readdir, stat } from "node:fs/promises";
2
+ import { basename, dirname, join, relative } from "node:path";
3
+ import { parseYaml } from "../contracts/yaml.js";
4
+ import { isNotFound, readTextFile } from "../fs/index.js";
5
+ import { assessBranchIdentity, branchIdentityExceptionFrom } from "../git/branchIdentity.js";
6
+ export async function evaluateSummaryHealth(root) {
7
+ const contractsPath = join(root, ".openworkflow", "audit", "ARTIFACT_CONTRACTS.yaml");
8
+ const contracts = await loadArtifactContracts(contractsPath);
9
+ if (!contracts) {
10
+ return {
11
+ ok: false,
12
+ initialized: false,
13
+ contracts_path: ".openworkflow/audit/ARTIFACT_CONTRACTS.yaml",
14
+ counts: emptyCounts(),
15
+ entries: [],
16
+ planning_queue_health_errors: [],
17
+ planning_queue_guidance: [],
18
+ warnings: ["missing OpenWorkflow artifact contracts: .openworkflow/audit/ARTIFACT_CONTRACTS.yaml"],
19
+ next_actions: ["run openworkflow init <folder> --tools codex, or run openworkflow sync on an initialized project"],
20
+ };
21
+ }
22
+ const entries = await Promise.all(contracts.map((contract) => evaluateContract(root, contract)));
23
+ const planningQueueAudit = await evaluatePlanningQueueCommitEvidence(root);
24
+ const warnings = unique([
25
+ ...entries.flatMap((entry) => entry.warnings),
26
+ ...planningQueueAudit.guidance,
27
+ ]);
28
+ const nextActions = unique([
29
+ ...entries.flatMap((entry) => entry.next_actions),
30
+ ...planningQueueAudit.next_actions,
31
+ ]);
32
+ return {
33
+ ok: !entries.some((entry) => ["missing", "stale_unknown"].includes(entry.status)),
34
+ initialized: true,
35
+ contracts_path: ".openworkflow/audit/ARTIFACT_CONTRACTS.yaml",
36
+ counts: countStatuses(entries),
37
+ entries,
38
+ planning_queue_health_errors: planningQueueAudit.health_errors,
39
+ planning_queue_guidance: planningQueueAudit.guidance,
40
+ warnings,
41
+ next_actions: nextActions,
42
+ };
43
+ }
44
+ export function evaluateSummaryQualityGate(health, strict) {
45
+ const healthErrors = strict ? summaryQualityHealthErrors(health) : [];
46
+ return {
47
+ strict,
48
+ ok: healthErrors.length === 0,
49
+ health_errors: healthErrors,
50
+ };
51
+ }
52
+ export function summaryQualityHealthErrors(health) {
53
+ return unique([
54
+ ...health.entries.flatMap((entry) => entry.items.flatMap((item) => {
55
+ if (item.quality_status !== "current_but_thin") {
56
+ return [];
57
+ }
58
+ const details = item.quality_warnings.length > 0
59
+ ? item.quality_warnings
60
+ : [`summary source quality is current_but_thin: ${item.artifact_path}`];
61
+ return details.map((detail) => `summary quality ${entry.artifact_type}: ${detail}`);
62
+ })),
63
+ ...health.planning_queue_health_errors,
64
+ ]);
65
+ }
66
+ export function buildSummaryQualitySummary(health, strictQuality = evaluateSummaryQualityGate(health, true)) {
67
+ const currentButThinCount = health.entries.reduce((count, entry) => count + entry.items.filter((item) => item.quality_status === "current_but_thin").length, 0);
68
+ const freshnessHealthErrorCount = health.ok ? 0 : health.warnings.length;
69
+ const strictQualityHealthErrorCount = strictQuality.health_errors.length;
70
+ const handoffQualityOk = health.ok && strictQuality.ok;
71
+ return {
72
+ initialized: health.initialized,
73
+ status: summaryQualitySummaryStatus(health, strictQuality),
74
+ freshness_ok: health.ok,
75
+ strict_quality_ok: strictQuality.ok,
76
+ handoff_quality_ok: handoffQualityOk,
77
+ counts: health.counts,
78
+ instantiated_count: health.entries.reduce((count, entry) => count + entry.instantiated_count, 0),
79
+ current_but_thin_count: currentButThinCount,
80
+ freshness_health_error_count: freshnessHealthErrorCount,
81
+ strict_quality_health_error_count: strictQualityHealthErrorCount,
82
+ health_error_count: freshnessHealthErrorCount + strictQualityHealthErrorCount,
83
+ warning_count: health.warnings.length,
84
+ next_actions: summaryQualityNextActions(health, strictQuality),
85
+ };
86
+ }
87
+ function summaryQualitySummaryStatus(health, strictQuality) {
88
+ if (!health.initialized) {
89
+ return "not_initialized";
90
+ }
91
+ if (!health.ok) {
92
+ return "needs_refresh";
93
+ }
94
+ if (!strictQuality.ok) {
95
+ return "current_but_thin";
96
+ }
97
+ return "trusted";
98
+ }
99
+ function summaryQualityNextActions(health, strictQuality) {
100
+ if (!health.initialized) {
101
+ return ["run openworkflow init <folder> --tools codex, or run openworkflow sync on an initialized project"];
102
+ }
103
+ return unique([
104
+ ...(!health.ok ? health.next_actions : []),
105
+ ...(health.planning_queue_health_errors.length > 0 ? [
106
+ "repair selected-change commit evidence before trusting handoff; run openworkflow git-automation commit for the affected candidate",
107
+ ] : []),
108
+ ...(!strictQuality.ok ? ["run openworkflow summaries --root . --strict --json before trusting artifact handoff quality"] : []),
109
+ ]);
110
+ }
111
+ async function loadArtifactContracts(contractsPath) {
112
+ try {
113
+ const parsed = parseYaml(await readTextFile(contractsPath));
114
+ if (isRecord(parsed) && Array.isArray(parsed.artifacts)) {
115
+ return parsed.artifacts.flatMap((artifact) => {
116
+ const mapped = artifactContractFromRecord(artifact);
117
+ return mapped ? [mapped] : [];
118
+ });
119
+ }
120
+ return [];
121
+ }
122
+ catch (error) {
123
+ if (!isNotFound(error)) {
124
+ throw error;
125
+ }
126
+ return null;
127
+ }
128
+ }
129
+ function artifactContractFromRecord(value) {
130
+ if (!isRecord(value)) {
131
+ return null;
132
+ }
133
+ const artifactType = stringValue(value.artifact_type);
134
+ const command = stringValue(value.command);
135
+ const sourceOfTruthPath = stringValue(value.source_of_truth_path);
136
+ if (!artifactType || !command || !sourceOfTruthPath) {
137
+ return null;
138
+ }
139
+ return {
140
+ artifactType,
141
+ command,
142
+ sourceOfTruthPath,
143
+ summaryPolicy: summaryPolicyFromRecord(value.summary_policy),
144
+ };
145
+ }
146
+ function summaryPolicyFromRecord(value) {
147
+ if (!isRecord(value)) {
148
+ return undefined;
149
+ }
150
+ const strategy = stringValue(value.strategy);
151
+ const path = stringValue(value.path);
152
+ if ((strategy !== "summary_file" && strategy !== "current_slice") || !path) {
153
+ return undefined;
154
+ }
155
+ return {
156
+ strategy,
157
+ path,
158
+ loadBeforeFull: value.load_before_full === true,
159
+ refreshWhen: stringValue(value.refresh_when) ?? "",
160
+ };
161
+ }
162
+ async function evaluateContract(root, contract) {
163
+ if (!contract.summaryPolicy) {
164
+ return {
165
+ artifact_type: contract.artifactType,
166
+ command: contract.command,
167
+ strategy: "none",
168
+ policy_path: null,
169
+ status: "not_applicable",
170
+ instantiated_count: 0,
171
+ items: [],
172
+ warnings: [],
173
+ next_actions: [],
174
+ };
175
+ }
176
+ const artifacts = await findInstantiatedArtifacts(root, contract);
177
+ if (artifacts.length === 0) {
178
+ return {
179
+ artifact_type: contract.artifactType,
180
+ command: contract.command,
181
+ strategy: contract.summaryPolicy.strategy,
182
+ policy_path: contract.summaryPolicy.path,
183
+ status: "not_instantiated",
184
+ instantiated_count: 0,
185
+ items: [],
186
+ warnings: [],
187
+ next_actions: [],
188
+ };
189
+ }
190
+ const items = await Promise.all(artifacts.map((path) => evaluateArtifact(root, path, contract)));
191
+ const status = aggregateStatus(items.map((item) => item.status));
192
+ const warnings = items.flatMap((item) => item.warnings);
193
+ return {
194
+ artifact_type: contract.artifactType,
195
+ command: contract.command,
196
+ strategy: contract.summaryPolicy.strategy,
197
+ policy_path: contract.summaryPolicy.path,
198
+ status,
199
+ instantiated_count: items.length,
200
+ items,
201
+ warnings,
202
+ next_actions: nextActionsFor(status, contract),
203
+ };
204
+ }
205
+ async function evaluateArtifact(root, artifactPath, contract) {
206
+ if (!contract.summaryPolicy) {
207
+ return {
208
+ artifact_path: artifactPath,
209
+ summary_path: null,
210
+ current_slice: null,
211
+ status: "not_applicable",
212
+ source_status: null,
213
+ empty_key_fields: [],
214
+ quality_status: "unknown",
215
+ quality_warnings: [],
216
+ warnings: [],
217
+ };
218
+ }
219
+ const source = await readYamlRecord(join(root, artifactPath));
220
+ const quality = qualityForArtifact(artifactPath, contract.artifactType, source);
221
+ if (contract.summaryPolicy.strategy === "current_slice") {
222
+ const fields = currentSliceFields(contract.summaryPolicy.path);
223
+ const missing = fields.filter((field) => !hasNonEmptyValue(source?.[field]));
224
+ return {
225
+ artifact_path: artifactPath,
226
+ summary_path: null,
227
+ current_slice: fields,
228
+ status: missing.length === 0 ? "current" : "missing",
229
+ ...quality,
230
+ warnings: [
231
+ ...missing.map((field) => `missing current_slice field ${field} in ${artifactPath}`),
232
+ ...quality.quality_warnings,
233
+ ],
234
+ };
235
+ }
236
+ const summaryPath = summaryPathForArtifact(artifactPath, contract);
237
+ const artifactStat = await stat(join(root, artifactPath));
238
+ const summaryStat = await statOptional(join(root, summaryPath));
239
+ if (!summaryStat) {
240
+ return {
241
+ artifact_path: artifactPath,
242
+ summary_path: summaryPath,
243
+ current_slice: null,
244
+ status: "missing",
245
+ ...quality,
246
+ warnings: [`missing summary file: ${summaryPath}`],
247
+ };
248
+ }
249
+ const current = summaryStat.mtimeMs >= artifactStat.mtimeMs;
250
+ return {
251
+ artifact_path: artifactPath,
252
+ summary_path: summaryPath,
253
+ current_slice: null,
254
+ status: current ? "current" : "stale_unknown",
255
+ ...quality,
256
+ warnings: current ? quality.quality_warnings : [`summary may be stale: ${summaryPath}`, ...quality.quality_warnings],
257
+ };
258
+ }
259
+ function qualityForArtifact(artifactPath, artifactType, source) {
260
+ if (!source) {
261
+ return {
262
+ source_status: null,
263
+ empty_key_fields: qualityFieldsForArtifact(artifactType),
264
+ quality_status: "current_but_thin",
265
+ quality_warnings: [`source artifact could not be read for quality assessment: ${artifactPath}`],
266
+ };
267
+ }
268
+ const sourceStatus = stringValue(source.status);
269
+ const emptyKeyFields = qualityFieldsForArtifact(artifactType).filter((field) => !hasNonEmptyValue(valueAtPath(source, field)));
270
+ const readinessWarnings = readinessWarningsForArtifact(artifactPath, artifactType, source);
271
+ const qualityWarnings = [
272
+ ...(sourceStatus === "draft" ? [`source artifact is draft: ${artifactPath}`] : []),
273
+ ...(emptyKeyFields.length > 0 ? [`source artifact has empty handoff fields in ${artifactPath}: ${emptyKeyFields.join(", ")}`] : []),
274
+ ...readinessWarnings,
275
+ ];
276
+ return {
277
+ source_status: sourceStatus,
278
+ empty_key_fields: emptyKeyFields,
279
+ quality_status: qualityWarnings.length > 0 ? "current_but_thin" : "usable",
280
+ quality_warnings: qualityWarnings,
281
+ };
282
+ }
283
+ function qualityFieldsForArtifact(artifactType) {
284
+ if (artifactType === "vision_session") {
285
+ return [
286
+ "vision_delta.one_sentence",
287
+ "vision_delta.problem",
288
+ "vision_delta.users",
289
+ "vision_delta.goals",
290
+ "vision_delta.non_goals",
291
+ "vision_delta.quality_bar",
292
+ "vision_delta.ai_native_role",
293
+ "vision_delta.success_signals",
294
+ "vision_delta.failure_signals",
295
+ "strategic_core.target_user",
296
+ "strategic_core.current_alternative",
297
+ "strategic_core.desired_behavior_change",
298
+ "strategic_core.core_mechanism",
299
+ "strategic_core.core_differentiator",
300
+ "strategic_core.strongest_success_signal",
301
+ "product_system_seed.product_thesis",
302
+ "product_system_seed.primary_loop",
303
+ "product_system_seed.trust_boundary",
304
+ "product_system_seed.anti_goals",
305
+ "proto_readiness.prototype_direction_seeds",
306
+ "proto_readiness.prompt_constraints",
307
+ "proto_readiness.validation_target",
308
+ "proto_readiness.status",
309
+ ];
310
+ }
311
+ if (artifactType === "validation_target") {
312
+ return [
313
+ "core_question",
314
+ "central_uncertainty",
315
+ "target_behavior",
316
+ "prototype_scope",
317
+ "prototype_experiment.scenario",
318
+ "prototype_experiment.must_show",
319
+ "observable_signals.pass",
320
+ "observable_signals.fail",
321
+ "acceptance",
322
+ "decision_rules.continue",
323
+ "decision_rules.revise",
324
+ "agent_readiness_gate.status",
325
+ ];
326
+ }
327
+ if (artifactType === "prototype_evidence") {
328
+ return [
329
+ "core_question",
330
+ "prompt_pack_type",
331
+ "internal_pipeline.current_stage",
332
+ "preflight_quality_gate.can_proceed",
333
+ "direction_count_policy.resolved_count",
334
+ "normalized_input.primary_user",
335
+ "normalized_input.desired_behavior_change",
336
+ "normalized_input.strongest_success_signal",
337
+ "strategic_core.central_uncertainty",
338
+ "prototype_brief.product_name",
339
+ "prototype_brief.positioning",
340
+ "prototype_brief.primary_loop",
341
+ "product_experience_model.product_archetype",
342
+ "product_experience_model.primary_canvas",
343
+ "product_experience_model.domain_object_model",
344
+ "product_experience_model.primary_task_loop",
345
+ "product_experience_model.interaction_state_model",
346
+ "product_experience_model.anti_generic_constraints",
347
+ "screen_manifest",
348
+ "global_design_system_prompt.visual_language",
349
+ "global_design_system_prompt.layout_system",
350
+ "global_design_system_prompt.negative_visual_patterns",
351
+ "quality_rubric.prompt_executability",
352
+ "quality_rubric.prompt_paragraph_quality",
353
+ "quality_rubric.state_coverage",
354
+ "prototype_reality_gate.status",
355
+ "prototype_reality_gate.dimensions",
356
+ "prompt_pack_integrity_gate.status",
357
+ "prompt_pack_integrity_gate.dimensions",
358
+ "directions",
359
+ "build_recommendation.first_direction_id",
360
+ "prompt_text_manifest.status",
361
+ "prompt_text_manifest.paragraph_quality_status",
362
+ "prompt_text_manifest.paragraph_quality_dimensions",
363
+ "image_generation.status",
364
+ "review_plan",
365
+ "result",
366
+ ];
367
+ }
368
+ if (artifactType === "decision_record") {
369
+ return ["outcome", "rationale", "next_command"];
370
+ }
371
+ if (artifactType === "product_design") {
372
+ return ["personas", "journey_map", "user_stories", "spec_readiness"];
373
+ }
374
+ if (artifactType === "production_spec") {
375
+ return ["goal", "scope", "requirements", "verification", "change_readiness"];
376
+ }
377
+ if (artifactType === "production_change") {
378
+ return ["problem", "goals", "affected_paths", "acceptance", "validation", "work_items", "runtime_readiness"];
379
+ }
380
+ if (artifactType === "team_runtime") {
381
+ return ["active_work_item", "work_queue", "verification", "handoff"];
382
+ }
383
+ return [];
384
+ }
385
+ function readinessWarningsForArtifact(artifactPath, artifactType, source) {
386
+ if (artifactType === "vision_session") {
387
+ const protoReadinessStatus = stringValue(valueAtPath(source, "proto_readiness.status"));
388
+ if (protoReadinessStatus !== "ready") {
389
+ return [`vision proto_readiness.status is not ready in ${artifactPath}: ${protoReadinessStatus || "missing"}`];
390
+ }
391
+ return [];
392
+ }
393
+ if (artifactType === "validation_target") {
394
+ const readinessStatus = stringValue(valueAtPath(source, "agent_readiness_gate.status"));
395
+ if (readinessStatus !== "ready_for_proto") {
396
+ return [`validation agent_readiness_gate.status is not ready_for_proto in ${artifactPath}: ${readinessStatus || "missing"}`];
397
+ }
398
+ }
399
+ return [];
400
+ }
401
+ async function findInstantiatedArtifacts(root, contract) {
402
+ const stageRoot = contract.sourceOfTruthPath.split("/<id>/", 1)[0];
403
+ const fileName = basename(contract.sourceOfTruthPath);
404
+ if (!stageRoot || fileName.includes("<")) {
405
+ return [];
406
+ }
407
+ const absoluteStageRoot = join(root, stageRoot);
408
+ if (!(await statOptional(absoluteStageRoot))) {
409
+ return [];
410
+ }
411
+ const found = await findFilesNamed(absoluteStageRoot, fileName);
412
+ return found.map((path) => relative(root, path)).sort();
413
+ }
414
+ async function findFilesNamed(root, fileName) {
415
+ const entries = await readdir(root, { withFileTypes: true });
416
+ const found = [];
417
+ for (const entry of entries) {
418
+ const path = join(root, entry.name);
419
+ if (entry.isDirectory()) {
420
+ if (entry.name.startsWith("_")) {
421
+ continue;
422
+ }
423
+ found.push(...(await findFilesNamed(path, fileName)));
424
+ }
425
+ else if (entry.isFile() && entry.name === fileName) {
426
+ found.push(path);
427
+ }
428
+ }
429
+ return found;
430
+ }
431
+ async function evaluatePlanningQueueCommitEvidence(root) {
432
+ const changesRoot = join(root, "changes");
433
+ if (!(await statOptional(changesRoot))) {
434
+ return { health_errors: [], guidance: [], next_actions: [] };
435
+ }
436
+ const queuePaths = await findFilesNamed(changesRoot, "CANDIDATE_CHANGES.yaml");
437
+ const healthErrors = [];
438
+ const guidance = [];
439
+ for (const queuePath of queuePaths) {
440
+ const queue = await readYamlRecord(queuePath);
441
+ if (!queue || queue.planning_artifact_type !== "candidate_changes") {
442
+ continue;
443
+ }
444
+ const queuePolicy = recordValue(queue.queue_policy);
445
+ if (queuePolicy.selected_change_commit_gate === "strict") {
446
+ healthErrors.push(...(await strictQueueCommitEvidenceErrors(root, queuePath, queue)));
447
+ guidance.push(...coderGateGuidance(root, queuePath, queue));
448
+ }
449
+ if (queuePolicy.git_lifecycle_gate === "strict") {
450
+ healthErrors.push(...(await strictQueueLifecycleErrors(root, queuePath, queue)));
451
+ }
452
+ }
453
+ return {
454
+ health_errors: unique(healthErrors),
455
+ guidance: unique(guidance),
456
+ next_actions: healthErrors.length > 0
457
+ ? ["repair selected-change commit evidence or git lifecycle evidence before trusting handoff"]
458
+ : [],
459
+ };
460
+ }
461
+ async function strictQueueLifecycleErrors(root, queuePath, queue) {
462
+ const label = relative(root, queuePath);
463
+ const queuePolicy = recordValue(queue.queue_policy);
464
+ const errors = [];
465
+ const planId = stringValue(queue.plan_id) ?? basename(dirname(queuePath));
466
+ const branchBoundary = stringValue(queuePolicy.branch_boundary);
467
+ if (!branchBoundary) {
468
+ errors.push(`git lifecycle gate ${label}: queue_policy.branch_boundary is required`);
469
+ }
470
+ else {
471
+ const branchIdentity = assessBranchIdentity(planId, branchBoundary, branchIdentityExceptionFrom(queuePolicy.branch_identity_exception), "validate");
472
+ errors.push(...branchIdentity.errors.map((error) => `git lifecycle gate ${label}: ${error}`));
473
+ }
474
+ const status = stringValue(queue.status);
475
+ if (status === "completed" || status === "done") {
476
+ const evidencePath = queuePrEvidencePath(queue);
477
+ if (!evidencePath) {
478
+ errors.push(`git lifecycle gate ${label}: completed queue must include DRAFT_PR_OPERATION_EVIDENCE.yaml`);
479
+ }
480
+ else if (evidencePath.startsWith("/") || evidencePath.includes("://") || evidencePath.startsWith("..")) {
481
+ errors.push(`git lifecycle gate ${label}: DRAFT_PR_OPERATION_EVIDENCE.yaml must be repo-relative`);
482
+ }
483
+ else if (!(await statOptional(join(root, evidencePath)))) {
484
+ errors.push(`git lifecycle gate ${label}: missing ${evidencePath}`);
485
+ }
486
+ }
487
+ return errors;
488
+ }
489
+ function queuePrEvidencePath(queue) {
490
+ const completion = recordValue(queue.completion);
491
+ const direct = stringValue(completion.draft_pr_evidence_path)
492
+ ?? stringValue(completion.draft_pr_evidence)
493
+ ?? stringValue(completion.pr_evidence_path)
494
+ ?? stringValue(completion.pr_evidence);
495
+ if (direct?.endsWith("DRAFT_PR_OPERATION_EVIDENCE.yaml")) {
496
+ return direct;
497
+ }
498
+ const evidence = Array.isArray(completion.evidence) ? completion.evidence : [];
499
+ for (const item of evidence) {
500
+ if (typeof item === "string" && item.endsWith("DRAFT_PR_OPERATION_EVIDENCE.yaml")) {
501
+ return item;
502
+ }
503
+ }
504
+ return null;
505
+ }
506
+ function coderGateGuidance(root, queuePath, queue) {
507
+ const label = relative(root, queuePath);
508
+ const changes = Array.isArray(queue.changes) ? queue.changes : [];
509
+ const guidance = [];
510
+ for (const candidate of changes) {
511
+ if (!isRecord(candidate) || candidate.status !== "selected") {
512
+ continue;
513
+ }
514
+ const candidateId = stringValue(candidate.id) ?? "<unknown>";
515
+ if (!sourceEditLikely(stringList(candidate.owned_paths))) {
516
+ continue;
517
+ }
518
+ guidance.push(`coder gate guidance ${label} ${candidateId}: source-edit candidate should bind coder gate status in LOCAL_COMMIT_EVIDENCE.yaml; guidance only, not a handoff blocker`);
519
+ }
520
+ return guidance;
521
+ }
522
+ function sourceEditLikely(ownedPaths) {
523
+ return ownedPaths.some((path) => {
524
+ const normalized = path.replace(/^\.?\//, "");
525
+ if (normalized.length === 0 || normalized.startsWith("changes/")) {
526
+ return false;
527
+ }
528
+ return normalized.startsWith("packages/")
529
+ || normalized.startsWith("skills/")
530
+ || normalized.startsWith("references/")
531
+ || normalized.startsWith("schemas/")
532
+ || normalized.startsWith(".agents/")
533
+ || normalized.startsWith(".openworkflow/audit/");
534
+ });
535
+ }
536
+ async function strictQueueCommitEvidenceErrors(root, queuePath, queue) {
537
+ const label = relative(root, queuePath);
538
+ const changes = Array.isArray(queue.changes) ? queue.changes : [];
539
+ const errors = [];
540
+ for (const candidate of changes) {
541
+ if (!isRecord(candidate) || candidate.status !== "done") {
542
+ continue;
543
+ }
544
+ const selection = recordValue(candidate.selection);
545
+ if (!stringValue(selection.selected_change_id)) {
546
+ continue;
547
+ }
548
+ const candidateId = stringValue(candidate.id) ?? "<unknown>";
549
+ const completion = recordValue(candidate.completion);
550
+ if (completion.implementation_changed_files === false) {
551
+ if (!stringValue(completion.commit_not_required_reason)) {
552
+ errors.push(`selected-change commit evidence ${label} ${candidateId}: planning-only completion must include commit_not_required_reason`);
553
+ }
554
+ continue;
555
+ }
556
+ if (completion.implementation_changed_files !== true) {
557
+ errors.push(`selected-change commit evidence ${label} ${candidateId}: strict completion must set implementation_changed_files true or false`);
558
+ continue;
559
+ }
560
+ const evidencePath = localCommitEvidencePath(completion);
561
+ if (!evidencePath) {
562
+ errors.push(`selected-change commit evidence ${label} ${candidateId}: implementation completion must include LOCAL_COMMIT_EVIDENCE.yaml`);
563
+ continue;
564
+ }
565
+ if (evidencePath.startsWith("/") || evidencePath.includes("://") || evidencePath.startsWith("..")) {
566
+ errors.push(`selected-change commit evidence ${label} ${candidateId}: LOCAL_COMMIT_EVIDENCE.yaml must be repo-relative`);
567
+ continue;
568
+ }
569
+ const absoluteEvidencePath = join(root, evidencePath);
570
+ if (!(await statOptional(absoluteEvidencePath))) {
571
+ errors.push(`selected-change commit evidence ${label} ${candidateId}: missing ${evidencePath}`);
572
+ }
573
+ }
574
+ return errors;
575
+ }
576
+ function localCommitEvidencePath(completion) {
577
+ const direct = stringValue(completion.local_commit_evidence_path) ?? stringValue(completion.local_commit_evidence);
578
+ if (direct?.endsWith("LOCAL_COMMIT_EVIDENCE.yaml")) {
579
+ return direct;
580
+ }
581
+ const evidence = Array.isArray(completion.evidence) ? completion.evidence : [];
582
+ for (const item of evidence) {
583
+ if (typeof item === "string" && item.endsWith("LOCAL_COMMIT_EVIDENCE.yaml")) {
584
+ return item;
585
+ }
586
+ }
587
+ return null;
588
+ }
589
+ function summaryPathForArtifact(artifactPath, contract) {
590
+ const policyPath = contract.summaryPolicy?.path;
591
+ if (policyPath) {
592
+ const artifactId = artifactIdForPath(artifactPath, contract.sourceOfTruthPath);
593
+ if (artifactId) {
594
+ return policyPath.replace("<id>", artifactId);
595
+ }
596
+ if (!policyPath.includes("<id>")) {
597
+ return policyPath;
598
+ }
599
+ }
600
+ return join(dirname(artifactPath), "SUMMARY.yaml");
601
+ }
602
+ function artifactIdForPath(artifactPath, sourceOfTruthPath) {
603
+ const marker = "<id>";
604
+ if (!sourceOfTruthPath.includes(marker)) {
605
+ return null;
606
+ }
607
+ const [prefix, suffix = ""] = sourceOfTruthPath.split(marker);
608
+ if (!prefix || !artifactPath.startsWith(prefix) || !artifactPath.endsWith(suffix)) {
609
+ return null;
610
+ }
611
+ const id = artifactPath.slice(prefix.length, artifactPath.length - suffix.length);
612
+ return id.length > 0 && !id.includes("/") ? id : null;
613
+ }
614
+ function currentSliceFields(path) {
615
+ return path.split("+").map((part) => part.trim()).filter(Boolean);
616
+ }
617
+ async function readYamlRecord(path) {
618
+ try {
619
+ const value = parseYaml(await readTextFile(path));
620
+ return isRecord(value) ? value : null;
621
+ }
622
+ catch {
623
+ return null;
624
+ }
625
+ }
626
+ async function statOptional(path) {
627
+ try {
628
+ return await stat(path);
629
+ }
630
+ catch (error) {
631
+ if (isNotFound(error)) {
632
+ return null;
633
+ }
634
+ throw error;
635
+ }
636
+ }
637
+ function aggregateStatus(statuses) {
638
+ if (statuses.includes("missing")) {
639
+ return "missing";
640
+ }
641
+ if (statuses.includes("stale_unknown")) {
642
+ return "stale_unknown";
643
+ }
644
+ if (statuses.includes("present")) {
645
+ return "present";
646
+ }
647
+ if (statuses.includes("current")) {
648
+ return "current";
649
+ }
650
+ return "not_instantiated";
651
+ }
652
+ function countStatuses(entries) {
653
+ const counts = emptyCounts();
654
+ for (const entry of entries) {
655
+ counts[entry.status] += 1;
656
+ }
657
+ return counts;
658
+ }
659
+ function emptyCounts() {
660
+ return {
661
+ not_applicable: 0,
662
+ not_instantiated: 0,
663
+ missing: 0,
664
+ present: 0,
665
+ stale_unknown: 0,
666
+ current: 0,
667
+ };
668
+ }
669
+ function nextActionsFor(status, contract) {
670
+ if (status === "missing" || status === "stale_unknown") {
671
+ return [`refresh summary for ${contract.artifactType} before relying on low-context reads`];
672
+ }
673
+ return [];
674
+ }
675
+ function hasNonEmptyValue(value) {
676
+ if (value === null || value === undefined) {
677
+ return false;
678
+ }
679
+ if (typeof value === "string") {
680
+ return value.trim().length > 0;
681
+ }
682
+ if (Array.isArray(value)) {
683
+ return value.length > 0;
684
+ }
685
+ if (isRecord(value)) {
686
+ return Object.values(value).some((item) => hasNonEmptyValue(item));
687
+ }
688
+ return true;
689
+ }
690
+ function valueAtPath(source, path) {
691
+ return path.split(".").reduce((current, part) => {
692
+ if (!isRecord(current)) {
693
+ return undefined;
694
+ }
695
+ return current[part];
696
+ }, source);
697
+ }
698
+ function isRecord(value) {
699
+ return typeof value === "object" && value !== null && !Array.isArray(value);
700
+ }
701
+ function recordValue(value) {
702
+ return isRecord(value) ? value : {};
703
+ }
704
+ function unique(values) {
705
+ return [...new Set(values.filter((value) => value.trim().length > 0))];
706
+ }
707
+ function stringValue(value) {
708
+ return typeof value === "string" ? value : null;
709
+ }
710
+ function stringList(value) {
711
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
712
+ }
713
+ //# sourceMappingURL=summaryHealth.js.map