@work-graph/cli 0.2.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 (194) hide show
  1. package/README.md +31 -0
  2. package/bin/work-graph.mjs +238 -0
  3. package/package.json +38 -0
  4. package/vendor/packages/design-tokens/generated/gripe-dark-default.css +67 -0
  5. package/vendor/packages/design-tokens/generated/marketplace-default.css +67 -0
  6. package/vendor/packages/design-tokens/generated/workgraph-dark.css +67 -0
  7. package/vendor/packages/workgraph-mcp/README.md +28 -0
  8. package/vendor/packages/workgraph-mcp/bin/workgraph-mcp.mjs +21 -0
  9. package/vendor/packages/workgraph-mcp/package.json +37 -0
  10. package/vendor/packages/workgraph-mcp/src/handlers.mjs +761 -0
  11. package/vendor/packages/workgraph-mcp/src/index.mjs +638 -0
  12. package/vendor/packages/workgraph-mcp/src/prompts.mjs +162 -0
  13. package/vendor/public/assets/workgraph-logo.svg +11 -0
  14. package/vendor/public/fonts/GraphikLCG/GraphikLCG-Medium.woff2 +0 -0
  15. package/vendor/public/fonts/GraphikLCG/GraphikLCG-Regular.woff2 +0 -0
  16. package/vendor/public/fonts/GraphikLCG/GraphikLCG-Semibold.woff2 +0 -0
  17. package/vendor/public/fonts/GraphikLCG/stylesheet.css +25 -0
  18. package/vendor/public/graph-canvas-lit-flow.css +154 -0
  19. package/vendor/public/graph-canvas-lit-flow.css.map +7 -0
  20. package/vendor/public/graph-canvas-lit-flow.js +8530 -0
  21. package/vendor/public/graph-canvas-lit-flow.js.map +7 -0
  22. package/vendor/src/agentBehaviorRulesAudit.mjs +168 -0
  23. package/vendor/src/agentBehaviorRulesBundle.mjs +144 -0
  24. package/vendor/src/agentRunApi.mjs +136 -0
  25. package/vendor/src/agentToolLoopGuard.mjs +88 -0
  26. package/vendor/src/agentWorkerClaudeProvider.mjs +288 -0
  27. package/vendor/src/agentWorkerCursorSdkProvider.mjs +156 -0
  28. package/vendor/src/agentWorkerLiveLoop.mjs +455 -0
  29. package/vendor/src/agentWorkerLocalCliProvider.mjs +217 -0
  30. package/vendor/src/agentWorkerLocalRunner.mjs +246 -0
  31. package/vendor/src/agentWorkerOpenAiProvider.mjs +459 -0
  32. package/vendor/src/analyticsPanelProjection.mjs +212 -0
  33. package/vendor/src/analyticsRecordStore.mjs +165 -0
  34. package/vendor/src/analyticsRecordWorkItems.mjs +104 -0
  35. package/vendor/src/architectureL1Canon.mjs +419 -0
  36. package/vendor/src/architectureLayout.mjs +229 -0
  37. package/vendor/src/architectureSnapshot.mjs +490 -0
  38. package/vendor/src/architectureViewsProjection.mjs +116 -0
  39. package/vendor/src/atomInspector.mjs +253 -0
  40. package/vendor/src/atomInspectorApi.mjs +130 -0
  41. package/vendor/src/auditGapMatrixRefresh.mjs +121 -0
  42. package/vendor/src/backlogSchemaLint.mjs +176 -0
  43. package/vendor/src/blockedOnebaseGoPreflightEval.mjs +100 -0
  44. package/vendor/src/bracketIrTraceSignal.mjs +93 -0
  45. package/vendor/src/bvcAtomParser.mjs +210 -0
  46. package/vendor/src/bvcDialectRegistry.mjs +86 -0
  47. package/vendor/src/bvcFileFormat.mjs +218 -0
  48. package/vendor/src/bvcFormatCli.mjs +55 -0
  49. package/vendor/src/bvcLintCli.mjs +48 -0
  50. package/vendor/src/bvcNewWritePolicy.mjs +70 -0
  51. package/vendor/src/charterPreflightPromoteGate.mjs +194 -0
  52. package/vendor/src/claimNoEligibleEval.mjs +205 -0
  53. package/vendor/src/closingAnalysisSuggest.mjs +59 -0
  54. package/vendor/src/codeGapAnalyzer.mjs +308 -0
  55. package/vendor/src/codeGapBacklogFeeder.mjs +82 -0
  56. package/vendor/src/codeGapDraftIntakeApi.mjs +307 -0
  57. package/vendor/src/codeGapOperatorProjection.mjs +60 -0
  58. package/vendor/src/codeSyntaxHighlight.mjs +123 -0
  59. package/vendor/src/codegenEvidence.mjs +187 -0
  60. package/vendor/src/compilerRoundTripCli.mjs +164 -0
  61. package/vendor/src/dagreGraphLayout.mjs +78 -0
  62. package/vendor/src/draftIntakePromotionRules.mjs +205 -0
  63. package/vendor/src/epicWorkScope.mjs +85 -0
  64. package/vendor/src/evalLiveLlmEnv.mjs +63 -0
  65. package/vendor/src/evidenceReadModel.mjs +167 -0
  66. package/vendor/src/gfsOverlayProjectPassport.mjs +235 -0
  67. package/vendor/src/globalStepPathToBvcReferences.mjs +196 -0
  68. package/vendor/src/goldenPath.mjs +69 -0
  69. package/vendor/src/graphCanvasLayout.mjs +464 -0
  70. package/vendor/src/graphCanvasLitFlow/client/graphCanvasMinimap.ts +261 -0
  71. package/vendor/src/graphCanvasLitFlow/client/graphCanvasSvgEdges.ts +259 -0
  72. package/vendor/src/graphCanvasLitFlow/client/graphCanvasTheme.css +152 -0
  73. package/vendor/src/graphCanvasLitFlow/client/graphCardNode.ts +328 -0
  74. package/vendor/src/graphCanvasLitFlow/client/mountGraphCanvasLitFlow.ts +322 -0
  75. package/vendor/src/graphCanvasLitFlow/graphCanvasEdgeLabels.mjs +58 -0
  76. package/vendor/src/graphCanvasLitFlow/graphCanvasEdgeRouter.mjs +142 -0
  77. package/vendor/src/graphCanvasLitFlow/graphCanvasLayoutProfile.mjs +32 -0
  78. package/vendor/src/graphCanvasLitFlow/graphCanvasNodeMetrics.mjs +45 -0
  79. package/vendor/src/graphCanvasLitFlow/graphCanvasProjection.mjs +115 -0
  80. package/vendor/src/graphCanvasLitFlow/graphCanvasProjectionToFlow.mjs +133 -0
  81. package/vendor/src/graphCanvasLitFlow/graphCanvasTraversal.mjs +77 -0
  82. package/vendor/src/graphCanvasLitFlow/layoutIntentRoadmapWorkStack.mjs +73 -0
  83. package/vendor/src/graphCanvasLitFlow/resolveGraphCanvasOverlaps.mjs +77 -0
  84. package/vendor/src/graphRagContextSlice.mjs +461 -0
  85. package/vendor/src/gvmVerifyWorkerGate.mjs +95 -0
  86. package/vendor/src/homeSnapshotApi.mjs +131 -0
  87. package/vendor/src/homeSnapshotProjection.mjs +275 -0
  88. package/vendor/src/inboxEventStream.mjs +140 -0
  89. package/vendor/src/intentComposerApi.mjs +245 -0
  90. package/vendor/src/intentGraphGbcSliceBoundary.mjs +258 -0
  91. package/vendor/src/intentGraphProjection.mjs +208 -0
  92. package/vendor/src/intentHierarchy.mjs +241 -0
  93. package/vendor/src/intentNodeLint.mjs +107 -0
  94. package/vendor/src/intentNodeRuntime.mjs +185 -0
  95. package/vendor/src/intentRoadmapCanvas.mjs +393 -0
  96. package/vendor/src/intentRoadmapEpicProjection.mjs +122 -0
  97. package/vendor/src/intentRoadmapMermaid.mjs +165 -0
  98. package/vendor/src/intentRoadmapProjection.mjs +85 -0
  99. package/vendor/src/intentTreeLint.mjs +114 -0
  100. package/vendor/src/intentTreeMigration.mjs +150 -0
  101. package/vendor/src/intentTreeWorkItems.mjs +227 -0
  102. package/vendor/src/kanbanBoardProjection.mjs +58 -0
  103. package/vendor/src/languageAdapterRegistry.mjs +180 -0
  104. package/vendor/src/languageAdapters/goAdapter.mjs +62 -0
  105. package/vendor/src/languageAdapters/jsTsAdapter.mjs +60 -0
  106. package/vendor/src/languageAdapters/jsonYamlAdapter.mjs +103 -0
  107. package/vendor/src/languageAdapters/onebaseOsAdapter.mjs +55 -0
  108. package/vendor/src/languageAdapters/plaintextAdapter.mjs +36 -0
  109. package/vendor/src/languageAdapters/shared.mjs +68 -0
  110. package/vendor/src/languageAdapters/stepAdapter.mjs +81 -0
  111. package/vendor/src/lintPlanWorkAlignment.mjs +136 -0
  112. package/vendor/src/loopHintRepeatToolEval.mjs +153 -0
  113. package/vendor/src/lowcodeScaffoldCli.mjs +386 -0
  114. package/vendor/src/markdownDocumentRender.mjs +208 -0
  115. package/vendor/src/memoryPanelProjection.mjs +116 -0
  116. package/vendor/src/memoryRecordWriter.mjs +243 -0
  117. package/vendor/src/memoryWorkerSlice.mjs +238 -0
  118. package/vendor/src/migrateStepToBvc.mjs +133 -0
  119. package/vendor/src/missionControlServerHandlers.mjs +195 -0
  120. package/vendor/src/missionControlUiClient.mjs +278 -0
  121. package/vendor/src/onebaseCliCapabilityProbe.mjs +107 -0
  122. package/vendor/src/onebaseCliRunner.mjs +145 -0
  123. package/vendor/src/onebaseGrossProfitStaticVerify.mjs +98 -0
  124. package/vendor/src/onebaseParityEvidenceSync.mjs +88 -0
  125. package/vendor/src/onebasePvrgGraphNodes.mjs +257 -0
  126. package/vendor/src/onebaseRestEvidenceAdapter.mjs +216 -0
  127. package/vendor/src/onebaseVectorDslCodegenReadiness.mjs +137 -0
  128. package/vendor/src/onebaseWorkItemTemplate.mjs +154 -0
  129. package/vendor/src/onebaseWorkerTools.mjs +586 -0
  130. package/vendor/src/operatorShellProjection.mjs +102 -0
  131. package/vendor/src/pipelineProseRender.mjs +180 -0
  132. package/vendor/src/pipelineStageLint.mjs +118 -0
  133. package/vendor/src/promptRulesEditorApi.mjs +174 -0
  134. package/vendor/src/promptRulesProjection.mjs +134 -0
  135. package/vendor/src/pvrg/bladeAdapter.mjs +40 -0
  136. package/vendor/src/pvrgTaskScope.mjs +152 -0
  137. package/vendor/src/releaseGateMatrix.mjs +188 -0
  138. package/vendor/src/schematicView.mjs +305 -0
  139. package/vendor/src/seedAnalyticsRecord.mjs +217 -0
  140. package/vendor/src/semanticSearchBm25.mjs +103 -0
  141. package/vendor/src/semanticSearchExcerpts.mjs +68 -0
  142. package/vendor/src/semanticSearchTfidfVector.mjs +86 -0
  143. package/vendor/src/semanticSearchWorkflow.mjs +366 -0
  144. package/vendor/src/stepAtomFormatter.mjs +413 -0
  145. package/vendor/src/stepGraphSlice.mjs +318 -0
  146. package/vendor/src/ui/atoms/badge.mjs +40 -0
  147. package/vendor/src/ui/atoms/badgeClient.mjs +32 -0
  148. package/vendor/src/ui/atoms/button.mjs +114 -0
  149. package/vendor/src/ui/atoms/buttonClient.mjs +49 -0
  150. package/vendor/src/ui/atoms/icon.mjs +23 -0
  151. package/vendor/src/ui/atoms/input.mjs +38 -0
  152. package/vendor/src/ui/atoms/modal.mjs +44 -0
  153. package/vendor/src/ui/atoms/select.mjs +98 -0
  154. package/vendor/src/ui/backlogShellButtons.mjs +238 -0
  155. package/vendor/src/ui/htmlEscape.mjs +11 -0
  156. package/vendor/src/ui/molecules/rating.mjs +48 -0
  157. package/vendor/src/ui/molecules/tabs.mjs +70 -0
  158. package/vendor/src/ui/organisms/modal.mjs +1 -0
  159. package/vendor/src/ui/pages/uiKitPage.mjs +147 -0
  160. package/vendor/src/ui/workItemStatusTone.mjs +36 -0
  161. package/vendor/src/unifiedLinkageProjection.mjs +264 -0
  162. package/vendor/src/verificationLoop.mjs +206 -0
  163. package/vendor/src/workGraphBacklogPersist.mjs +234 -0
  164. package/vendor/src/workGraphBacklogUiServer.mjs +9192 -0
  165. package/vendor/src/workGraphBoundedTargetFileRead.mjs +178 -0
  166. package/vendor/src/workGraphCycleSlice.mjs +184 -0
  167. package/vendor/src/workGraphDaemonTick.mjs +307 -0
  168. package/vendor/src/workGraphDaemonWatch.mjs +157 -0
  169. package/vendor/src/workGraphEngineRoot.mjs +136 -0
  170. package/vendor/src/workGraphInstallLayout.mjs +65 -0
  171. package/vendor/src/workGraphLlmUsefulnessEval.mjs +611 -0
  172. package/vendor/src/workGraphPhasePromoteReadyQueue.mjs +159 -0
  173. package/vendor/src/workGraphProjectHost.mjs +149 -0
  174. package/vendor/src/workGraphProjectInit.mjs +392 -0
  175. package/vendor/src/workGraphPromoteReadyApi.mjs +115 -0
  176. package/vendor/src/workGraphRecoveryPolicy.mjs +124 -0
  177. package/vendor/src/workGraphRunnerQueueProjection.mjs +187 -0
  178. package/vendor/src/workGraphRuntime.mjs +1008 -0
  179. package/vendor/src/workGraphToolSurfaceAudit.mjs +372 -0
  180. package/vendor/src/workGraphToolTransportRuntime.mjs +195 -0
  181. package/vendor/src/workGraphWorkerProvider.mjs +600 -0
  182. package/vendor/src/workItemBvcQuality.mjs +262 -0
  183. package/vendor/src/workItemCreateAnalysis.mjs +157 -0
  184. package/vendor/src/workItemDecisionPipeline.mjs +278 -0
  185. package/vendor/src/workItemEpicCascade.mjs +176 -0
  186. package/vendor/src/workItemExecutionGate.mjs +78 -0
  187. package/vendor/src/workItemHierarchy.mjs +226 -0
  188. package/vendor/src/workItemProseLint.mjs +133 -0
  189. package/vendor/src/workItemTextRusify.mjs +794 -0
  190. package/vendor/src/workItemTraceEnvelope.mjs +158 -0
  191. package/vendor/src/workItemUiReferences.mjs +272 -0
  192. package/vendor/src/workflowEpicGrouping.mjs +67 -0
  193. package/vendor/src/workflowTreeProjection.mjs +53 -0
  194. package/vendor/src/workspaceRegistry.mjs +150 -0
@@ -0,0 +1,235 @@
1
+ import { access, constants, readFile } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+
4
+ const compareText = (left, right) => String(left).localeCompare(String(right), 'en', { sensitivity: 'variant' });
5
+
6
+ export const GFS_OVERLAY_PASSPORT_SCHEMA = 'gfs.overlay.project.passport.v1';
7
+
8
+ export const GFS_OVERLAY_READ_ORDER = ['disk-canonical', 'gfs-overlay-suffix', 'json-snapshot-projection'];
9
+
10
+ export const GFS_OVERLAY_OPTIONAL_PATHS = [
11
+ {
12
+ id: 'passport-slice-b64',
13
+ logicalPath: '.iohasc/cache/passport-slice.b64',
14
+ format: 'base64-flatbuffers',
15
+ encoding: 'transport',
16
+ status: 'deferred',
17
+ },
18
+ {
19
+ id: 'passport-slice-gbc',
20
+ logicalPath: '.iohasc/cache/passport-slice.gbc',
21
+ format: 'flatbuffers',
22
+ encoding: 'binary',
23
+ status: 'deferred',
24
+ },
25
+ {
26
+ id: 'module-registry-json',
27
+ logicalPath: '.iohasc/cache/iohasc-gbc-module-registry.json',
28
+ format: 'json',
29
+ encoding: 'utf-8',
30
+ status: 'optional-overlay',
31
+ },
32
+ {
33
+ id: 'trace-link-slice-b64',
34
+ logicalPath: '.iohasc/cache/trace-link-slice.b64',
35
+ format: 'base64-flatbuffers',
36
+ encoding: 'transport',
37
+ status: 'deferred',
38
+ },
39
+ {
40
+ id: 'cm-trace-link-slices-json',
41
+ logicalPath: '.iohasc/cache/cm-trace-link-slices.v1.json',
42
+ format: 'json',
43
+ encoding: 'utf-8',
44
+ status: 'optional-overlay',
45
+ },
46
+ {
47
+ id: 'pvrg-node-descriptions-json',
48
+ logicalPath: '.iohasc/cache/pvrg-node-descriptions.v1.json',
49
+ format: 'json',
50
+ encoding: 'utf-8',
51
+ status: 'optional-overlay',
52
+ },
53
+ ];
54
+
55
+ export const GFS_MANDATORY_FALLBACK_PROJECTIONS = [
56
+ {
57
+ id: 'workgraph-snapshot',
58
+ schema: 'workgraph.snapshot.v1',
59
+ source: 'parseWorkItems(work/backlog.bvc)',
60
+ required: true,
61
+ },
62
+ {
63
+ id: 'intent-tree-parity',
64
+ schema: 'intent.hierarchy.snapshot.v1',
65
+ source: 'intent tree migration equivalence',
66
+ required: true,
67
+ },
68
+ {
69
+ id: 'operator-shell',
70
+ schema: 'operator-shell.snapshot.v2',
71
+ source: 'buildOperatorShellProjection',
72
+ required: true,
73
+ },
74
+ {
75
+ id: 'architecture-snapshot',
76
+ schema: 'architecture.snapshot.v1',
77
+ source: 'buildArchitectureSnapshot (on demand)',
78
+ required: false,
79
+ },
80
+ ];
81
+
82
+ export function buildGfsOverlayReadContract() {
83
+ const optionalPaths = [...GFS_OVERLAY_OPTIONAL_PATHS].sort((left, right) => compareText(left.id, right.id));
84
+
85
+ return {
86
+ schema: 'gfs.overlay.read-contract.v1',
87
+ readOrder: [...GFS_OVERLAY_READ_ORDER],
88
+ diskFirst: true,
89
+ overlayNeverCanonicalWithoutWorkItem: true,
90
+ utf8JsonOverlayPaths: optionalPaths.filter((entry) => entry.encoding === 'utf-8'),
91
+ deferredBinaryPaths: optionalPaths.filter((entry) => entry.status === 'deferred'),
92
+ optionalOverlayPaths: optionalPaths.filter((entry) => entry.status === 'optional-overlay'),
93
+ donorReference: '../project/src/iohascGbc/gfsFileContentOverlay.ts',
94
+ };
95
+ }
96
+
97
+ export function buildGfsOverlayProjectPassport() {
98
+ const mandatoryFallback = [...GFS_MANDATORY_FALLBACK_PROJECTIONS].sort((left, right) => compareText(left.id, right.id));
99
+ const readContract = buildGfsOverlayReadContract();
100
+
101
+ return {
102
+ schema: GFS_OVERLAY_PASSPORT_SCHEMA,
103
+ status: 'optional-deferred',
104
+ readContract,
105
+ mandatoryFallback: {
106
+ required: true,
107
+ projections: mandatoryFallback,
108
+ requiredProjectionIds: mandatoryFallback.filter((entry) => entry.required).map((entry) => entry.id),
109
+ },
110
+ agentContextPolicy: {
111
+ withoutGfs: 'JSON snapshots + .bvc canon only',
112
+ withGfs: 'merge overlay bytes after disk-first check; never wipe disk canon',
113
+ },
114
+ relatedProtocols: ['gbc-gvm-zig-deferral-boundary', 'gfs-overlay-project-passport-v1'],
115
+ };
116
+ }
117
+
118
+ export function evaluateGfsOverlayFallbackPolicy(passport = buildGfsOverlayProjectPassport()) {
119
+ const requiredProjections = passport.mandatoryFallback.projections.filter((entry) => entry.required);
120
+
121
+ return {
122
+ schema: 'gfs.overlay.fallback-policy.v1',
123
+ ok: passport.mandatoryFallback.required === true
124
+ && requiredProjections.length >= 2
125
+ && passport.readContract.diskFirst === true
126
+ && passport.readContract.overlayNeverCanonicalWithoutWorkItem === true,
127
+ requiredProjectionCount: requiredProjections.length,
128
+ };
129
+ }
130
+
131
+ export const GFS_PROJECT_PASSPORT_DISK_PATH = '.iohasc/project-passport.v1.json';
132
+ export const GFS_OVERLAY_PILOT_READ_SCHEMA = 'gfs.overlay.pilot-read.v1';
133
+
134
+ export const GFS_OVERLAY_PILOT_PREREQUISITES = [
135
+ 'Disk canonical: .iohasc/project-passport.v1.json under repo root (or fixture cwd)',
136
+ 'Optional GFS mount: set gfsOverlayRoot to overlay directory mirroring logical paths',
137
+ 'Without GFS: mandatory JSON fallback projections from buildGfsOverlayProjectPassport()',
138
+ 'Binary b64/gbc overlay paths remain deferred; pilot reads UTF-8 JSON only',
139
+ ];
140
+
141
+ async function readJsonFileIfPresent(absolutePath, source) {
142
+ try {
143
+ await access(absolutePath, constants.R_OK);
144
+ const text = await readFile(absolutePath, 'utf8');
145
+ return {
146
+ ok: true,
147
+ source,
148
+ absolutePath,
149
+ payload: JSON.parse(text),
150
+ };
151
+ } catch (error) {
152
+ return {
153
+ ok: false,
154
+ source,
155
+ absolutePath,
156
+ error: error instanceof Error ? error.message : String(error),
157
+ };
158
+ }
159
+ }
160
+
161
+ export async function readDiskCanonicalProjectPassport(options = {}) {
162
+ const cwd = options.cwd ?? process.cwd();
163
+ const logicalPath = options.logicalPath ?? GFS_PROJECT_PASSPORT_DISK_PATH;
164
+ const absolutePath = resolve(cwd, logicalPath);
165
+ const readResult = await readJsonFileIfPresent(absolutePath, 'disk-canonical');
166
+
167
+ return {
168
+ ...readResult,
169
+ logicalPath,
170
+ };
171
+ }
172
+
173
+ export async function readGfsOverlayPassportPilot(options = {}) {
174
+ const passport = buildGfsOverlayProjectPassport();
175
+ const cwd = options.cwd ?? process.cwd();
176
+ const diskRead = await readDiskCanonicalProjectPassport({ ...options, cwd });
177
+
178
+ if (diskRead.ok) {
179
+ return {
180
+ schema: GFS_OVERLAY_PILOT_READ_SCHEMA,
181
+ ok: true,
182
+ readPath: 'disk-canonical',
183
+ gfsMounted: false,
184
+ passportSchema: diskRead.payload?.schemaVersion ?? diskRead.payload?.schema ?? null,
185
+ absolutePath: diskRead.absolutePath,
186
+ prerequisites: [...GFS_OVERLAY_PILOT_PREREQUISITES],
187
+ };
188
+ }
189
+
190
+ if (options.gfsOverlayRoot) {
191
+ const overlayPath = resolve(cwd, options.gfsOverlayRoot, GFS_PROJECT_PASSPORT_DISK_PATH);
192
+ const overlayRead = await readJsonFileIfPresent(overlayPath, 'gfs-overlay-suffix');
193
+ if (overlayRead.ok) {
194
+ return {
195
+ schema: GFS_OVERLAY_PILOT_READ_SCHEMA,
196
+ ok: true,
197
+ readPath: 'gfs-overlay-suffix',
198
+ gfsMounted: true,
199
+ passportSchema: overlayRead.payload?.schemaVersion ?? overlayRead.payload?.schema ?? null,
200
+ absolutePath: overlayRead.absolutePath,
201
+ prerequisites: [...GFS_OVERLAY_PILOT_PREREQUISITES],
202
+ };
203
+ }
204
+ }
205
+
206
+ const fallbackRead = options.fallbackRoot
207
+ ? await readDiskCanonicalProjectPassport({ cwd: resolve(cwd, options.fallbackRoot) })
208
+ : diskRead;
209
+
210
+ if (fallbackRead.ok) {
211
+ return {
212
+ schema: GFS_OVERLAY_PILOT_READ_SCHEMA,
213
+ ok: true,
214
+ readPath: 'json-snapshot-projection',
215
+ gfsMounted: false,
216
+ fallback: true,
217
+ passportSchema: fallbackRead.payload?.schemaVersion ?? fallbackRead.payload?.schema ?? null,
218
+ absolutePath: fallbackRead.absolutePath,
219
+ mandatoryFallbackProjectionIds: passport.mandatoryFallback.requiredProjectionIds,
220
+ prerequisites: [...GFS_OVERLAY_PILOT_PREREQUISITES],
221
+ };
222
+ }
223
+
224
+ return {
225
+ schema: GFS_OVERLAY_PILOT_READ_SCHEMA,
226
+ ok: true,
227
+ readPath: 'json-snapshot-projection',
228
+ gfsMounted: false,
229
+ fallback: true,
230
+ passportSchema: null,
231
+ mandatoryFallbackProjectionIds: passport.mandatoryFallback.requiredProjectionIds,
232
+ prerequisites: [...GFS_OVERLAY_PILOT_PREREQUISITES],
233
+ note: 'No disk passport; contract-only fallback projections apply',
234
+ };
235
+ }
@@ -0,0 +1,196 @@
1
+ import { readdir, readFile, stat, writeFile } from 'node:fs/promises';
2
+ import { join, relative } from 'node:path';
3
+
4
+ /** Files that must keep literal `.step` for legacy dual-read API/tests. */
5
+ export const STEP_PATH_REPLACE_SKIP_FILES = new Set([
6
+ 'src/bvcFileFormat.mjs',
7
+ 'src/migrateStepToBvc.mjs',
8
+ 'tests/bvcDualExtension.test.mjs',
9
+ 'tests/migrateStepToBvc.test.mjs',
10
+ 'tests/bvcSpecPackage.test.mjs',
11
+ 'tests/bvcFormatCli.test.mjs',
12
+ 'tests/conformance/minimal.en.step',
13
+ 'tests/conformance/minimal.en.bvc',
14
+ 'src/globalStepPathToBvcReferences.mjs',
15
+ 'packages/bvc-spec/index.js',
16
+ 'dist/bvc-spec-github/index.js',
17
+ ]);
18
+
19
+ export const STEP_PATH_REPLACE_SKIP_DIRS = new Set([
20
+ '.git',
21
+ 'node_modules',
22
+ 'dist',
23
+ 'playwright-report',
24
+ 'test-results',
25
+ ]);
26
+
27
+ const TEXT_EXTENSIONS = new Set([
28
+ '.bvc',
29
+ '.step',
30
+ '.md',
31
+ '.mdc',
32
+ '.mjs',
33
+ '.js',
34
+ '.json',
35
+ '.jsonl',
36
+ '.ts',
37
+ '.tsx',
38
+ '.yaml',
39
+ '.yml',
40
+ '.txt',
41
+ ]);
42
+
43
+ /**
44
+ * Replace filesystem path suffix `.step` → `.bvc` in prose and labels.
45
+ * Preserves ../project/* paths (ioHasC sibling repo still on .step).
46
+ * @param {string} text
47
+ */
48
+ export function replaceStepPathReferencesInText(text) {
49
+ /** @type {string[]} */
50
+ const externalStepPaths = [];
51
+ let out = String(text).replace(/(\.\.\/project[^\s'"),#\]]*?)\.step\b/g, (match) => {
52
+ const token = `__EXTERNAL_STEP_PATH_${externalStepPaths.length}__`;
53
+ externalStepPaths.push(match);
54
+ return token;
55
+ });
56
+
57
+ /** Protect prose mentions of the legacy extension before path rewrites. */
58
+ const legacyExtTokens = [];
59
+ out = out.replace(/\blegacy \.step\b/gi, () => {
60
+ const token = `__LEGACY_EXT_${legacyExtTokens.length}__`;
61
+ legacyExtTokens.push('legacy .step');
62
+ return token;
63
+ });
64
+ out = out.replace(/`\.step`/g, () => {
65
+ const token = `__LEGACY_EXT_${legacyExtTokens.length}__`;
66
+ legacyExtTokens.push('`.step`');
67
+ return token;
68
+ });
69
+
70
+ out = out.replace(/\.work\.step\b/g, '.work.bvc');
71
+ out = out.replace(/\.intent\.step\b/g, '.intent.bvc');
72
+ out = out.replace(/\.compiler\.step\b/g, '.compiler.bvc');
73
+ out = out.replace(/\.step\b/g, '.bvc');
74
+
75
+ for (let index = 0; index < legacyExtTokens.length; index += 1) {
76
+ const restored = legacyExtTokens[index];
77
+ out = out.replace(`__LEGACY_EXT_${index}__`, restored);
78
+ }
79
+
80
+ for (let index = 0; index < externalStepPaths.length; index += 1) {
81
+ out = out.replace(`__EXTERNAL_STEP_PATH_${index}__`, externalStepPaths[index]);
82
+ }
83
+
84
+ return out;
85
+ }
86
+
87
+ /**
88
+ * @param {string} cwd
89
+ * @param {{ apply?: boolean, roots?: string[] }} [options]
90
+ */
91
+ export async function collectTextFilesForStepPathReplace(cwd, options = {}) {
92
+ const roots = options.roots ?? ['.'];
93
+ /** @type {string[]} */
94
+ const files = [];
95
+
96
+ async function walk(relativeDir) {
97
+ const absoluteDir = join(cwd, relativeDir);
98
+ let entries;
99
+ try {
100
+ entries = await readdir(absoluteDir, { withFileTypes: true });
101
+ } catch {
102
+ return;
103
+ }
104
+
105
+ for (const entry of entries) {
106
+ const relativePath = join(relativeDir, entry.name).replace(/\\/g, '/');
107
+ const base = relativePath.replace(/^\.\//, '');
108
+
109
+ if (entry.isDirectory()) {
110
+ if (STEP_PATH_REPLACE_SKIP_DIRS.has(entry.name)) {
111
+ continue;
112
+ }
113
+ await walk(relativePath);
114
+ continue;
115
+ }
116
+
117
+ if (!entry.isFile()) {
118
+ continue;
119
+ }
120
+
121
+ if (STEP_PATH_REPLACE_SKIP_FILES.has(base)) {
122
+ continue;
123
+ }
124
+
125
+ const ext = entry.name.includes('.') ? entry.name.slice(entry.name.lastIndexOf('.')) : '';
126
+ if (!TEXT_EXTENSIONS.has(ext)) {
127
+ continue;
128
+ }
129
+
130
+ files.push(base);
131
+ }
132
+ }
133
+
134
+ for (const root of roots) {
135
+ const absoluteRoot = join(cwd, root);
136
+ try {
137
+ const rootStat = await stat(absoluteRoot);
138
+ if (!rootStat.isDirectory() && root !== '.') {
139
+ continue;
140
+ }
141
+ } catch {
142
+ continue;
143
+ }
144
+ await walk(root === '.' ? '.' : root);
145
+ }
146
+
147
+ files.sort((left, right) => left.localeCompare(right, 'en', { sensitivity: 'variant' }));
148
+ return files;
149
+ }
150
+
151
+ /**
152
+ * @param {string} cwd
153
+ * @param {{ apply?: boolean, roots?: string[] }} [options]
154
+ */
155
+ export async function runGlobalStepPathToBvcReferences(cwd, options = {}) {
156
+ const apply = options.apply === true;
157
+ const files = await collectTextFilesForStepPathReplace(cwd, options);
158
+ /** @type {Array<{ path: string, changed: boolean }>} */
159
+ const report = [];
160
+
161
+ for (const filePath of files) {
162
+ const absolutePath = join(cwd, filePath);
163
+ const before = await readFile(absolutePath, 'utf8');
164
+ const after = replaceStepPathReferencesInText(before);
165
+ const changed = before !== after;
166
+ report.push({ path: filePath, changed });
167
+ if (changed && apply) {
168
+ await writeFile(absolutePath, after, 'utf8');
169
+ }
170
+ }
171
+
172
+ return {
173
+ schema: 'global-step-path-to-bvc-references.v1',
174
+ apply,
175
+ scanned: files.length,
176
+ changed: report.filter((entry) => entry.changed).length,
177
+ files: report.filter((entry) => entry.changed),
178
+ };
179
+ }
180
+
181
+ /**
182
+ * Extended rename roots for residual `.bvc` artifacts.
183
+ */
184
+ export const FULL_BVC_RENAME_ROOTS = Object.freeze([
185
+ 'architecture',
186
+ 'charter',
187
+ 'protocols',
188
+ 'intent',
189
+ 'work',
190
+ 'rules',
191
+ 'ui',
192
+ 'domains',
193
+ 'plans',
194
+ 'skills',
195
+ 'tests',
196
+ ]);
@@ -0,0 +1,69 @@
1
+ import { claimNext, recordEvidence, transitionStatus } from './workGraphRuntime.mjs';
2
+
3
+ /** Agent loop phases aligned with protocols/agent-state-machine-v1.bvc */
4
+ export const AGENT_LOOP_PHASES = [
5
+ 'observe',
6
+ 'plan',
7
+ 'claim',
8
+ 'act',
9
+ 'verify',
10
+ 'record',
11
+ 'stop',
12
+ ];
13
+
14
+ /**
15
+ * Deterministic golden path: claim ready task -> act evidence -> verify -> done.
16
+ * No LLM, no filesystem — exercises Work Graph runtime policy only.
17
+ *
18
+ * @param {Array<{ id: string, status: string, evidence?: string[], targetFiles?: string[], labels?: object, dependsOn?: string[] }>} items
19
+ * @param {{ taskId?: string }} [options]
20
+ */
21
+ export function runDeterministicGoldenPath(items, options = {}) {
22
+ const steps = [];
23
+ let pool = items.map((item) => ({ ...item, evidence: [...(item.evidence || [])], labels: { ...item.labels } }));
24
+
25
+ steps.push({ phase: 'observe', detail: 'read snapshot', itemCount: pool.length });
26
+
27
+ const target = options.taskId
28
+ ? pool.find((item) => item.id === options.taskId)
29
+ : claimNext(pool);
30
+
31
+ if (!target) {
32
+ return { ok: false, steps, error: 'no_claimable_task', finalItems: pool };
33
+ }
34
+
35
+ steps.push({ phase: 'plan', detail: 'select task ' + target.id, taskId: target.id });
36
+
37
+ let current = transitionStatus(target, 'claimed');
38
+ pool = replaceItem(pool, target.id, current);
39
+ steps.push({ phase: 'claim', detail: 'transition to claimed', taskId: current.id, status: current.status });
40
+
41
+ current = recordEvidence(current, 'change: updated ' + (current.targetFiles?.[0] || 'artifact') + ' for golden path');
42
+ pool = replaceItem(pool, current.id, current);
43
+ steps.push({ phase: 'act', detail: 'record change evidence', evidenceCount: current.evidence.length });
44
+
45
+ current = transitionStatus(current, 'verify', {
46
+ evidence: 'verify: npm run test:deterministic scheduled for golden path task',
47
+ });
48
+ pool = replaceItem(pool, current.id, current);
49
+ steps.push({ phase: 'verify', detail: 'transition to verify', status: current.status });
50
+
51
+ current = transitionStatus(current, 'done', {
52
+ evidence: 'test: npm run test:deterministic exit_code=0 golden-path',
53
+ });
54
+ pool = replaceItem(pool, current.id, current);
55
+ steps.push({ phase: 'record', detail: 'transition to done with verification evidence', status: current.status });
56
+ steps.push({ phase: 'stop', detail: 'golden path complete', taskId: current.id });
57
+
58
+ return {
59
+ ok: current.status === 'done' && current.evidence.length >= 3,
60
+ steps,
61
+ finalItems: pool,
62
+ taskId: current.id,
63
+ };
64
+ }
65
+
66
+ /** @param {typeof items} pool @param {string} id @param {object} nextItem */
67
+ function replaceItem(pool, id, nextItem) {
68
+ return pool.map((item) => (item.id === id ? nextItem : item));
69
+ }