workspai 0.46.0 → 0.48.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 (143) hide show
  1. package/README.md +225 -81
  2. package/contracts/agent-customization-pack.v1.json +11 -1
  3. package/contracts/bootstrap-compliance.v1.json +14 -0
  4. package/contracts/cli-runtime-command-inventory.v1.snapshot.json +4 -0
  5. package/contracts/extension-cli-compatibility.v1.json +13 -2
  6. package/contracts/mirror-ops.v1.json +16 -0
  7. package/contracts/published-contract-catalog.v1.json +59 -1
  8. package/contracts/runtime-command-surface.v1.json +294 -2
  9. package/contracts/transparency-evidence.v1.json +13 -0
  10. package/contracts/workspace-contract.v1.json +78 -0
  11. package/contracts/workspace-intelligence/model-usage-event.v1.json +82 -0
  12. package/contracts/workspace-intelligence/workspace-context.v1.json +20 -0
  13. package/contracts/workspace-intelligence/workspace-graph-token-efficiency.v1.json +72 -0
  14. package/contracts/workspace-intelligence/workspace-intelligence-evaluation-comparison.v1.json +53 -0
  15. package/contracts/workspace-intelligence/workspace-intelligence-evaluation.v1.json +120 -0
  16. package/contracts/workspace-intelligence/workspace-intelligence-run.v1.json +6 -1
  17. package/contracts/workspace-intelligence/workspace-knowledge-graph-change-overlay.v1.json +200 -0
  18. package/contracts/workspace-intelligence/workspace-knowledge-graph.v1.json +260 -0
  19. package/contracts/workspace-intelligence/workspace-knowledge-search.v1.json +60 -0
  20. package/contracts/workspace-intelligence-architecture.v1.json +37 -5
  21. package/contracts/workspace-intelligence-chain.v1.json +58 -6
  22. package/contracts/workspace-share-bundle.v1.json +16 -0
  23. package/dist/analyze-EEEU3MIF.js +1 -0
  24. package/dist/artifact-remediation-plan-SPOUHMK5.js +3 -0
  25. package/dist/autopilot-release-XGVXPOZI.js +1 -0
  26. package/dist/chunk-32OJDBIG.js +2 -0
  27. package/dist/chunk-37CVKXBD.js +1 -0
  28. package/dist/chunk-3NU32T4A.js +2 -0
  29. package/dist/chunk-3VFA7D5T.js +1 -0
  30. package/dist/chunk-4HDYADHT.js +13 -0
  31. package/dist/chunk-54EP5CEV.js +8 -0
  32. package/dist/chunk-5S3DJQEP.js +8 -0
  33. package/dist/chunk-AFL3ACCR.js +2 -0
  34. package/dist/{chunk-VFDM65IE.js → chunk-BFLJ2R4D.js} +22 -22
  35. package/dist/chunk-BGPXQQNY.js +4 -0
  36. package/dist/chunk-BMWFQXGW.js +1 -0
  37. package/dist/{chunk-UQWOVV6V.js → chunk-CRHYBQI3.js} +1 -1
  38. package/dist/chunk-CV5HKU4P.js +1 -0
  39. package/dist/chunk-ESLPI3XZ.js +1 -0
  40. package/dist/chunk-FB7SCXAZ.js +1 -0
  41. package/dist/{chunk-WPEEC5BX.js → chunk-HDXNIN4N.js} +1 -1
  42. package/dist/chunk-HZDXO65G.js +36 -0
  43. package/dist/{chunk-J5PIZCAU.js → chunk-I46XEIPL.js} +1 -1
  44. package/dist/chunk-J5ENLXDF.js +1 -0
  45. package/dist/chunk-KB44JP4M.js +2 -0
  46. package/dist/chunk-LHOZXC2M.js +2 -0
  47. package/dist/chunk-NAJCUQ4X.js +2 -0
  48. package/dist/chunk-OA537ZQ5.js +1 -0
  49. package/dist/chunk-OW42TZFB.js +1 -0
  50. package/dist/chunk-P3D5YQB2.js +1 -0
  51. package/dist/chunk-PHXQR6PX.js +2 -0
  52. package/dist/{chunk-ZKAI3PJE.js → chunk-PRTR2DQ2.js} +1 -1
  53. package/dist/{chunk-QA5BGEQW.js → chunk-QNONOO4F.js} +1 -1
  54. package/dist/chunk-RHQW3DTP.js +1 -0
  55. package/dist/chunk-T4YR4RAI.js +2 -0
  56. package/dist/chunk-THIOE2PB.js +2 -0
  57. package/dist/{chunk-4LGXSBCN.js → chunk-VU7NZHPM.js} +1 -1
  58. package/dist/chunk-WDKNMTJQ.js +1 -0
  59. package/dist/{chunk-YUATNVOT.js → chunk-Y5UJLPS4.js} +16 -16
  60. package/dist/{chunk-6IIZJQLV.js → chunk-YJZOMRAS.js} +1 -1
  61. package/dist/{create-WCV3L6XH.js → create-DBQNAMKP.js} +1 -1
  62. package/dist/{doctor-5BWM2EMJ.js → doctor-4NNUDNGZ.js} +1 -1
  63. package/dist/{dotnet-webapi-clean-6TVFBTVI.js → dotnet-webapi-clean-A6MVDYXX.js} +4 -4
  64. package/dist/{gofiber-standard-2BL7GWZB.js → gofiber-standard-I5YPQG5V.js} +1 -1
  65. package/dist/{gogin-standard-XGP3KBXA.js → gogin-standard-VY2L4QT5.js} +1 -1
  66. package/dist/index.d.ts +56 -14
  67. package/dist/index.js +322 -320
  68. package/dist/pipeline-TQM43A3K.js +5 -0
  69. package/dist/{springboot-standard-JJNUID6M.js → springboot-standard-55XKCBIZ.js} +4 -4
  70. package/dist/{workspace-7OXW5YTJ.js → workspace-NCWRINEF.js} +1 -1
  71. package/dist/{workspace-agent-sync-O4IA6VOA.js → workspace-agent-sync-662QHXGF.js} +1 -1
  72. package/dist/{workspace-archive-H74NBBNW.js → workspace-archive-P76EDIUG.js} +1 -1
  73. package/dist/{workspace-context-R7IPUBPG.js → workspace-context-23YYCUCP.js} +1 -1
  74. package/dist/workspace-contract-TU2I7GC2.js +1 -0
  75. package/dist/workspace-dependency-graph-BP4EXYQ5.js +1 -0
  76. package/dist/workspace-explain-MWUEN643.js +1 -0
  77. package/dist/workspace-explain-contract-ZPI3JXJU.js +1 -0
  78. package/dist/{workspace-feedback-REOS36ZZ.js → workspace-feedback-SUVH2LUJ.js} +1 -1
  79. package/dist/{workspace-foundation-KXT4QI5O.js → workspace-foundation-WXJ6I7ES.js} +1 -1
  80. package/dist/workspace-graph-token-efficiency-CFGFCJ5V.js +1 -0
  81. package/dist/{workspace-history-OGOVSKZG.js → workspace-history-BANOJRQ2.js} +1 -1
  82. package/dist/workspace-intelligence-MFJE7W67.js +1 -0
  83. package/dist/workspace-intelligence-evaluation-IPH7M3WV.js +1 -0
  84. package/dist/workspace-intelligence-runner-THYLHHMF.js +1 -0
  85. package/dist/workspace-knowledge-graph-ARDC6HHG.js +1 -0
  86. package/dist/workspace-knowledge-graph-change-overlay-XG6FC4IX.js +1 -0
  87. package/dist/workspace-knowledge-graph-export-UYAYFTWX.js +10 -0
  88. package/dist/workspace-knowledge-graph-query-VOSPPH4W.js +1 -0
  89. package/dist/workspace-mcp-serve-EZR6O76D.js +3 -0
  90. package/dist/workspace-model-7OU2M3LE.js +1 -0
  91. package/dist/workspace-model-hash-MHXK5MEI.js +1 -0
  92. package/dist/{workspace-registry-summary-SZ46R5PD.js → workspace-registry-summary-ORDK7A36.js} +1 -1
  93. package/dist/workspace-run-RLIYSOTN.js +1 -0
  94. package/dist/{workspace-verify-MFQ7IXGD.js → workspace-verify-EBVL7FWT.js} +1 -1
  95. package/dist/workspace-watch-3BPGLFLB.js +1 -0
  96. package/docs/AI_DYNAMIC_INTEGRATION.md +73 -428
  97. package/docs/AI_EXAMPLES.md +37 -395
  98. package/docs/AI_FEATURES.md +76 -456
  99. package/docs/AI_QUICKSTART.md +49 -212
  100. package/docs/GLOSSARY.md +64 -0
  101. package/docs/OPEN_SOURCE_USER_SCENARIOS.md +68 -7
  102. package/docs/README.md +70 -41
  103. package/docs/README_CONTENT_CONTRACT.md +154 -0
  104. package/docs/commands-reference.md +64 -4
  105. package/docs/config-file-guide.md +6 -2
  106. package/docs/contracts/ARTIFACT_CATALOG.md +76 -37
  107. package/docs/contracts/README.md +47 -8
  108. package/docs/graph-benchmark-methodology.md +121 -0
  109. package/docs/workspace-intelligence-evaluation.md +147 -0
  110. package/docs/workspace-knowledge-graph.md +316 -0
  111. package/docs/workspace-operations.md +49 -0
  112. package/package.json +2 -1
  113. package/dist/analyze-BEBEZSZK.js +0 -1
  114. package/dist/artifact-remediation-plan-FFQSESAM.js +0 -3
  115. package/dist/autopilot-release-WUR4CQIT.js +0 -1
  116. package/dist/chunk-2G7FASAO.js +0 -2
  117. package/dist/chunk-4EPHWD27.js +0 -8
  118. package/dist/chunk-CVHMUSRX.js +0 -1
  119. package/dist/chunk-DIPD72H4.js +0 -2
  120. package/dist/chunk-EFYHGCGX.js +0 -2
  121. package/dist/chunk-FWRXA435.js +0 -2
  122. package/dist/chunk-HDURFXW5.js +0 -2
  123. package/dist/chunk-HMUKBW2S.js +0 -4
  124. package/dist/chunk-K4WNYXKK.js +0 -33
  125. package/dist/chunk-LG6RFLPZ.js +0 -1
  126. package/dist/chunk-N7DV5L7C.js +0 -1
  127. package/dist/chunk-PRBVYW3T.js +0 -1
  128. package/dist/chunk-QZLIURER.js +0 -13
  129. package/dist/chunk-RIEF2DDX.js +0 -8
  130. package/dist/chunk-SXMTSV5M.js +0 -1
  131. package/dist/chunk-SXPY523X.js +0 -1
  132. package/dist/chunk-V3LRQZ36.js +0 -1
  133. package/dist/chunk-WYFPXTTS.js +0 -2
  134. package/dist/pipeline-ORIWVVYM.js +0 -5
  135. package/dist/workspace-contract-HKCMOMFE.js +0 -1
  136. package/dist/workspace-explain-GOPQYTPQ.js +0 -1
  137. package/dist/workspace-explain-contract-SVFJAAEI.js +0 -1
  138. package/dist/workspace-intelligence-7IESQSXY.js +0 -1
  139. package/dist/workspace-intelligence-runner-6GJ5M4HB.js +0 -1
  140. package/dist/workspace-mcp-serve-FRVWBO36.js +0 -3
  141. package/dist/workspace-model-PPYX7B4S.js +0 -1
  142. package/dist/workspace-run-V3KKHTVF.js +0 -1
  143. package/dist/workspace-watch-SOPZHRWA.js +0 -1
@@ -0,0 +1,316 @@
1
+ # Workspace Knowledge Graph
2
+
3
+ Most code graphs answer questions about one repository. Workspai connects code,
4
+ APIs, infrastructure, delivery, documentation, ownership, tests, and runtime
5
+ configuration across a whole workspace—and records why every relationship is
6
+ believed.
7
+
8
+ The graph is local-first and deterministic. Building it does not require an
9
+ LLM, a hosted service, embeddings, or a graph database.
10
+
11
+ ## Why this is useful
12
+
13
+ A repository graph can tell you that function A calls function B. A workspace
14
+ question is usually wider:
15
+
16
+ > If we change this endpoint, which project consumes it, which deployment ships
17
+ > it, which tests cover it, which document describes it, and which release gate
18
+ > can stop it?
19
+
20
+ Workspai keeps those domains in one proof-carrying representation. The graph is
21
+ not the final product screen; it is the shared knowledge layer behind impact,
22
+ verification, context, MCP, IDE, CI, and agent workflows.
23
+
24
+ | If you are… | The graph helps you… |
25
+ | -------------------- | ------------------------------------------------------------------------------------------ |
26
+ | A developer | find the implementation, nearby dependencies, tests, and evidence without repo-wide search |
27
+ | A tech lead | inspect cross-project boundaries, owners, contracts, and change paths |
28
+ | An AI coding agent | retrieve question-sized context and verify every returned claim |
29
+ | A CI/release system | consume versioned JSON, source hashes, quality diagnostics, and deterministic exits |
30
+ | An IDE or MCP client | offer the same system understanding without rebuilding a private index |
31
+
32
+ ## What makes it a workspace graph
33
+
34
+ Workspai does not stop at files, imports, functions, and classes. Repository
35
+ structure is one provider domain alongside APIs, containers, infrastructure,
36
+ pipelines, documents, decisions, ownership, tests, environments, and authored
37
+ workspace contracts.
38
+
39
+ That distinction matters when the answer crosses repositories. The canonical
40
+ Workspace Model remains the source of truth; the Knowledge Graph is its rich,
41
+ queryable, evidence-backed representation. AI is a consumer, never a requirement
42
+ for building the graph.
43
+
44
+ ## Try it in two minutes
45
+
46
+ Run from a Workspai workspace:
47
+
48
+ ```bash
49
+ npx workspai workspace model --write --json
50
+ npx workspai workspace graph search "authentication endpoint" --limit 12 --json
51
+ ```
52
+
53
+ Useful follow-up questions:
54
+
55
+ ```bash
56
+ # What APIs and endpoints exist?
57
+ npx workspai workspace graph entities endpoint --json
58
+
59
+ # Why does Workspai believe this entity exists?
60
+ npx workspai workspace graph evidence "GET /users" --json
61
+
62
+ # How are two services, files, or APIs connected?
63
+ npx workspai workspace graph path frontend-api "GET /users" --json
64
+
65
+ # What changed since a saved graph revision?
66
+ npx workspai workspace graph overlay --from previous-graph.json --json
67
+ ```
68
+
69
+ For agents and MCP clients, prefer bounded search over loading the complete
70
+ graph:
71
+
72
+ ```bash
73
+ npx workspai workspace graph search "billing database" --limit 12 --json
74
+ ```
75
+
76
+ A simplified response looks like this:
77
+
78
+ ```json
79
+ {
80
+ "schemaVersion": "workspace-knowledge-search.v1",
81
+ "query": "billing database",
82
+ "totalMatches": 23,
83
+ "truncated": true,
84
+ "entities": [{ "kind": "database", "label": "billing-db", "proofIds": ["proof:..."] }],
85
+ "relations": [{ "kind": "reads-from", "from": "service:billing", "to": "database:billing-db" }],
86
+ "proofs": [{ "provider": "compose", "artifact": "infra/compose.yml", "trust": "authoritative" }]
87
+ }
88
+ ```
89
+
90
+ The response is intentionally bounded. `totalMatches` tells the consumer more
91
+ results exist, `truncated` prevents silent omission, and every returned claim can
92
+ be traced through `proofIds`.
93
+
94
+ ## Pick the command by question
95
+
96
+ | You want to know… | Use |
97
+ | ---------------------------------------------------- | ------------------------------------------------------- |
98
+ | What is relevant to a natural-language question? | `workspace graph search <query> --limit <n> --json` |
99
+ | Which entities of one type exist? | `workspace graph entities <kind> --json` |
100
+ | Why does Workspai believe an item exists? | `workspace graph evidence <entity-or-relation> --json` |
101
+ | How are two things connected? | `workspace graph path <from> <to> --json` |
102
+ | What changed between graph revisions? | `workspace graph overlay --from <graph.json> --json` |
103
+ | What is the full portable graph? | `workspace graph emit --json` |
104
+ | How do I export to semantic or graph-analysis tools? | `workspace graph jsonld\|graphml\|gexf --output <file>` |
105
+ | How much retrieval payload did one query avoid? | `workspace graph benchmark <query> --limit <n> --json` |
106
+ | How should an MCP-compatible agent retrieve context? | `workspace mcp serve` → `searchWorkspaceGraph` |
107
+
108
+ ## What it models
109
+
110
+ The current graph can represent:
111
+
112
+ - workspaces, projects, services, packages, modules, files, and symbols;
113
+ - APIs, endpoints, schemas, events, queues, and databases;
114
+ - containers, deployments, environments, pipelines, and infrastructure;
115
+ - documentation, architecture decisions, tests, and owners.
116
+
117
+ Relations include `contains`, `imports`, `depends-on`, `calls`, `exposes`,
118
+ `implements`, `reads-from`, `writes-to`, `publishes`, `consumes`, `deploys`,
119
+ `documents`, `decided-by`, `tests`, and `owns`.
120
+
121
+ Every entity and relation carries portable proof references. A proof records its
122
+ provider, source artifact, optional pointer/line, content hash, freshness,
123
+ derivation, trust, and confidence. Secret values and machine-local absolute
124
+ paths are excluded from the portable graph contract.
125
+
126
+ ## Model first, graph second
127
+
128
+ The canonical direction is one-way:
129
+
130
+ ```text
131
+ Workspace sources
132
+
133
+ Canonical Workspace Model + project topology
134
+
135
+ Evidence-backed Workspace Knowledge Graph
136
+
137
+ CLI queries · Context · MCP · Agents · IDEs · CI
138
+ ```
139
+
140
+ The graph does not rewrite or replace the canonical Workspace Model. It is a
141
+ derived representation bound to an exact model revision by SHA-256. Context and
142
+ MCP consumers reject a graph whose source hash no longer matches the model.
143
+
144
+ The model also contains a smaller project dependency graph. That projection is
145
+ used for impact, blast radius, verify, explain, watch, and affected fleet runs.
146
+ The richer Knowledge Graph is used for proof-backed retrieval and cross-domain
147
+ understanding.
148
+
149
+ ## Sources and providers
150
+
151
+ The current CLI uses bounded providers for:
152
+
153
+ - workspace/project foundations and service contracts;
154
+ - language-neutral source structure and package manifests;
155
+ - OpenAPI, GraphQL, Protobuf, and AsyncAPI interfaces;
156
+ - Docker/Compose, Kubernetes, Terraform, and CI workflows;
157
+ - README/docs, ADRs, tests, and CODEOWNERS.
158
+
159
+ Providers emit facts and proofs. The graph engine owns stable identity,
160
+ deduplication, typed relations, reconciliation, quality metrics, diagnostics,
161
+ and deterministic ordering. Regex-backed source observations are explicitly
162
+ marked as observed/medium-confidence; authored contracts remain authoritative.
163
+
164
+ ## Outputs and consumers
165
+
166
+ `workspace model --write` publishes these two artifacts atomically:
167
+
168
+ ```text
169
+ .workspai/reports/workspace-model.json
170
+ .workspai/reports/workspace-knowledge-graph.json
171
+ ```
172
+
173
+ The Knowledge Graph is consumed by:
174
+
175
+ - `workspace graph search|entities|evidence|path|overlay`;
176
+ - `workspace context`, which validates the model hash and publishes graph
177
+ availability and query commands;
178
+ - `workspace agent-sync`, which places it in the evidence index and generated
179
+ agent/MCP instructions;
180
+ - `workspace mcp serve`, through `getWorkspaceKnowledgeGraph`,
181
+ `searchWorkspaceGraph`, `queryWorkspaceEntities`,
182
+ `getWorkspaceGraphEvidence`, and `findWorkspaceGraphPath`;
183
+ - `workspace contract graph`, which exposes the contract projection, project
184
+ topology, rich graph, and quality summary in one response.
185
+
186
+ The complete graph is an interchange artifact, not a prompt. Agents should
187
+ start with `INDEX.json`, use bounded search, then retrieve evidence or a path
188
+ for the selected result.
189
+
190
+ ### Interchange and visualization
191
+
192
+ The JSON artifact is the canonical interchange form of the derived graph; the
193
+ Workspace Model remains the system source of truth. Other formats are
194
+ deterministic projections of that same graph revision:
195
+
196
+ ```bash
197
+ npx workspai workspace graph mermaid
198
+ npx workspai workspace graph dot
199
+ npx workspai workspace graph jsonld --output workspace-graph.jsonld
200
+ npx workspai workspace graph graphml --output workspace-graph.graphml
201
+ npx workspai workspace graph gexf --output workspace-graph.gexf
202
+ ```
203
+
204
+ - Mermaid and DOT are suited to documentation and architecture diagrams.
205
+ - JSON-LD carries semantic identities, relations, and proof references.
206
+ - GraphML and GEXF work with graph-analysis and interactive visualization tools.
207
+ - The canonical JSON, JSON-LD, GraphML, and GEXF outputs can drive 2D or 3D
208
+ viewers; a 3D view is a presentation layer, not a separate source of truth.
209
+
210
+ ## AI tool output locations
211
+
212
+ `workspace agent-sync --write --preset enterprise` generates native surfaces
213
+ without changing project source:
214
+
215
+ | Consumer | Canonical output |
216
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
217
+ | Cross-tool/Codex | `AGENTS.md`, `.workspai/reports/INDEX.json` |
218
+ | Claude Code | `CLAUDE.md`, `.claude/rules/workspai-evidence.md` |
219
+ | GitHub Copilot/VS Code | `.github/copilot-instructions.md`, `.github/instructions/workspai-*.instructions.md`, `.github/agents/workspai-*.agent.md`, `.github/prompts/workspai-*.prompt.md` |
220
+ | Cursor | `.cursor/rules/workspai-grounding.mdc` |
221
+ | MCP clients | `.workspai/reports/workspai-mcp-design.json`, `workspace mcp serve` |
222
+
223
+ Files named `rapidkit-*` are compatibility aliases for older consumers. They
224
+ must stay narrowly scoped and must not duplicate an always-applied canonical
225
+ rule.
226
+
227
+ ### Avoiding duplicate AI instructions
228
+
229
+ Canonical Workspai rules are the only always-applied surfaces. Legacy RapidKit
230
+ aliases point to the canonical files and apply only to `.rapidkit/**`. This
231
+ prevents two equivalent instruction files from being injected into one prompt.
232
+
233
+ The recommended read order is:
234
+
235
+ 1. `AGENTS.md` for stable workspace policy and navigation;
236
+ 2. `.workspai/reports/INDEX.json` for artifact discovery and freshness;
237
+ 3. `workspace graph search` or `searchWorkspaceGraph` for question-sized facts;
238
+ 4. `workspace graph evidence|path` when a claim needs proof;
239
+ 5. the complete model or graph only for export, audit, or whole-system analysis.
240
+
241
+ ## Performance and scale
242
+
243
+ Graph construction inventories each project once per build and caps the number
244
+ of scanned files. Providers reuse the same in-memory inventory and content
245
+ hashes. Query indexes are cached per immutable graph object; replacing the graph
246
+ is the invalidation boundary. `workspace model --cache` and `--incremental`
247
+ avoid unnecessary model/project work when inputs are unchanged.
248
+
249
+ Use full graph export for interchange or offline analysis. Use bounded search
250
+ for interactive agents. The latter keeps response size proportional to the
251
+ question instead of workspace size.
252
+
253
+ ## Measuring retrieval payload reduction
254
+
255
+ Workspai does not publish an unqualified “N× fewer tokens” claim. Such a claim
256
+ depends on the workspace, query, tokenizer, model, answer-quality target, and
257
+ baseline.
258
+
259
+ Measure the current workspace instead:
260
+
261
+ ```bash
262
+ npx workspai workspace graph benchmark "authentication endpoint" --limit 12 --json
263
+ ```
264
+
265
+ The report compares the readable, proof-indexed source corpus with the bounded
266
+ search payload using a clearly labelled `characters / 4` token estimate. It
267
+ reports corpus size, retrieval size, estimated ratio, percentage reduction,
268
+ unreadable artifacts, query, limit, graph counts, and the exact source-model
269
+ SHA-256 needed to reproduce the run.
270
+
271
+ This proves **retrieval payload reduction**, not equivalent answer quality,
272
+ model-specific billing savings, or universal token savings. A publishable
273
+ cross-project claim additionally requires pinned source revisions, fixed
274
+ queries, a real tokenizer, repeated runs, and answer-quality evaluation.
275
+
276
+ In the current 16-project development fixture, the query `api endpoint` with
277
+ `--limit 8` returned 8 entities and 9 proofs. The compact retrieval was 2,812
278
+ estimated tokens versus 134,105 estimated tokens in 392 readable proof-source
279
+ artifacts: an observed 47.69× / 97.9% payload reduction. This is a transparent
280
+ fixture result, not a headline claim for every workspace.
281
+
282
+ See [Graph Benchmark Methodology](./graph-benchmark-methodology.md) for formulas,
283
+ reproduction rules, realistic baselines, and the gate required before publishing
284
+ a general performance claim.
285
+
286
+ ## Current boundaries
287
+
288
+ - The CLI graph is intentionally file-backed; a graph database is not required.
289
+ - Text search is deterministic lexical retrieval, not embedding similarity.
290
+ - Compiler/LSP-grade symbol resolution belongs in deeper language providers.
291
+ - Missing project edges mean “relationship not proven,” not “projects are
292
+ independent.” Author service contracts or provide API/package/runtime
293
+ evidence to close that gap.
294
+ - The standalone `@workspai/graph` package remains unpublished while its public
295
+ contracts and conformance gates are developed.
296
+
297
+ ## When the graph looks incomplete
298
+
299
+ Workspai does not invent relationships. If projects appear as disconnected
300
+ nodes, check the following in order:
301
+
302
+ 1. run `workspace sync --json` and regenerate the model;
303
+ 2. declare `dependsOn`, APIs, published events, and consumed events in the
304
+ workspace/project contracts;
305
+ 3. confirm package manifests, OpenAPI/AsyncAPI/GraphQL/Protobuf documents,
306
+ Compose/Kubernetes/Terraform files, and CI definitions are inside registered
307
+ project paths;
308
+ 4. inspect `graph.quality`, `providers`, and `diagnostics` before treating a
309
+ missing edge as proof of independence.
310
+
311
+ An absent edge means “not proven by current evidence,” not “no dependency
312
+ exists.”
313
+
314
+ For schemas and machine contracts, see the
315
+ [Artifact Catalog](./contracts/ARTIFACT_CATALOG.md). For the full command
316
+ surface, see [Commands Reference](./commands-reference.md).
@@ -94,6 +94,55 @@ npx workspai workspace contract graph
94
94
 
95
95
  Contract file: `.workspai/workspace.contract.json`. Verification checks schema, duplicate slugs, port collisions, and unknown dependencies.
96
96
 
97
+ `workspace contract graph --json` preserves its original `nodes`, `edges`, and
98
+ summary fields for existing consumers, and now adds an evidence-backed
99
+ `dependencyGraph` using the public `workspace-dependency-graph.v1` contract. It
100
+ discovers package/workspace dependencies and supported cross-project imports,
101
+ records relationship provenance and confidence, and reports graph coverage,
102
+ orphans, hotspots, and cycles. Project nodes also expose safe package metadata,
103
+ public environment-template keys, command capabilities, key manifests,
104
+ entrypoints, API specifications, infrastructure, documentation, and an
105
+ operational verification profile. Environment values are never emitted.
106
+
107
+ The same response also exposes `knowledgeGraph` under the public
108
+ `workspace-knowledge-graph.v1` contract. It is a provider-neutral,
109
+ proof-carrying view spanning source structure, packages, service and API
110
+ contracts, infrastructure, delivery pipelines, docs/ADRs, ownership, tests,
111
+ runtime resources, and safe configuration keys. Use the dedicated query and
112
+ change-overlay surfaces when the full document is larger than a human needs:
113
+
114
+ ```bash
115
+ npx workspai workspace graph entities endpoint --json
116
+ npx workspai workspace graph search "authentication endpoint" --limit 12 --json
117
+ npx workspai workspace graph benchmark "authentication endpoint" --limit 12 --json
118
+ npx workspai workspace graph evidence "GET /users" --json
119
+ npx workspai workspace graph path frontend-api "GET /users" --json
120
+ npx workspai workspace graph emit --json > .workspai/reports/knowledge-baseline.json
121
+ npx workspai workspace graph overlay --from .workspai/reports/knowledge-baseline.json --json
122
+ ```
123
+
124
+ The Model step persists the same projection to
125
+ `.workspai/reports/workspace-knowledge-graph.json`. It is registered in the
126
+ artifact contract registry and agent report index, required by the unified
127
+ runner's Model stage, referenced from `workspace-context-agent.json`, and
128
+ queryable through the read-mostly MCP server. This keeps CLI, CI, IDE and agent
129
+ consumers on one contract revision without injecting the full graph into every
130
+ agent prompt.
131
+
132
+ The overlay follows
133
+ `workspace-knowledge-graph-change-overlay.v1`: graph revisions are identified
134
+ by content-derived fingerprints (timestamps do not create false changes), and
135
+ changed artifacts are portable proof paths rather than machine-local absolute
136
+ paths. Proof additions, removals, and content-hash changes are first-class
137
+ overlay changes, so a source edit is visible even when the entity and relation
138
+ shape remains stable. The builder performs one bounded inventory pass per project and reuses
139
+ in-memory content hashes; query indexes live only for the immutable graph
140
+ instance, so replacing the graph is the invalidation boundary.
141
+
142
+ Direction is explicit: legacy `edges` remain producer-to-consumer for backward
143
+ compatibility; `dependencyGraph.edges` use consumer-to-dependency semantics so
144
+ impact and blast-radius consumers share one canonical interpretation.
145
+
97
146
  Workspai keeps the contract alive during `create project` and `workspace sync` without overwriting manual API/event/owner declarations.
98
147
 
99
148
  On a freshly cloned or moved workspace, `workspace sync` also repairs the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workspai",
3
- "version": "0.46.0",
3
+ "version": "0.48.0",
4
4
  "type": "module",
5
5
  "description": "Open-source workspace intelligence CLI for software systems: create, adopt, govern, verify, and align polyglot workspaces for humans, CI, IDEs, and AI agents.",
6
6
  "keywords": [
@@ -158,6 +158,7 @@
158
158
  "openai": "^6.22.0",
159
159
  "ora": "^8.0.1",
160
160
  "validate-npm-package-name": "^5.0.1",
161
+ "yaml": "^2.9.0",
161
162
  "yauzl": "^3.4.0",
162
163
  "yazl": "^3.3.1"
163
164
  },
@@ -1 +0,0 @@
1
- export{b as printAnalyzeReport,a as runAnalyze}from'./chunk-RIEF2DDX.js';
@@ -1,3 +0,0 @@
1
- import {a}from'./chunk-2E6WGUN6.js';import {c,g,d}from'./chunk-HDURFXW5.js';import y from'path';import {existsSync}from'fs';import x from'fs-extra';var I=[{artifactKind:"bootstrap-compliance",cardId:"bootstrap",fileNames:["bootstrap-compliance.latest.json"]},{artifactKind:"doctor-workspace",cardId:"doctor",fileNames:["doctor-remediation-plan-last-run.json"]},{artifactKind:"analyze",cardId:"analyze",fileNames:["analyze-last-run.json"]},{artifactKind:"readiness",cardId:"readiness",fileNames:["release-readiness-last-run.json"]},{artifactKind:"pipeline",cardId:"pipeline",fileNames:["pipeline-last-run.json"]},{artifactKind:"workspace-run",cardId:"workspaceRun",fileNames:["workspace-run-last.json"]},{artifactKind:"workspace-verify",cardId:"workspaceVerify",fileNames:["workspace-verify-last-run.json"]}];function m(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:void 0}function f(e){return Array.isArray(e)?e.filter(r=>typeof r=="string"&&r.trim().length>0):[]}function u(e){return [...new Set(e.map(r=>r.trim()).filter(Boolean))]}function K(e,r,t){return t?r:y.relative(e,r)}function C(e){let r=e?.trim()||"npx workspai bootstrap";if(!/(?:^|\s)--ci(?:\s|$)/.test(r)&&/(?:^|\s)--json(?:\s|$)/.test(r))return r.replace(/(?:^|\s)--json(?:\s|$)/,i=>{let n=i.startsWith(" ")?" ":"",c=i.endsWith(" ")?" ":"";return `${n}--ci --json${c}`}).trim();let t=/(?:^|\s)--ci(?:\s|$)/.test(r)?r:`${r} --ci`;return /(?:^|\s)--json(?:\s|$)/.test(t)?t:`${t} --json`}function M(e){return `${JSON.stringify({schemaVersion:"rapidkit.compatibility-matrix.v1",generatedAt:e,source:"workspai workspace remediation-plan",runtimes:{},notes:["Minimal enterprise baseline. Add runtime and toolchain entries as governance matures."]},null,2)}
2
- `}function N(e){return `${JSON.stringify({schema_version:"1.0",enabled:false,strategy:"on-demand",artifacts:[],created_at:e,note:"Minimal enterprise baseline. Set enabled: true and add artifact entries to activate mirroring."},null,2)}
3
- `}function P(e){let r=e.payload,t=f(r.blockers),i=f(r.blockingReasons),n=f(r.failures),c=f(r.reasons),d=f(r.policyViolations),a=m(r.summary),l=f(a?.blockers);if(e.artifactKind==="analyze"){let o=(Array.isArray(r.findings)?r.findings:[]).map(s=>m(s)).filter(s=>!!s).map(s=>String(s.message??s.title??s.id??"").trim()).filter(Boolean);return u([...t,...o,...i])}if(e.artifactKind==="workspace-run"){let g=m(r.stages),o=Object.entries(g??{}).flatMap(([s,b])=>{let A=m(b);return (Array.isArray(A?.projects)?A.projects:[]).map(p=>m(p)).filter(p=>!!p).filter(p=>p.status==="failed"||p.ok===false).map(p=>`${s}: ${String(p.project??p.name??"project")} failed`)});return u([...t,...o,...i])}return u([...t,...i,...n,...c,...d,...l])}function k(e){return {id:e.id,artifactKind:e.artifactKind,cardId:e.cardId,title:e.title,order:e.order,phase:e.phase,scope:"workspace",status:e.status??"ready",mode:e.mode,risk:e.risk,requiresApproval:true,blocker:e.blocker,summary:e.summary,...e.command?{command:e.command}:{},verifyCommand:e.verifyCommand,cwd:"workspace",files:e.files??[],...e.operation?{operation:e.operation}:{},rollback:{available:!!e.operation,strategy:e.operation?"idempotent":"none"},notes:e.notes??[]}}function S(e){let r=[],t=C("npx workspai bootstrap --json");for(let i of e.blockers)i.includes("profile.enterprise.ci")&&r.push(k({id:"bootstrap.enterprise-ci",artifactKind:"bootstrap-compliance",cardId:"bootstrap",title:"Run bootstrap in deterministic CI mode",order:10,phase:"bootstrap-preflight",blocker:i,summary:"Enterprise bootstrap compliance requires --ci for deterministic execution.",mode:"run-command",risk:"safe",command:t,verifyCommand:t})),i.includes("profile.enterprise.compatibility-matrix")&&r.push(k({id:"bootstrap.compatibility-matrix",artifactKind:"bootstrap-compliance",cardId:"bootstrap",title:"Create enterprise compatibility matrix baseline",order:20,phase:"bootstrap-config",blocker:i,summary:"Create the missing compatibility matrix baseline without overwriting user data.",mode:"edit-file",risk:"safe",verifyCommand:t,files:[".workspai/compatibility-matrix.json"],operation:{type:"file-create",path:".workspai/compatibility-matrix.json",content:M(e.generatedAt),overwrite:false}})),i.includes("profile.enterprise.mirror-config")&&r.push(k({id:"bootstrap.mirror-config",artifactKind:"bootstrap-compliance",cardId:"bootstrap",title:"Create enterprise mirror config baseline",order:30,phase:"bootstrap-config",blocker:i,summary:"Create the missing mirror configuration baseline without enabling mirroring.",mode:"edit-file",risk:"safe",verifyCommand:t,files:[".workspai/mirror-config.json"],operation:{type:"file-create",path:".workspai/mirror-config.json",content:N(e.generatedAt),overwrite:false}}));return r}function $(e){let t={analyze:{title:"Refresh analyze evidence",phase:"analysis",command:"npx workspai analyze --strict --json",verify:"npx workspai analyze --strict --json"},readiness:{title:"Refresh release readiness",phase:"release-readiness",command:e.ciMode?"npx workspai readiness --strict --json":"npx workspai readiness --json",verify:e.ciMode?"npx workspai readiness --strict --json":"npx workspai readiness --json"},pipeline:{title:"Rerun governance pipeline",phase:"governance-pipeline",command:"npx workspai pipeline --json --strict",verify:"npx workspai pipeline --json --strict"},"workspace-run":{title:"Rerun failed workspace stage",phase:"fleet-run",command:e.ciMode?"npx workspai workspace run test --strict --json":"npx workspai workspace run test --json",verify:e.ciMode?"npx workspai workspace run test --strict --json":"npx workspai workspace run test --json"},"workspace-verify":{title:"Refresh workspace verify gate",phase:"verification",command:e.ciMode?"npx workspai workspace verify --strict --json":"npx workspai workspace verify --json",verify:e.ciMode?"npx workspai workspace verify --strict --json":"npx workspai workspace verify --json"},"doctor-workspace":{title:"Use Doctor remediation plan",phase:"doctor-remediation",command:"npx workspai doctor workspace --plan --json",verify:"npx workspai doctor workspace --json"}}[e.report.artifactKind]??{title:"Refresh artifact evidence",phase:"evidence-refresh",command:"npx workspai pipeline --json --strict",verify:"npx workspai pipeline --json --strict"};return k({id:`${e.report.cardId}.refresh.${e.order}`,artifactKind:e.report.artifactKind,cardId:e.report.cardId,title:t.title,order:e.order,phase:t.phase,blocker:e.blocker,summary:"No deterministic file operation is available for this artifact yet; refresh the evidence and continue with the card-specific plan.",mode:e.report.artifactKind==="doctor-workspace"?"verify-before-fix":"run-command",risk:"guarded",status:e.report.artifactKind==="doctor-workspace"?"review-required":"ready",command:t.command,verifyCommand:t.verify,notes:e.report.artifactKind==="doctor-workspace"?["Read doctor-remediation-plan-last-run.json for ordered file-level steps."]:[]})}async function O(e){let r=[c(e,".workspai/reports"),d(e,".workspai/reports")],t=[],i=new Set;for(let n of I)for(let c of n.fileNames){let d=(await Promise.all(r.map(a=>y.join(a,c)))).find(a=>existsSync(a));if(!(!d||i.has(`${n.artifactKind}:${c}`))){i.add(`${n.artifactKind}:${c}`);try{let a=await x.readJSON(d),l=m(a);if(!l)continue;t.push({artifactKind:n.artifactKind,cardId:n.cardId,fileName:c,absolutePath:d,payload:l});}catch{t.push({artifactKind:n.artifactKind,cardId:n.cardId,fileName:c,absolutePath:d,payload:{blockers:[`${n.artifactKind}: report exists but could not be parsed.`]}});}}}return t}async function F(e){let r=y.resolve(e.workspacePath),t=e.includeAbsolutePaths===true,i=e.ciMode===true,n=new Date().toISOString(),c$1=c(r,".workspai/reports"),d=await O(r),a$1=[],l=1;for(let o of d){let s=P(o);if(s.length!==0){if(o.artifactKind==="bootstrap-compliance"){a$1.push(...S({blockers:s,generatedAt:n})),l=a$1.length+1;continue}for(let b of s.slice(0,8))a$1.push($({report:o,blocker:b,order:l,ciMode:i})),l+=1;}}let g={safe:a$1.filter(o=>o.risk==="safe").length,guarded:a$1.filter(o=>o.risk==="guarded").length,invasive:a$1.filter(o=>o.risk==="invasive").length};return {schemaVersion:a,generatedAt:n,workspace:{name:y.basename(r),...t?{path:r}:{}},source:{command:"workspace remediation-plan",reportsDir:K(r,c$1,t),includeAbsolutePaths:t,ciMode:i},summary:{artifactsScanned:d.length,cardsCovered:u(a$1.map(o=>o.cardId)).length,totalActions:a$1.length,executableActions:a$1.filter(o=>o.status==="ready").length,risk:g},actions:a$1}}async function W(e,r){return g(r,".workspai/reports/artifact-remediation-plan-last-run.json",e)}export{F as buildArtifactRemediationPlan,W as writeArtifactRemediationPlan};
@@ -1 +0,0 @@
1
- export{b as AUTOPILOT_RELEASE_ALIAS_FILENAME,a as AUTOPILOT_RELEASE_LAST_RUN_FILENAME,c as runAutopilotRelease}from'./chunk-4EPHWD27.js';
@@ -1,2 +0,0 @@
1
- import {b as b$1}from'./chunk-NHN4QXPP.js';import {i}from'./chunk-MER6ZBN2.js';import {c}from'./chunk-PRBVYW3T.js';import {a}from'./chunk-Y45WZR5N.js';import {f}from'./chunk-7YHK5NM3.js';import {b}from'./chunk-RO73VVHW.js';import {h,g as g$1}from'./chunk-5XATWNME.js';import {promises,constants}from'fs';import c$1 from'path';import T,{homedir}from'os';import {pathToFileURL}from'url';import g from'process';import E from'crypto';import s from'fs/promises';function q(t){let e=t.label.indexOf(" \u2014 ");return e>=0?t.label.slice(e+3).trim():t.label.trim()}function B(){let t=c().map(e=>({value:e.id,label:q(e),hint:e.description,name:e.label})),r=i().map(e=>({value:e.kitId,label:e.displayName,hint:e.commandDisplay("my-app"),name:`${e.displayName} \u2014 ${e.framework}`}));return [...t,...r]}var Q=".workspairc.json",z=".rapidkitrc.json",Z=["workspai.config.js","workspai.config.mjs","workspai.config.cjs","rapidkit.config.js","rapidkit.config.mjs","rapidkit.config.cjs"],ee=["workspai.config.json","rapidkit.config.json"];function I(t){return typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT"}function L(t,r){let e=r instanceof Error?r.message:String(r),i=t.endsWith(".js")&&/module is not defined in ES module scope/i.test(e)?' CommonJS syntax in a .js config is not valid when the project package uses "type": "module"; rename the file to .cjs or use export default.':"";return `Failed to load Workspai config at ${t}.${i} Cause: ${e}`}async function _e(){for(let t of [c$1.join(T.homedir(),Q),c$1.join(T.homedir(),z)])try{let r=await promises.readFile(t,"utf-8"),e=JSON.parse(r);return f.debug(`Loaded config from ${t}`),e}catch{}return f.debug("No user config found, using defaults"),{}}async function Ke(t=process.cwd(),r={}){let e=t,i=c$1.parse(e).root;for(;e!==i;){for(let o of ee){let n=c$1.join(e,o);try{let a=await promises.readFile(n,"utf-8"),l=JSON.parse(a);if(!l||typeof l!="object"||Array.isArray(l))throw new Error("configuration root must be a JSON object");return f.debug(`Loaded data-only Workspai config from ${o}`),l}catch(a){if(I(a))continue;throw new Error(L(n,a))}}for(let o of Z){let n=c$1.join(e,o);try{await promises.access(n);}catch(a){if(I(a))continue;throw new Error(L(n,a))}if(f.debug(`Found config file: ${n}`),!r.trustExecutableConfig)throw new Error(`Refusing to execute Workspai config at ${n} without explicit trust. Use a data-only workspai.config.json file, pass --trust-config, or set WORKSPAI_TRUST_CONFIG=1.`);try{let l=await import(pathToFileURL(n).href),f$1=l.default||l;return f.debug(`Loaded Workspai config from ${o}`),f$1}catch(a){throw new Error(L(n,a))}}e=c$1.dirname(e);}return f.debug("No Workspai config file found, using defaults"),{}}function Me(t,r,e){return {author:e.author||r.workspace?.defaultAuthor||t.author,pythonVersion:e.pythonVersion||r.workspace?.pythonVersion||t.pythonVersion,defaultInstallMethod:e.defaultInstallMethod||r.workspace?.installMethod||t.defaultInstallMethod,defaultKit:e.defaultKit||r.projects?.defaultKit||t.defaultKit,skipGit:e.skipGit??r.projects?.skipGit??t.skipGit,license:e.license||t.license,testRapidKitPath:e.testRapidKitPath||t.testRapidKitPath}}function Ge(t){return a("DEV_PATH")||t.testRapidKitPath||void 0}function re(t,r){let e=t.indexOf(r);if(e>=0&&e+1<t.length)return t[e+1];let i=t.find(o=>o.startsWith(`${r}=`));if(i)return i.slice(r.length+1)}function ie(t){return t.includes("--here")}function U(t,r=g.cwd()){if(ie(t))return c$1.resolve(r);let e=re(t,"--output");if(e)return c$1.resolve(e)}function Ze(t,r=g.cwd()){let e=c$1.resolve(t),i=c$1.resolve(r),o=c$1.relative(i,e);return o.length>0&&!o.startsWith("..")&&!c$1.isAbsolute(o)?`cd ${o}`:`cd ${e}`}function et(t,r={}){let e=r.argv??[],i=r.outputParent??U(e,g.cwd());return h(t.trim(),{homeDir:r.homeDir,outputDir:i})}function tt(t,r,e={}){return t?c$1.resolve(t)===c$1.resolve(r)?true:e.outputParent===void 0:false}async function rt(t,r={}){let e=r.cwd??g.cwd(),i=r.homeDir??homedir(),o=U(t,e);if(o!==void 0)return o;let n=r.hasYes??(t.includes("--yes")||t.includes("-y"));if(!(r.interactive??(!n&&!!g.stdin.isTTY&&!b())))return;let l=g$1(i),{location:f}=await b$1([{type:"rawlist",name:"location",message:"Where should the workspace be created?",choices:[{value:"managed",label:"Managed home",hint:l},{value:"here",label:"Current directory",hint:e}],default:0}]);if(f==="here")return c$1.resolve(e)}var W="workspai.lifecycle-transaction",J=1,N="manifest.json",_="lifecycle-transaction-";async function w(t){try{return await s.lstat(t)}catch(r){if(r.code==="ENOENT")return null;throw r}}function K(t){let r=t?.code;return process.platform==="win32"&&(r==="EPERM"||r==="EINVAL"||r==="ENOSYS")}async function D(t){try{await t.sync();}catch(r){if(!K(r))throw r}}function oe(t){if(typeof t!="string"||!c$1.isAbsolute(t))throw new Error("Lifecycle transaction journal contains a non-absolute target path.")}function ne(t){if(typeof t!="string"||t.length===0||c$1.basename(t)!==t||t==="."||t==="..")throw new Error("Lifecycle transaction journal contains an unsafe backup reference.")}function ae(t){if(!t||typeof t!="object")throw new Error("Lifecycle transaction journal is not an object.");let r=t;if(r.kind!==W||r.version!==J)throw new Error("Lifecycle transaction journal has an unsupported format.");if(!Number.isInteger(r.ownerPid)||r.ownerPid<=0)throw new Error("Lifecycle transaction journal has an invalid owner process.");if(!["active","committed","rolling-back"].includes(r.phase))throw new Error("Lifecycle transaction journal has an invalid phase.");if(!Array.isArray(r.operations))throw new Error("Lifecycle transaction journal has invalid operations.");for(let e of r.operations){if(!e||typeof e!="object")throw new Error("Lifecycle transaction journal contains an invalid operation.");let i=e;if(oe(i.path),i.type!=="tree"){if(i.type!=="file"||!["absent","regular"].includes(i.state))throw new Error("Lifecycle transaction journal contains an invalid operation.");if(i.state==="regular"){if(!Number.isInteger(i.mode)||i.mode<0||i.mode>4095)throw new Error("Lifecycle transaction journal contains an invalid file mode.");ne(i.backup);}}}return r}async function x(t){let r;try{r=await s.open(t,constants.O_RDONLY);}catch(e){if(K(e))return;throw e}try{await D(r);}finally{await r.close();}}async function M(t,r){let e=c$1.join(c$1.dirname(t),`.${c$1.basename(t)}.${process.pid}.${E.randomUUID()}.tmp`);try{let i=await s.open(e,constants.O_WRONLY|constants.O_CREAT|constants.O_EXCL,384);try{await i.writeFile(r),await D(i);}finally{await i.close();}await s.rename(e,t),await x(c$1.dirname(t));}catch(i){throw await s.rm(e,{force:true}).catch(()=>{}),i}}async function G(t,r){await M(c$1.join(t,N),Buffer.from(`${JSON.stringify(r,null,2)}
2
- `));}async function V(t,r){let e=await w(t.path);if(e?.isSymbolicLink()||e&&!e.isFile())throw new Error(`Refusing to restore over a non-regular file: ${t.path}`);if(t.state==="absent"){e&&await s.unlink(t.path);return}if(!r)throw new Error(`Missing durable backup for: ${t.path}`);if(!await w(c$1.dirname(t.path)))return;let i=c$1.join(r,t.backup),o=await s.lstat(i).catch(f=>{if(f.code==="ENOENT"&&e?.isFile())return e;throw f});if(o===e)return;if(!o.isFile()||o.isSymbolicLink())throw new Error(`Lifecycle transaction backup is not a regular file: ${i}`);let n=await s.readFile(i),a=c$1.join(c$1.dirname(t.path),`.${c$1.basename(t.path)}.${process.pid}.${E.randomUUID()}.rollback`),l=await s.open(a,constants.O_WRONLY|constants.O_CREAT|constants.O_EXCL,t.mode);try{await l.writeFile(n),await l.chmod(t.mode),await D(l);}finally{await l.close();}try{await s.rename(a,t.path),await x(c$1.dirname(t.path));}catch(f){throw await s.rm(a,{force:true}).catch(()=>{}),f}}async function Y(t){let r=await w(t.path);if(r){if(r.isSymbolicLink()||!r.isDirectory())throw new Error(`Refusing to remove a non-directory owned tree: ${t.path}`);await s.rm(t.path,{recursive:true});}}async function se(t,r){let e=[];for(let i of [...t].reverse())try{i.type==="file"?await V(i,r):await Y(i);}catch(o){e.push(o);}if(e.length>0)throw new AggregateError(e,"Lifecycle transaction rollback failed.")}var j=class t{constructor(r){this.transactionDirectory=r;this.journalPath=r?c$1.join(r,N):void 0;}transactionDirectory;journalPath;actions=[];durableOperations=[];phase="active";finished=false;static async create(r={}){if(!r.journalDirectory)return new t;let e=c$1.resolve(r.journalDirectory);await s.mkdir(e,{recursive:true});let i=await s.mkdtemp(c$1.join(e,_));await x(e);let o=new t(i);return await o.persist(),o}assertActive(){if(this.finished||this.phase!=="active")throw new Error("Lifecycle transaction is no longer active.")}async persist(r=this.durableOperations){this.transactionDirectory&&await G(this.transactionDirectory,{kind:W,version:J,ownerPid:process.pid,phase:this.phase,operations:r});}async addDurableOperation(r){let e=[...this.durableOperations,r];await this.persist(e),this.durableOperations.push(r),this.actions.push(r);}async captureFile(r){this.assertActive();let e=c$1.resolve(r),i=await w(e);if(!i){await this.addDurableOperation({type:"file",path:e,state:"absent"});return}if(i.isSymbolicLink()||!i.isFile())throw new Error(`Lifecycle transaction can only capture regular files: ${e}`);let o;try{o=await s.open(e,constants.O_RDONLY|(constants.O_NOFOLLOW??0));}catch(n){throw n.code==="ENOENT"?new Error(`File changed while being captured: ${e}`,{cause:n}):n}try{let n=await o.stat();if(!n.isFile())throw new Error(`Lifecycle transaction can only capture regular files: ${e}`);let a=await o.readFile(),l=n.mode&4095;if(this.transactionDirectory){let f=`file-${this.durableOperations.length}-${E.randomUUID()}.bin`;await M(c$1.join(this.transactionDirectory,f),a),await this.addDurableOperation({type:"file",path:e,state:"regular",mode:l,backup:f});}else {let f=`memory-${this.durableOperations.length}`,y={type:"file",path:e,state:"regular",mode:l,backup:f};this.durableOperations.push(y),this.actions.push({type:"compensation",run:async()=>{let d=await w(e);if(d?.isSymbolicLink()||d&&!d.isFile())throw new Error(`Refusing to restore over a non-regular file: ${e}`);let b=c$1.join(c$1.dirname(e),`.${c$1.basename(e)}.${process.pid}.${E.randomUUID()}.rollback`);await s.writeFile(b,a,{flag:"wx",mode:l}),await s.chmod(b,l);try{await s.rename(b,e);}catch(H){throw await s.rm(b,{force:true}).catch(()=>{}),H}}});}}finally{await o.close();}}async captureOwnedTree(r){this.assertActive();let e=c$1.resolve(r),i=await w(e);if(!i)return await this.addDurableOperation({type:"tree",path:e}),true;if(i.isSymbolicLink()||!i.isDirectory())throw new Error(`Lifecycle transaction tree must be absent or a directory: ${e}`);return false}registerCompensation(r){this.assertActive(),this.actions.push({type:"compensation",run:async()=>r()});}async commit(){if(!this.finished){this.assertActive(),this.phase="committed";try{await this.persist(),this.finished=true,this.actions.length=0,this.transactionDirectory&&await s.rm(this.transactionDirectory,{recursive:true}).catch(()=>{});}catch(r){throw this.phase="active",r}}}async rollback(){if(this.finished||this.phase==="committed")return;this.assertActive(),this.phase="rolling-back";try{await this.persist();}catch(e){throw this.phase="active",e}let r=[];for(let e of [...this.actions].reverse())try{e.type==="compensation"?await e.run():e.type==="file"?await V(e,this.transactionDirectory):await Y(e);}catch(i){r.push(i);}if(r.length>0)throw new AggregateError(r,"Lifecycle transaction rollback failed.");this.finished=true,this.transactionDirectory&&await s.rm(this.transactionDirectory,{recursive:true});}};async function lt(t={}){return j.create(t)}async function ft(t){let r=c$1.resolve(t),e=await s.readdir(r,{withFileTypes:true}).catch(n=>{if(n.code==="ENOENT")return [];throw n}),i=[],o=[];for(let n of e){if(!n.isDirectory()||!n.name.startsWith(_))continue;let a=c$1.join(r,n.name);try{let l;try{l=await s.readFile(c$1.join(a,N),"utf8");}catch(d){if(d.code==="ENOENT")continue;throw d}let f=ae(JSON.parse(l));if(f.phase==="committed"){await s.rm(a,{recursive:true});continue}let y=false;try{process.kill(f.ownerPid,0),y=true;}catch(d){y=d.code==="EPERM";}if(y)continue;f.phase==="active"&&(f.phase="rolling-back",await G(a,f)),await se(f.operations,a),await s.rm(a,{recursive:true}),i.push(a);}catch(l){o.push(l);}}if(o.length>0)throw new AggregateError(o,"Lifecycle transaction recovery failed.");return i}export{B as a,_e as b,Ke as c,Me as d,Ge as e,Ze as f,et as g,tt as h,rt as i,lt as j,ft as k};
@@ -1,8 +0,0 @@
1
- import {a as a$1}from'./chunk-QA5BGEQW.js';import {a as a$4}from'./chunk-22DT744Z.js';import {a as a$2,e}from'./chunk-WPEEC5BX.js';import {f,c,g}from'./chunk-HDURFXW5.js';import {a}from'./chunk-N7DV5L7C.js';import a$3 from'chalk';import se from'fs';import b from'path';import {execa}from'execa';var G="autopilot-release-last-run.json",V="autopilot-release.json";function j(r){try{return JSON.parse(r)}catch{return null}}function Re(r){let e=b.resolve(r),n=a$4(e);if(!n)throw new Error("No Workspai workspace found in current directory or parents");return n}async function S(r,e){let n=process.argv[1];if(!n)return {exitCode:1,stdout:"",stderr:"RapidKit entrypoint is unavailable for autopilot execution.",crashed:true};try{let o=await execa(process.execPath,[n,...r],{cwd:e,reject:false,env:{...process.env,RAPIDKIT_AUTOPILOT_CHILD:"1"}});return {exitCode:Number(o.exitCode??1),stdout:o.stdout,stderr:o.stderr,crashed:false}}catch(o){return {exitCode:1,stdout:"",stderr:o instanceof Error?o.message:String(o),crashed:true}}}function re(r){let e=r.toLowerCase();return e==="pass"?"pass":e==="warn"?"warn":e==="fail"?"fail":"warn"}function oe(r){return r.summary.failed>0||r.gates.results.some(e=>e.status==="fail")?"fail":r.gates.results.some(e=>e.status==="warn")?"warn":"pass"}function Se(r){let e=r.filter(o=>o.status!=="skipped");if(e.length===0)return 100;let n=e.reduce((o,t)=>t.status==="pass"?o+1:t.status==="warn"?o+.6:o,0);return Math.round(n/e.length*100)}function be(r){return r.executionError?["Re-run: npx workspai autopilot release --mode audit --json","Inspect .workspai/reports/autopilot-release-last-run.json for execution failure details"]:r.blockers.length>0?["Run: npx workspai doctor workspace --plan","Run: npx workspai readiness --json --strict","Run: npx workspai workspace run test --affected --strict"]:r.hasWarnings&&r.mode!=="enforce"?["Review warning-level findings in autopilot report","Optionally run: npx workspai autopilot release --mode safe-fix"]:["Workspace is release-ready based on current autopilot policy"]}async function xe(r,e){await se.promises.mkdir(b.dirname(r),{recursive:true}),await se.promises.writeFile(r,`${JSON.stringify(e,null,2)}
2
- `,"utf-8");}async function Me(r){let e$1=Re(r.workspacePath),n=r.mode,o=[],t=[],F,H,D,q,Q,X=0,f$1=false,T=0,L=0,N=-1,W=-1,c$1="skipped",d="skipped",ae=n==="enforce"?["doctor","workspace","--json","--strict"]:["doctor","workspace","--json","--ci"];if(r.skipPipelineStages)o.push({name:"doctor-workspace",status:"skipped",durationMs:0,summary:"doctor stage skipped (pipeline already executed)"},{name:"analyze",status:"skipped",durationMs:0,summary:"analyze stage skipped (pipeline already executed)"},{name:"readiness",status:"skipped",durationMs:0,summary:"readiness stage skipped (pipeline already executed)"});else {let s=Date.now(),l=await S([...ae],e$1),m=Date.now()-s;if(c$1="pass",l.crashed)c$1="fail",f$1=true,t.push(`doctor workspace execution error: ${l.stderr||"unknown error"}`);else if(l.exitCode===1)c$1="fail",t.push("doctor workspace command failed or reported errors");else if(l.exitCode===2)c$1="warn",t.push("doctor workspace reported warnings");else if(l.exitCode!==0)c$1="fail",t.push("doctor workspace command failed");else {let p=j(l.stdout),E=p&&p.healthScore&&typeof p.healthScore=="object"?p.healthScore:{},k=Number(E.errors??0),$=Number(E.warnings??0);Number.isFinite(k)&&k>0?(c$1="fail",t.push(`doctor workspace reports ${k} error(s)`)):Number.isFinite($)&&$>0&&(c$1="warn");}N=o.push({name:"doctor-workspace",status:c$1,durationMs:m,summary:c$1==="pass"?"doctor workspace passed":c$1==="warn"?"doctor workspace reported warnings":"doctor workspace reported errors"})-1,n==="enforce"&&c$1==="warn"&&t.push("doctor workspace reported warnings under enforce mode");let g=Date.now(),w=await S(["analyze","--json"],e$1),v=Date.now()-g;H=await f(e$1,a.analyze)??c(e$1,a.analyze);let i="pass";if(w.crashed)i="fail",f$1=true,t.push(`analyze execution error: ${w.stderr||"unknown error"}`);else if(w.exitCode!==0)i=w.exitCode===2?"warn":"fail",t.push(w.exitCode===2?"analyze reported needs-attention verdict":"analyze command failed or reported blocked verdict");else {let p=j(w.stdout),E=p&&p.summary&&typeof p.summary=="object"?p.summary:{},k=String(E.verdict??"ready");k==="blocked"?(i="fail",t.push("analyze reported blocked verdict")):k==="needs-attention"&&(i="warn");}o.push({name:"analyze",status:i,durationMs:v,summary:i==="pass"?"analyze passed":i==="warn"?"analyze reported needs-attention":"analyze reported blocked verdict"}),n==="enforce"&&i==="warn"&&t.push("analyze reported warnings under enforce mode");let P=Date.now(),h=await S(["readiness","--json"],e$1),y=Date.now()-P;if(d="fail",h.crashed)d="fail",f$1=true,t.push(`readiness execution error: ${h.stderr||"unknown error"}`);else if(h.exitCode!==0)d="fail",t.push("readiness command failed");else {let p=j(h.stdout),E=String(p?.overallStatus??"fail");if(d=re(E),typeof p?.evidencePath=="string"&&p.evidencePath.trim().length>0&&(F=p.evidencePath),d==="fail"){let k=Array.isArray(p?.blockingReasons)?p?.blockingReasons.filter($=>typeof $=="string"):[];k.length>0?t.push(...k.map($=>`readiness: ${$}`)):t.push("readiness overall status is fail");}}W=o.push({name:"readiness",status:d,durationMs:y,summary:`readiness overall status is ${d}`})-1,n==="enforce"&&d==="warn"&&t.push("readiness reported warnings under enforce mode");}let ne=Date.now(),z=await S(["doctor","workspace","--plan","--json"],e$1),ie=Date.now()-ne,R="warn";if(z.crashed)R="fail",f$1=true,t.push(`doctor remediation plan execution error: ${z.stderr||"unknown error"}`);else if(z.exitCode!==0)R="fail",t.push("doctor remediation plan command failed");else {let s=j(z.stdout),l=s&&s.remediationPlan&&typeof s.remediationPlan=="object"?s.remediationPlan:null,m=Number(l?.totalSteps??0),g=Number(l?.executableSteps??0);Number.isFinite(m)&&m>0&&(T=m),Number.isFinite(g)&&g>0&&(L=g),Number.isFinite(m)&&m===0?R="pass":R="warn";}if(o.push({name:"remediation-plan",status:R,durationMs:ie,summary:R==="pass"?"no remediation steps required":"remediation steps available"}),n==="enforce"&&R==="warn"&&t.push("remediation plan has pending steps under enforce mode"),n==="safe-fix"){let s=Date.now(),l=await S(["doctor","workspace","--apply"],e$1),m=Date.now()-s,g=l.crashed||l.exitCode!==0?"fail":"pass";if(l.crashed)f$1=true,t.push(`doctor remediation apply execution error: ${l.stderr||"unknown error"}`);else if(g==="fail")t.push("doctor remediation apply failed");else {X=L>0?L:T>0?T:1;let w=await S(["doctor","workspace","--json"],e$1);if(w.crashed)c$1="fail",f$1=true,t.push(`post-apply doctor execution error: ${w.stderr||"unknown error"}`);else if(w.exitCode!==0)c$1="fail",t.push("post-apply doctor workspace command failed");else {let i=j(w.stdout),P=i&&i.healthScore&&typeof i.healthScore=="object"?i.healthScore:{},h=Number(P.errors??0),y=Number(P.warnings??0);Number.isFinite(h)&&h>0?(c$1="fail",t.push(`post-apply doctor reports ${h} error(s)`)):Number.isFinite(y)&&y>0?c$1="warn":c$1="pass";}N>=0&&(o[N].status=c$1,o[N].summary=`doctor workspace post-apply status is ${c$1}`);let v=await S(["readiness","--json"],e$1);if(v.crashed)d="fail",f$1=true,t.push(`post-apply readiness execution error: ${v.stderr||"unknown error"}`);else if(v.exitCode!==0)d="fail",t.push("post-apply readiness command failed");else {let i=j(v.stdout),P=String(i?.overallStatus??"fail");if(d=re(P),typeof i?.evidencePath=="string"&&i.evidencePath.trim().length>0&&(F=i.evidencePath),d==="fail"){let h=Array.isArray(i?.blockingReasons)?i?.blockingReasons.filter(y=>typeof y=="string"):[];h.length>0?t.push(...h.map(y=>`post-apply readiness: ${y}`)):t.push("post-apply readiness overall status is fail");}}W>=0&&(o[W].status=d,o[W].summary=`readiness post-apply overall status is ${d}`);}o.push({name:"remediation-apply",status:g,durationMs:m,summary:g==="pass"?"safe remediation apply completed":"safe remediation apply failed"});}else o.push({name:"remediation-apply",status:"skipped",durationMs:0,summary:"remediation apply is skipped for this mode"});let le=Date.now(),x="pass",A="workspace test/build completed for selected projects";try{let s=await a$1({workspacePath:e$1,stage:"test",affected:true,since:r.since,parallel:r.parallel,maxWorkers:r.maxWorkers,strict:true,json:true,enforceGates:false});D=c(e$1,b.join(".workspai","reports",a$2)),await e(e$1,s),q=D;let l=oe(s);if(l==="fail")x="fail",A="workspace test stage failed for selected projects",t.push("workspace run test failed for selected projects");else {l==="warn"&&(x="warn",A="workspace test stage completed with warnings",n==="enforce"&&t.push("workspace run test reported warnings under enforce mode"));let m=await a$1({workspacePath:e$1,stage:"build",affected:true,since:r.since,parallel:r.parallel,maxWorkers:r.maxWorkers,strict:true,json:true,enforceGates:false});await e(e$1,m),Q=D;let g=oe(m);g==="fail"?(x="fail",A="workspace build stage failed for selected projects",t.push("workspace run build failed for selected projects")):g==="warn"&&(x="warn",A="workspace test/build completed with warnings",n==="enforce"&&t.push("workspace run test/build reported warnings under enforce mode"));}}catch(s){x="fail",A="workspace test/build orchestration failed",f$1=true,t.push(`workspace run orchestration error: ${s instanceof Error?s.message:String(s)}`);}let ce=Date.now()-le;o.push({name:"workspace-run-test-build",status:x,durationMs:ce,summary:A});let M=o.filter(s=>s.status==="warn").length,pe=o.filter(s=>s.status==="fail").length,_=n==="enforce"?o.some(s=>s.status==="warn"||s.status==="fail"):pe>0,C=[...new Set(t)],O=f$1||_?Math.max(1,C.length):0,ue=O>0?C:[],de=O===0?C:[],fe=Se(o),me=f$1||_?"blocked":M>0?"partial":"approved",ge=f$1?3:_?1:M>0?2:0,we=be({mode:n,executionError:f$1,blockers:C,hasWarnings:M>0}),Y=c(e$1,".workspai/reports"),he=b.join(Y,G),ke=b.join(Y,V),u={schemaVersion:"autopilot-release-v1",generatedAt:new Date().toISOString(),workspacePath:e$1,mode:n,summary:{releaseScore:fe,verdict:me,blockers:O,warnings:M,safeFixesApplied:X,manualActions:C.length,exitCode:ge},stages:o,blockingReasons:ue,warningReasons:de,nextActions:we,artifacts:{reportPath:he,aliasEvidencePath:ke,analyzeEvidencePath:H,readinessEvidencePath:F,workspaceRunEvidencePath:D,workspaceRunTestPath:q,workspaceRunBuildPath:Q},enterpriseControls:{jsonReady:true,evidencePath:`.workspai/reports/${G}`,aliasEvidencePath:`.workspai/reports/${V}`}};if(await g(e$1,`.workspai/reports/${G}`,u),await g(e$1,`.workspai/reports/${V}`,u),r.output&&await xe(b.resolve(r.output),u),!r.json){console.log(a$3.bold.cyan(`
3
- \u{1F680} Workspai Autopilot Release
4
- `)),console.log(a$3.bold(`Workspace: ${a$3.cyan(b.basename(e$1))}`)),console.log(a$3.gray(`Path: ${e$1}`)),console.log(a$3.white(`Mode: ${n}`)),console.log(a$3.white(`Verdict: ${u.summary.verdict==="approved"?a$3.green("approved"):u.summary.verdict==="partial"?a$3.yellow("partial"):a$3.red("blocked")}`)),console.log(a$3.white(`Release score: ${u.summary.releaseScore}`));for(let s of u.stages){let l=s.status==="pass"?a$3.green("PASS"):s.status==="warn"?a$3.yellow("WARN"):s.status==="skipped"?a$3.gray("SKIP"):a$3.red("FAIL");console.log(` - ${s.name}: ${l} ${s.summary} (${s.durationMs}ms)`);}if(u.blockingReasons.length>0){console.log(a$3.bold.red(`
5
- Blocking reasons:`));for(let s of u.blockingReasons)console.log(a$3.red(` - ${s}`));}if(u.warningReasons.length>0){console.log(a$3.bold.yellow(`
6
- Warning reasons:`));for(let s of u.warningReasons)console.log(a$3.yellow(` - ${s}`));}if(u.nextActions.length>0){console.log(a$3.bold(`
7
- Next actions:`));for(let s of u.nextActions)console.log(a$3.gray(` - ${s}`));}console.log(a$3.gray(`
8
- Report: ${u.artifacts.reportPath}`));}return u}export{G as a,V as b,Me as c};
@@ -1 +0,0 @@
1
- import {a as a$6}from'./chunk-HTYMXMQM.js';import {d,q,a as a$5}from'./chunk-DIPD72H4.js';import {i as i$1,h}from'./chunk-4KUIFXHM.js';import {i}from'./chunk-MER6ZBN2.js';import {c,b as b$2}from'./chunk-PRBVYW3T.js';import {a as a$4,k,b as b$3}from'./chunk-WYFPXTTS.js';import {a as a$2}from'./chunk-FXQJX34Z.js';import {g,f as f$1,c as c$1}from'./chunk-HDURFXW5.js';import {a as a$1}from'./chunk-GSWPGELT.js';import {a as a$3}from'./chunk-GZTYAEWX.js';import {b as b$1,a}from'./chunk-N7DV5L7C.js';import {p,o}from'./chunk-5XATWNME.js';import f from'path';import P from'fs-extra';import yt from'crypto';import {createRequire}from'module';var ft=new Set(["service","frontend","worker","library","infra","docs","test-suite","unknown"]);async function He(e){try{if(!await P.pathExists(e))return null;let t=await P.readJSON(e);return t&&typeof t=="object"?t:null}catch{return null}}async function mt(e){for(let t of e){let r=await He(t);if(r)return r}return null}function Te(e){if(typeof e!="string")return null;let t=e.trim().toLowerCase();return ft.has(t)?t:null}async function $e(e,t){let r=t??await mt(p(e,"project.json")),o=Te(r?.kind)??Te(r?.type);if(o)return o;let s=typeof r?.kit_name=="string"?r.kit_name:r?.kit,n=typeof r?.framework=="string"?r.framework:null,a=typeof r?.runtime=="string"?r.runtime:null,i=`${typeof s=="string"?s:""} ${n??""} ${a??""}`.trim().toLowerCase();if(/\b(frontend|nextjs|next\.js|react|vue|svelte|vite|angular|astro|remix|nuxt)\b/.test(i))return "frontend";if(/\b(fastapi|nestjs|springboot|spring boot|gofiber|gogin|dotnet|webapi|django|flask|express|fastify|python|node|java|go|rust|php|ruby|elixir)\b/.test(i))return "service";let c=await He(f.join(e,"package.json"));if(c){let d={...c.dependencies??{},...c.devDependencies??{}},l=c.scripts??{},p=Object.values(l).filter(u=>typeof u=="string").join(" ").toLowerCase();if(d.next||d.react||d.vue||d.svelte||d.vite||d["@angular/core"]||p.includes("next ")||p.includes("vite "))return "frontend";if(c.private===true&&!d.express&&!d["@nestjs/core"])return "library"}return await P.pathExists(f.join(e,"Dockerfile"))||await P.pathExists(f.join(e,"docker-compose.yml"))||await P.pathExists(f.join(e,"terraform.tf"))?"infra":"service"}var gt=new Set(c().map(e=>e.id)),ht=[...i().map(e=>({id:e.kitId,aliases:[...e.aliases],ecosystem:e.framework,status:"available",canExecuteCreate:true,officialCommands:[e.commandDisplay("<name>",{skipGit:false,skipInstall:false})],adoptAfterCreate:true})),{id:"wordpress-site",aliases:["wordpress","wordpress-site","wp","wp-site"],ecosystem:"wordpress",status:"planned",canExecuteCreate:false,officialCommands:["wp core download","wp config create","wp db create","wp core install"],adoptAfterCreate:true},{id:"wordpress-block",aliases:["wordpress-block","wp-block","gutenberg-block"],ecosystem:"wordpress",status:"planned",canExecuteCreate:false,officialCommands:["npx @wordpress/create-block@latest <slug>"],adoptAfterCreate:true},{id:"laravel",aliases:["laravel","php-laravel"],ecosystem:"php",status:"planned",canExecuteCreate:false,officialCommands:["composer create-project laravel/laravel <name>"],adoptAfterCreate:true},{id:"symfony",aliases:["symfony","php-symfony"],ecosystem:"php",status:"planned",canExecuteCreate:false,officialCommands:["composer create-project symfony/skeleton <name>"],adoptAfterCreate:true},{id:"rails",aliases:["rails","ruby-on-rails","ruby-rails"],ecosystem:"ruby",status:"planned",canExecuteCreate:false,officialCommands:["rails new <name>"],adoptAfterCreate:true}],V=new Map;for(let e of ht){V.set(e.id,e);for(let t of e.aliases)V.set(t,e);}var kt=new Set(["php","ruby","rust","elixir","clojure","scala","kotlin","unknown"]);function F(e){return e?.trim().toLowerCase()||void 0}function Ve(e){let t=F(e.kitId)??F(e.framework)??F(e.runtime)??"unknown";if(e.projectExists)return {lane:"existing",status:"available",canExecuteCreate:false,requested:t,reason:"Existing projects enter Workspace Intelligence through adopt/import."};let r=e.kitId?b$2(e.kitId):void 0;if(r&&gt.has(r))return {lane:"native",status:"available",canExecuteCreate:true,requested:t,resolved:r,reason:"Workspai owns the create contract, project marker, registry, doctor, and workspace model path."};let o=V.get(t)??V.get(F(e.framework)??"")??V.get(F(e.runtime)??"");if(o)return {lane:"official",status:o.status,canExecuteCreate:o.canExecuteCreate,requested:t,resolved:o.id,officialCommands:o.officialCommands,fallbackLane:o.canExecuteCreate?void 0:"existing",reason:o.status==="available"?"Workspai runs the official ecosystem generator, then registers the project in Workspace Intelligence.":"Official generator support is planned but not enabled; use adopt/import until Workspai owns the post-create contract."};let s=F(e.runtime);return s&&kt.has(s)?{lane:"existing",status:"available",canExecuteCreate:false,requested:t,resolved:s,reason:"Runtime can be governed through Workspace Intelligence, but native create is not supported."}:{lane:"existing",status:"available",canExecuteCreate:false,requested:t,reason:"No native create contract is available; use adopt/import to enter Workspace Intelligence."}}function br(e){return !e.canExecuteCreate&&(e.lane==="official"||e.lane==="existing"&&e.resolved!==void 0)}var Ke="workspace-dependency-graph.v1",Be=["code-import","package-dep","event-pub-sub","service-dependsOn","shared-resource"];var Wr="rapidkit-freshness-metadata-v1";function le(e){if(Array.isArray(e))return e.map(t=>le(t));if(e&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=le(e[r]);return t}return e}function wt(e){return JSON.stringify(le(e))}function M(e){return yt.createHash("sha256").update(wt(e)).digest("hex")}var Le=".workspai/workspace-graph.overrides.json",vt=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs"]),bt=new Set([".git",".hg",".svn",".workspai",".rapidkit",".venv","node_modules","dist","build","out","target","coverage","htmlcov",".next",".turbo",".cache"]),Ue=600,Je=5,jt=256*1024,ze={inferred:1,contract:2,manual:3};function Ct(e){return e.split(f.sep).join("/")}function Z(e,t){return Ct(f.relative(e,t)||".")}function qe(e){let t=new Map;for(let r of e.projects)t.has(r.name)||t.set(r.name,{id:r.name,path:r.path,...r.runtime?{runtime:r.runtime}:{},...r.framework?{framework:r.framework}:{},...r.kind?{kind:r.kind}:{}});return [...t.values()].sort((r,o)=>r.id.localeCompare(o.id))}function Xe(e,t){let r=new Map,o=new Map;for(let n of t.projects){if(r.has(n.name))continue;let a=n.absolutePath?f.resolve(n.absolutePath):f.resolve(e,n.path);r.set(n.name,a),o.has(a)||o.set(a,n.name);}let s=[...o.entries()].map(([n,a])=>({dir:n,id:a})).sort((n,a)=>a.dir.length-n.dir.length||n.dir.localeCompare(a.dir));return {idToDir:r,dirToId:o,sortedDirs:s}}function ee(e,t){let r=f.resolve(t);for(let{dir:o,id:s}of e.sortedDirs)if(r===o||r.startsWith(`${o}${f.sep}`))return s;return null}async function me(e){try{if(!await P.pathExists(e))return null;let t=await P.readJSON(e);return t&&typeof t=="object"&&!Array.isArray(t)?t:null}catch{return null}}async function he(e){try{return await P.pathExists(e)?await P.readFile(e,"utf8"):null}catch{return null}}async function Ye(e,t){let r=[],o=new Map;for(let[s,n]of t.idToDir.entries()){let a=await me(f.join(n,"package.json")),i=typeof a?.name=="string"?a.name.trim():"";i&&!o.has(i)&&o.set(i,s);}for(let[s,n]of t.idToDir.entries()){let a=await me(f.join(n,"package.json"));if(a){let i=["dependencies","devDependencies","peerDependencies","optionalDependencies"],c=new Set;for(let d of i){let l=a[d];if(!(!l||typeof l!="object"||Array.isArray(l)))for(let p of Object.keys(l)){let u=o.get(p);!u||u===s||c.has(u)||(c.add(u),r.push({from:s,to:u,kind:"package-dep",source:"inferred",confidence:"high",evidence:[{file:Z(e,f.join(n,"package.json")),detail:`declares dependency ${p}`}]}));}}}r.push(...await Et(e,t,s,n)),r.push(...await St(e,t,s,n));}return r}async function Et(e,t,r,o){let s=await he(f.join(o,"pyproject.toml"));if(!s)return [];let n=[],a=new Set,i=/path\s*=\s*["']([^"']+)["']/g,c;for(;(c=i.exec(s))!==null;){let d=ee(t,f.resolve(o,c[1]));!d||d===r||a.has(d)||(a.add(d),n.push({from:r,to:d,kind:"package-dep",source:"inferred",confidence:"high",evidence:[{file:Z(e,f.join(o,"pyproject.toml")),detail:`path dependency ${c[1]}`}]}));}return n}async function St(e,t,r,o){let s=await he(f.join(o,"go.mod"));if(!s)return [];let n=[],a=new Set,i=/replace\s+\S+\s+=>\s+(\.[^\s]+)/g,c;for(;(c=i.exec(s))!==null;){let d=ee(t,f.resolve(o,c[1]));!d||d===r||a.has(d)||(a.add(d),n.push({from:r,to:d,kind:"package-dep",source:"inferred",confidence:"high",evidence:[{file:Z(e,f.join(o,"go.mod")),detail:`go.mod replace ${c[1]}`}]}));}return n}async function Pt(e,t){let r=[],o=[e];for(;o.length>0&&r.length<t;){let s=o.shift();if(!s)continue;let n=[];try{n=await P.readdir(s,{withFileTypes:true});}catch{continue}let a=[],i=[];for(let c of n)if(c.isDirectory()){if(bt.has(c.name)||c.name.startsWith("."))continue;a.push(f.join(s,c.name));}else c.isFile()&&vt.has(f.extname(c.name))&&i.push(f.join(s,c.name));i.sort((c,d)=>c.localeCompare(d)),a.sort((c,d)=>c.localeCompare(d));for(let c of i){if(r.length>=t)break;r.push(c);}o.push(...a);}return r}var Wt=[/\bfrom\s+["']([^"']+)["']/g,/\bimport\s+["']([^"']+)["']/g,/\bimport\s*\(\s*["']([^"']+)["']\s*\)/g,/\brequire\s*\(\s*["']([^"']+)["']\s*\)/g];function xt(e){let t=new Set;for(let r of Wt){r.lastIndex=0;let o;for(;(o=r.exec(e))!==null;){let s=o[1];s.startsWith(".")&&t.add(s);}}return [...t]}async function ge(e,t,r,o){let s=new Map;for(let[n,a]of t.idToDir.entries()){if(o&&!o.has(n))continue;let i=await Pt(a,r);for(let c of i){let d=await P.stat(c).catch(()=>null);if(!d||d.size>jt)continue;let l=await he(c);if(l)for(let p of xt(l)){let u=f.resolve(f.dirname(c),p),m=ee(t,u);if(!m||m===n)continue;let E=`${n}\0${m}`,w=s.get(E);w||(w={from:n,to:m,evidence:[]},s.set(E,w)),w.evidence.length<Je&&w.evidence.push({file:Z(e,c),detail:`imports ${p}`});}}}return [...s.values()].map(n=>({from:n.from,to:n.to,kind:"code-import",source:"inferred",confidence:"medium",evidence:n.evidence}))}function Rt(e,t,r){let o=new Map;for(let s of r.projects){let n=At(e,t,s);n&&o.set(s.slug,n);}return o}function At(e,t,r){let o=[r.relativePath,r.externalPath].filter(s=>typeof s=="string"&&s.length>0);for(let s of o){let n=f.resolve(e,s),a=t.dirToId.get(n)??ee(t,n);if(a)return a}return t.idToDir.has(r.slug)?r.slug:null}function Qe(e,t,r){let o=[],s=Rt(e,t,r),n=b$3,a=new Map,i=new Map;for(let c of r.projects){let d=s.get(c.slug);if(!d)continue;let l=c.contracts??{publishes:[],consumes:[],dependsOn:[]};for(let p of l.dependsOn??[]){let u=s.get(p);!u||u===d||o.push({from:d,to:u,kind:"service-dependsOn",source:"contract",confidence:"high",evidence:[{file:n,detail:`dependsOn ${p}`}]});}for(let p of l.publishes??[])a.has(p)||a.set(p,new Set),a.get(p)?.add(d);for(let p of l.consumes??[])i.has(p)||i.set(p,new Set),i.get(p)?.add(d);}for(let[c,d]of a.entries()){let l=i.get(c);if(l)for(let p of l)for(let u of d)p!==u&&o.push({from:p,to:u,kind:"event-pub-sub",source:"contract",confidence:"high",evidence:[{file:n,detail:`consumes event ${c}`}]});}return o.push(...It(r,s)),o}function ue(e){return e.toLowerCase().replace(/[^a-z0-9]/g,"")}function It(e,t){let r=[],o=e.projects.map(s=>({project:s,id:t.get(s.slug)})).filter(s=>!!s.id).filter(s=>ue(s.project.slug).length>=3);for(let s of e.projects){let n=t.get(s.slug);if(!n)continue;let a=s.contracts?.env??[];if(a.length===0)continue;let i=new Set;for(let c of a){let d=ue(c);for(let l of o)l.id===n||i.has(l.id)||!(d.includes(ue(l.project.slug))&&(l.project.ports?.length??0)>0)||(i.add(l.id),r.push({from:n,to:l.id,kind:"shared-resource",source:"inferred",confidence:"low",evidence:[{file:b$3,detail:`env ${c} references ${l.project.slug}`}]}));}}return r}async function Ze(e,t){let r=await me(f.join(e,Le)),o=Array.isArray(r?.edges)?r?.edges:[],s=[],n=new Set(Be);for(let a of o){if(!a||typeof a!="object"||Array.isArray(a))continue;let i=a,c=typeof i.from=="string"?i.from:"",d=typeof i.to=="string"?i.to:"",l=typeof i.kind=="string"?i.kind:"";if(!t.has(c)||!t.has(d)||c===d||!n.has(l))continue;let p=Array.isArray(i.evidence)?i.evidence.map(u=>u&&typeof u=="object"&&typeof u.file=="string"?{file:u.file,...typeof u.detail=="string"?{detail:u.detail}:{}}:null).filter(u=>!!u):[];s.push({from:c,to:d,kind:l,source:"manual",confidence:"high",evidence:p.length>0?p:[{file:Le,detail:"manual edge"}]});}return s}function Ft(e){return `${e.from}\0${e.to}\0${e.kind}`}function Mt(e){let t=new Set,r=[];for(let o of e){let s=`${o.file}\0${o.detail??""}`;t.has(s)||(t.add(s),r.push(o));}return r.sort((o,s)=>o.file.localeCompare(s.file)||(o.detail??"").localeCompare(s.detail??"")).slice(0,Je)}function Dt(e){let t=new Map;for(let r of e){let o=Ft(r),s=t.get(o);if(!s){t.set(o,{...r,evidence:[...r.evidence]});continue}let n=ze[s.source],a=ze[r.source];a>n?t.set(o,{...r,evidence:[...r.evidence,...s.evidence]}):a===n&&s.evidence.push(...r.evidence);}return [...t.values()].map(r=>({from:r.from,to:r.to,kind:r.kind,source:r.source,confidence:r.confidence,evidence:Mt(r.evidence)})).sort((r,o)=>r.from.localeCompare(o.from)||r.to.localeCompare(o.to)||r.kind.localeCompare(o.kind)||r.source.localeCompare(o.source))}function fe(e){return Math.round(e*1e3)/1e3}function Gt(e){return Math.max(0,Math.min(100,Math.round(e)))}function Ot(e){return e>=75?"critical":e>=50?"high":e>=20?"medium":"low"}function _t(e){return e==="critical"||e==="high"?"strict":e==="medium"?"elevated":"normal"}function Nt(e,t){let r=a$6({nodes:e,edges:t}),o=new Map;for(let s of e){let n=r.byId.get(s.id)??{fanIn:0,fanOut:0,reach:0,betweenness:0,isHotspot:false},a=t.filter(m=>m.from===s.id||m.to===s.id),i=a.filter(m=>m.source==="contract"||m.source==="manual").length,c=a.filter(m=>m.confidence==="low").length,d=[],l=n.reach*20+n.fanIn*14+n.fanOut*8+Math.min(20,n.betweenness*4)+i*8;n.isHotspot&&(l+=24,d.push("Critical-path hotspot in dependency graph")),n.reach>0&&d.push(`Change reaches ${n.reach} dependent project(s)`),n.fanIn>0&&d.push(`${n.fanIn} direct dependent project(s)`),n.fanOut>0&&d.push(`${n.fanOut} direct dependency project(s)`),i>0&&d.push(`${i} contract/manual edge(s)`),c>0&&d.push(`${c} low-confidence inferred edge(s) need review`),a.length===0&&d.push("No dependency evidence connected to this project yet");let p=Gt(l),u=Ot(p);o.set(s.id,{weight:u,score:p,verificationPriority:_t(u),reasons:d.slice(0,5),centrality:{fanIn:n.fanIn,fanOut:n.fanOut,reach:n.reach,betweenness:n.betweenness,isHotspot:n.isHotspot}});}return o}function Tt(e,t){let r=Nt(e,t);return e.map(o=>({...o,operationalProfile:r.get(o.id)}))}function Ht(e,t){let r=new Set;for(let c of t)r.add(c.from),r.add(c.to);let o=e.length,s=t.length,n=e.filter(c=>r.has(c.id)).length,a=Math.max(0,o-n),i=a$6({nodes:e,edges:t});return {nodeCount:o,edgeCount:s,inferredEdges:t.filter(c=>c.source==="inferred").length,contractEdges:t.filter(c=>c.source==="contract").length,manualEdges:t.filter(c=>c.source==="manual").length,authoritativeEdges:t.filter(c=>c.source==="contract"||c.source==="manual").length,lowConfidenceEdges:t.filter(c=>c.confidence==="low").length,orphanCount:a,connectedNodeCount:n,density:fe(o>1?s/(o*(o-1)):0),edgeCoverageRatio:fe(o>0?n/o:1),evidenceCoverageRatio:fe(s>0?t.filter(c=>c.evidence.length>0).length/s:1),hotspotCount:i.hotspots.length,hasCycle:Vt(e,t)}}function $t(e,t,r){let o=[],s=e.filter(n=>!t.some(a=>a.from===n.id||a.to===n.id)).map(n=>n.id).sort((n,a)=>n.localeCompare(a));return r.nodeCount===0&&o.push({code:"graph.empty",severity:"info",message:"Workspace model has no projects, so dependency reasoning is unavailable.",recommendation:"Import, scaffold, or register projects before relying on graph-aware impact."}),r.nodeCount>1&&r.edgeCount===0?o.push({code:"graph.edges.missing",severity:"warning",message:"Projects were detected, but no inter-project dependency edges were found.",recommendation:"Run graph explain, add workspace contract relationships, or define manual graph overrides for operational dependencies that code imports cannot reveal.",nodeIds:s}):r.orphanCount>0&&o.push({code:"graph.orphans.detected",severity:"warning",message:`${r.orphanCount} project(s) have no dependency evidence connected to the graph.`,recommendation:"Review isolated projects and add package, contract, or manual edges when they participate in release-critical flows.",nodeIds:s.slice(0,12)}),r.lowConfidenceEdges>0&&o.push({code:"graph.low_confidence_edges",severity:"info",message:`${r.lowConfidenceEdges} inferred edge(s) are low confidence.`,recommendation:"Promote important low-confidence relationships to workspace contract or manual overrides."}),r.edgeCount>0&&r.evidenceCoverageRatio<1&&o.push({code:"graph.evidence.partial",severity:"warning",message:"Some dependency edges do not include file-level evidence.",recommendation:"Attach evidence to manual overrides so agents can audit why a relationship exists."}),r.hasCycle&&o.push({code:"graph.cycle.detected",severity:"error",message:"The dependency graph contains at least one directed cycle.",recommendation:"Break the cycle or document the relationship explicitly before using graph-aware release gates."}),o.sort((n,a)=>{let i={error:0,warning:1,info:2};return i[n.severity]-i[a.severity]||n.code.localeCompare(a.code)})}function Vt(e,t){let r=new Map;for(let c of e)r.set(c.id,[]);for(let c of t)r.has(c.from)||r.set(c.from,[]),r.get(c.from)?.push(c.to);let o=0,s=1,n=2,a=new Map;for(let c of r.keys())a.set(c,o);let i=c=>{let d=[{id:c,index:0}];for(a.set(c,s);d.length>0;){let l=d[d.length-1],p=r.get(l.id)??[];if(l.index>=p.length){a.set(l.id,n),d.pop();continue}let u=p[l.index];l.index+=1;let m=a.get(u)??o;if(m===s)return true;m===o&&(a.set(u,s),d.push({id:u,index:0}));}return false};for(let c of [...r.keys()].sort())if(a.get(c)===o&&i(c))return true;return false}function et(e,t,r,o){let s=Dt(r.filter(c=>t.has(c.from)&&t.has(c.to))),n=Tt(e,s),a=Ht(e,s),i=$t(e,s,a);return {schemaVersion:Ke,generatedAt:(o??new Date).toISOString(),nodes:n,edges:s,stats:a,...i.length>0?{diagnostics:i}:{}}}async function tt(e){let t=f.resolve(e.workspacePath),r=e.maxImportFilesPerProject??Ue,o=qe(e.model),s=new Set(o.map(i=>i.id)),n=Xe(t,e.model),a=[];return a.push(...await Ye(t,n)),a.push(...await ge(t,n,r)),e.contract&&a.push(...Qe(t,n,e.contract)),a.push(...await Ze(t,s)),et(o,s,a,e.now)}async function rt(e){let t=f.resolve(e.workspacePath),r=e.maxImportFilesPerProject??Ue,o=qe(e.model),s=new Set(o.map(i=>i.id)),n=Xe(t,e.model),a=[];if(a.push(...await Ye(t,n)),e.structuralChange)a.push(...await ge(t,n,r));else {a.push(...await ge(t,n,r,e.changedProjectIds));for(let i of e.previousGraph.edges)i.kind==="code-import"&&i.source==="inferred"&&!e.changedProjectIds.has(i.from)&&s.has(i.from)&&s.has(i.to)&&a.push({from:i.from,to:i.to,kind:"code-import",source:"inferred",confidence:i.confidence,evidence:i.evidence});}return e.contract&&a.push(...Qe(t,n,e.contract)),a.push(...await Ze(t,s)),et(o,s,a,e.now)}var ye="workspace-model-cache.v1",ke=".workspai/cache/workspace-model.v1.json",nt=["package.json","pyproject.toml","requirements.txt","go.mod","go.sum","pom.xml","build.gradle","build.gradle.kts","Cargo.toml","composer.json","Gemfile","workspai.project.json",".workspai/project.json",".workspai/context.json","rapidkit.project.json",".rapidkit/project.json",".rapidkit/context.json"],ot=[".workspai/workspace.contract.json",".workspai/workspace.json","workspai.workspace.json",".workspai/policies.yml",".workspai/policies.yaml",".rapidkit/workspace.contract.json",".rapidkit/workspace.json","rapidkit.workspace.json",".rapidkit/policies.yml",".rapidkit/policies.yaml"],Lt=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs"]),zt=new Set([".git",".workspai",".rapidkit","node_modules","dist","build","out","target","coverage",".next",".turbo",".cache",".venv"]),Ut=1500,K=null;function we(){if(K)return K;try{K=createRequire(import.meta.url)("../package.json")?.version??"0.0.0";}catch{K="0.0.0";}return K}async function te(e){try{let t=await P.readFile(e);return yt.createHash("sha256").update(t).digest("hex")}catch{return null}}async function Jt(e){let t={};for(let s of nt){let n=await te(f.join(e,s));n&&(t[s]=n);}let r=[],o=[e];for(;o.length>0&&r.length<Ut;){let s=o.shift();if(!s)continue;let n=[];try{n=await P.readdir(s,{withFileTypes:true});}catch{continue}let a=[];for(let i of n)if(i.isDirectory()){if(zt.has(i.name)||i.name.startsWith("."))continue;a.push(f.join(s,i.name));}else if(i.isFile()&&Lt.has(f.extname(i.name))){let c=f.join(s,i.name),d=await P.stat(c).catch(()=>null);if(d){let l=f.relative(e,c).split(f.sep).join("/");r.push(`${l}:${d.size}:${Math.round(d.mtimeMs)}`);}}a.sort((i,c)=>i.localeCompare(c)),o.push(...a);}return r.sort((s,n)=>s.localeCompare(n)),M({manifests:t,source:r})}async function re(e,t){let r=f.resolve(e),o={},s=[...new Set(t.map(n=>f.relative(r,f.resolve(n)).split(f.sep).join("/")))].sort((n,a)=>n.localeCompare(a));for(let n of s)o[n]=await Jt(f.join(r,n));return o}async function ne(e){let t=f.resolve(e),r={};for(let o of ot){let s=await te(f.join(t,o));s&&(r[o]=s);}return r}async function oe(e){let t=f.resolve(e.workspacePath),r=[...new Set(e.projectPaths.map(n=>f.relative(t,f.resolve(n)).split(f.sep).join("/")))].sort((n,a)=>n.localeCompare(a)),o=[];for(let n of r){let a={};for(let i of nt){let c=await te(f.join(t,n,i));c&&(a[i]=c);}o.push({project:n,manifests:a});}let s={};for(let n of ot){let a=await te(f.join(t,n));a&&(s[n]=a);}return M({cacheSchema:ye,cliVersion:e.cliVersion,flags:e.flags,workspaceJson:e.workspaceJson??null,marker:e.marker??null,projects:o,workspaceFiles:s})}async function ve(e){let t=await f$1(e,ke)??c$1(e,ke);try{if(!await P.pathExists(t))return null;let r=await P.readJson(t);return !r||r.schemaVersion!==ye||typeof r.inputsHash!="string"||typeof r.cliVersion!="string"||!r.model?null:r}catch{return null}}async function se(e,t){let r={schemaVersion:ye,...t};return g(e,ke,r)}var st="rapidkit-fact-freshness-v1",L={durable:720*60*60,derived:10080*60,evidenceBacked:1440*60,live:300,verifyBeforeUse:1440*60};function qt(e){switch(e){case "durable":return L.durable;case "derived":return L.derived;case "evidence-backed":return L.evidenceBacked;case "live":return L.live;case "verify-before-use":return L.verifyBeforeUse}}function Xt(e){if(e.status)return e.status;if(e.ttlSeconds===null)return "unknown";let t=Date.parse(e.generatedAt);if(!Number.isFinite(t))return "unknown";let r=t+e.ttlSeconds*1e3;return e.now.getTime()>r?"stale":"fresh"}function Yt(e){let t=e.now??new Date,r=e.generatedAt??t.toISOString(),o=Date.parse(r),s=Number.isFinite(o),n=s?r:t.toISOString(),a=e.ttlSeconds===void 0?qt(e.kind):e.ttlSeconds,i=Xt({generatedAt:n,ttlSeconds:a,status:e.status??(s?void 0:"unknown"),now:t}),c=Date.parse(n),d=a===null||!Number.isFinite(c)?void 0:new Date(c+a*1e3),l=e.verifyBeforeUse??(e.kind==="live"||e.kind==="verify-before-use"||e.category!=="structure"||i!=="fresh");return {schemaVersion:st,kind:e.kind,category:e.category,generatedAt:n,ttlSeconds:a,...d?{expiresAt:d.toISOString()}:{},status:i,verifyBeforeUse:l,...e.sourceArtifact?{sourceArtifact:e.sourceArtifact}:{},...e.sourcePath?{sourcePath:e.sourcePath}:{},inputsHash:e.inputsHash??M(e.value??null),reason:e.reason}}function v(e){return {id:e.id,label:e.label,scope:e.scope,value:e.value,...e.project?{project:e.project}:{},freshness:Yt({...e.freshness,value:e.value})}}function at(e){let t=e.generatedAt??(e.now??new Date).toISOString(),r={durable:0,derived:0,"evidence-backed":0,live:0,"verify-before-use":0},o={structure:0,verification:0,state:0},s=0,n=0,a=0,i=0;for(let c of e.facts)r[c.freshness.kind]+=1,o[c.freshness.category]+=1,c.freshness.status==="stale"&&(s+=1),c.freshness.status==="unknown"&&(n+=1),c.freshness.kind==="live"&&(a+=1),c.freshness.verifyBeforeUse&&(i+=1);return {schemaVersion:st,generatedAt:t,status:s>0?"stale":n>0?"unknown":"fresh",totalFacts:e.facts.length,staleFacts:s,unknownFacts:n,liveFacts:a,verifyBeforeUseFacts:i,byKind:r,byCategory:o}}var Qt=b$1.model,ct=a.model,Zt=["package.json","pyproject.toml","requirements.txt","go.mod","pom.xml","build.gradle","build.gradle.kts","Cargo.toml","composer.json","Gemfile","mix.exs","deno.json","deno.jsonc","bun.lock","bun.lockb","deps.edn","project.clj","build.sbt","docker-compose.yml","docker-compose.yaml","terraform.tf"],er=new Set([".git",".hg",".svn",".workspai",".rapidkit",".venv","node_modules","dist","build","target","coverage","htmlcov",".next",".turbo"]);function dt(e,t){return (f.relative(e,t)||".").split(f.sep).join("/")}async function pt(e){try{if(!await P.pathExists(e))return null;let t=await P.readJSON(e);return t&&typeof t=="object"?t:null}catch{return null}}async function tr(e,t){for(let r of t)if(await P.pathExists(f.join(e,r)))return true;return false}function be(e){let t=Number.parseInt(process.env.RAPIDKIT_WORKSPACE_MODEL_SCAN_DEPTH??"",10),r=typeof e=="number"&&Number.isFinite(e)?e:Number.isFinite(t)?t:4;return Math.min(12,Math.max(1,Math.trunc(r)))}async function je(e,t){let r=f.resolve(e),o=[{dirPath:r,depth:0}],s=new Set,n=new Set;for(;o.length>0;){let a=o.shift();if(!a)continue;let i=f.resolve(a.dirPath);if(n.has(i))continue;if(n.add(i),i!==r&&await tr(i,Zt)){s.add(i);continue}if(a.depth>=t)continue;let c=[];try{c=await P.readdir(i,{withFileTypes:true});}catch{continue}for(let d of c)!d.isDirectory()||er.has(d.name)||d.name.startsWith(".")&&d.name!==".config"||o.push({dirPath:f.join(i,d.name),depth:a.depth+1});}return Array.from(s).sort((a,i)=>a.localeCompare(i))}function Ce(e){let t=new Set,r=[];for(let o of e){let s=f.resolve(o);t.has(s)||(t.add(s),r.push(s));}return r.sort((o,s)=>o.localeCompare(s))}function it(e,t){let r=e?.[t];return typeof r=="string"&&r.trim()?r.trim():void 0}function rr(e,t){return e?.[t]===true}function nr(e,t,r){let o=e?.frontend&&typeof e.frontend=="object"&&!Array.isArray(e.frontend)?e.frontend:void 0,s=it(o,"generator"),n=it(o,"command_display"),a=typeof t=="string"&&t.startsWith("frontend.");if(!(!s&&!a))return {...s?{id:s}:{},...t?{kit:t}:{},displayName:r,source:rr(o,"official_generator")?"official-generator":"metadata",...n?{commandDisplay:n}:{}}}async function or(e){let t=[".workspai/project.json",".workspai/context.json",".rapidkit/project.json",".rapidkit/context.json","package.json","pyproject.toml","requirements.txt","go.mod","pom.xml","build.gradle","build.gradle.kts","Cargo.toml","composer.json","Gemfile","mix.exs","deno.json","Dockerfile","docker-compose.yml","README.md"],r=[];for(let o of t)await P.pathExists(f.join(e,o))&&r.push(o);return r}async function S(e,t,r,o=t){let s=await f$1(e,t),n=s!==null,a={path:o.split(f.sep).join("/"),exists:n};if(s&&r){let i=await pt(s);typeof i?.generatedAt=="string"&&(a.generatedAt=i.generatedAt);let c=i?.status??i?.result??i?.verdict;typeof c=="string"&&(a.status=c);}return a}async function sr(e,t,r){let o=dt(e,t),s=".workspai/reports",n=c=>S(t,`${s}/${c}`,r,`${o}/${s}/${c}`),a=await n("doctor-project-last-run.json");return {doctor:a?.exists===true?a:await n("doctor-last-run.json"),remediationPlan:await n("doctor-remediation-plan-last-run.json"),fixResult:await n("doctor-fix-result-last-run.json"),analyze:await n("analyze-last-run.json"),readiness:await n("release-readiness-last-run.json")}}async function ar(e,t,r){let o=d(t),s=i$1(t,o),n=q(t),a=a$5(s.runtime),i=await $e(t,o),c=typeof o?.name=="string"&&o.name.trim()?o.name.trim():f.basename(t),d$1=typeof o?.kit_name=="string"?o.kit_name:typeof o?.kit=="string"?o.kit:void 0,l=typeof o?.engine=="string"?o.engine:n.engine!=="unknown"?n.engine:void 0,p=nr(o,d$1,s.displayName),u=Ve({kitId:d$1,framework:s.key,runtime:s.runtime});return {name:c,path:dt(e,t),...r.includeAbsolutePaths?{absolutePath:t}:{},kind:i,runtime:s.runtime,runtimeCandidates:h(t),framework:s.key,frameworkDisplayName:s.displayName,confidence:s.confidence,detectionSource:s.source,supportTier:s.supportTier,runtimeSupportTier:a.tier,runtimeDoctorSupport:a.doctorSupport,moduleSupport:n.moduleSupport,...d$1?{kit:d$1}:{},...l?{engine:l}:{},...p?{generator:p}:{},createCapability:u,commands:{supported:n.supportedCommands,unsupported:n.unsupportedCommands,global:n.globalCommands,fleetStages:n.fleetStages,localOnly:n.localOnlyCommands,map:n.commandMap},importantFiles:await or(t),evidence:await sr(e,t,r.includeEvidence),provenance:{path:"filesystem discovery",runtime:s.source,framework:s.source,commands:"project command capability matrix",createCapability:"create planner capability contract",evidence:"project .workspai/reports"}}}async function Ee(e){for(let t of o(e,"workspace.json")){let r=await pt(t);if(r)return r}return null}function ir(e){return e.length===0?"empty-workspace":e.some(t=>t.kind==="frontend")&&e.length>1?"full-stack-workspace":e.some(t=>t.kind==="frontend")?"frontend-workspace":e.length>1?"backend-platform":"backend-workspace"}function cr(e){let t=new Set;for(let r of e){let o=`${r.name} ${r.path}`.toLowerCase();for(let s of ["auth","billing","payment","notification","order","admin","report","search","analytics"])o.includes(s)&&t.add(s);}return Array.from(t).sort()}function C(e,t,r,o){return {severity:e,code:t,message:r,target:o}}function lt(e){let t=[];e.workspace.name.trim()||t.push(C("error","workspace.name.missing","Workspace name could not be resolved.","workspace")),e.workspace.type==="observed-workspace"&&t.push(C("warning","workspace.marker.missing","Workspace marker is missing; model is based on filesystem observation.","workspace.marker")),e.summary.projectCount===0&&t.push(C("warning","workspace.projects.empty","No project roots were detected in this workspace.","projects")),e.contracts.exists||t.push(C("warning","workspace.contract.missing","Workspace contract is missing; dependency and API edges may be incomplete.",e.contracts.workspaceContractPath));let r=new Map;for(let n of e.projects){let a=n.name.toLowerCase(),i=r.get(a)??[];i.push(n),r.set(a,i),n.importantFiles.length||t.push(C("warning","project.markers.missing",`Project ${n.name} has no important manifest files recorded.`,n.path)),n.runtime==="unknown"&&t.push(C("warning","project.runtime.unknown",`Project ${n.name} runtime could not be confidently detected.`,n.path));let c=["test","build"];for(let p of c)n.commands.supported.includes(p)&&n.commands.unsupported.includes(p)&&t.push(C("error","project.commands.conflict",`Project ${n.name} marks ${p} as both supported and unsupported.`,n.path));let d=new Set(n.commands.fleetStages),l=new Set(n.commands.localOnly);for(let p of n.commands.fleetStages){l.has(p)&&t.push(C("error","project.commands.scope-conflict",`Project ${n.name} marks ${p} as both fleet and local-only.`,n.path));let u=n.commands.map[p];(!u||u.status!=="supported"||u.fleetEligible!==true||u.executionScope!=="fleet")&&t.push(C("error","project.commands.fleet-stage-invalid",`Project ${n.name} advertises ${p} as a fleet stage without a supported fleet capability.`,n.path));}for(let p of n.commands.localOnly){let u=n.commands.map[p];(!u||u.status!=="supported"||u.executionScope!=="local-only"||u.fleetEligible===true)&&t.push(C("error","project.commands.local-only-invalid",`Project ${n.name} advertises ${p} as local-only without a matching local-only capability.`,n.path));}for(let p of Object.values(n.commands.map))p.status==="supported"&&(p.fleetEligible===true&&!d.has(p.command)&&t.push(C("error","project.commands.fleet-stage-missing",`Project ${n.name} capability ${p.command} is fleet-eligible but missing from fleetStages.`,n.path)),p.executionScope==="local-only"&&p.fleetEligible!==true&&!l.has(p.command)&&t.push(C("error","project.commands.local-only-missing",`Project ${n.name} capability ${p.command} is local-only but missing from localOnly commands.`,n.path)));}for(let[n,a]of r.entries())a.length>1&&t.push(C("error","project.name.duplicate",`Project name "${n}" is ambiguous across ${a.length} project roots.`,a.map(i=>i.path).join(", ")));let o=t.filter(n=>n.severity==="error").length,s=t.filter(n=>n.severity==="warning").length;return {status:o>0?"failed":s>0?"warning":"passed",errors:o,warnings:s,issues:t}}function gn(e){return lt(e)}function b(e){return e.join(".")}function dr(e,t){let r=ct,o=e.generatedAt,s=[v({id:"workspace.name",label:"Workspace name",scope:"workspace",value:e.workspace.name,freshness:{kind:"durable",category:"structure",generatedAt:o,now:t,sourceArtifact:r,sourcePath:b(["workspace","name"]),reason:"Workspace identity is structural metadata and changes through workspace setup."}}),v({id:"workspace.type",label:"Workspace type",scope:"workspace",value:e.identity.workspaceType,freshness:{kind:"derived",category:"structure",generatedAt:o,now:t,sourceArtifact:r,sourcePath:b(["identity","workspaceType"]),reason:"Workspace type is derived from the current project inventory."}}),v({id:"workspace.projectCount",label:"Project count",scope:"workspace",value:e.summary.projectCount,freshness:{kind:"derived",category:"structure",generatedAt:o,now:t,sourceArtifact:r,sourcePath:b(["summary","projectCount"]),reason:"Project count is derived from workspace discovery and should be refreshed after structural changes."}}),v({id:"workspace.runtimeFamilies",label:"Runtime families",scope:"workspace",value:e.identity.runtimeFamilies,freshness:{kind:"derived",category:"structure",generatedAt:o,now:t,sourceArtifact:r,sourcePath:b(["identity","runtimeFamilies"]),reason:"Runtime coverage is inferred from project surfaces."}}),v({id:"workspace.policyMode",label:"Workspace policy mode",scope:"policy",value:e.policies.mode,freshness:{kind:"durable",category:"structure",generatedAt:o,now:t,sourceArtifact:r,sourcePath:b(["policies","mode"]),reason:"Policy mode is configuration, not runtime state."}}),v({id:"workspace.contract.exists",label:"Workspace contract presence",scope:"contract",value:e.contracts.exists,freshness:{kind:"derived",category:"structure",generatedAt:o,now:t,sourceArtifact:r,sourcePath:b(["contracts","exists"]),reason:"Contract presence is derived from workspace files and should be refreshed before release gating."}})];e.graph&&s.push(v({id:"graph.edgeCount",label:"Dependency graph edge count",scope:"graph",value:e.graph.stats.edgeCount,freshness:{kind:"derived",category:"structure",generatedAt:e.graph.generatedAt??o,now:t,sourceArtifact:r,sourcePath:b(["graph","stats","edgeCount"]),reason:"Graph topology is derived from manifests, imports, and workspace contracts."}}),v({id:"graph.evidenceCoverageRatio",label:"Dependency graph evidence coverage",scope:"graph",value:e.graph.stats.evidenceCoverageRatio,freshness:{kind:"derived",category:"structure",generatedAt:e.graph.generatedAt??o,now:t,sourceArtifact:r,sourcePath:b(["graph","stats","evidenceCoverageRatio"]),reason:"Graph evidence coverage changes when dependency evidence or contract edges change."}}));for(let[n,a]of e.projects.entries()){let i=`projects[${n}]`,c={kind:"derived",category:"structure",generatedAt:o,now:t,sourceArtifact:r,reason:"Project facts are derived from workspace discovery, project metadata, and framework probes."};s.push(v({id:`project.${a.name}.kind`,label:`${a.name} kind`,scope:"project",project:a.name,value:a.kind,freshness:{...c,sourcePath:b([i,"kind"])}}),v({id:`project.${a.name}.runtime`,label:`${a.name} runtime`,scope:"project",project:a.name,value:a.runtime,freshness:{...c,sourcePath:b([i,"runtime"])}}),v({id:`project.${a.name}.framework`,label:`${a.name} framework`,scope:"project",project:a.name,value:a.frameworkDisplayName,freshness:{...c,sourcePath:b([i,"frameworkDisplayName"])}}),v({id:`project.${a.name}.supportTier`,label:`${a.name} support tier`,scope:"project",project:a.name,value:a.supportTier,freshness:{...c,sourcePath:b([i,"supportTier"])}}),v({id:`project.${a.name}.safeFleetStages`,label:`${a.name} safe fleet stages`,scope:"command",project:a.name,value:a.commands.fleetStages,freshness:{...c,sourcePath:b([i,"commands","fleetStages"]),reason:"Safe command availability is derived from package and project command surfaces."}}));for(let[d,l]of Object.entries(a.evidence))s.push(v({id:`project.${a.name}.evidence.${d}`,label:`${a.name} ${d} evidence`,scope:"evidence",project:a.name,value:l?{path:l.path,exists:l.exists,status:l.status??null}:{exists:false},freshness:{kind:l?.exists?"evidence-backed":"verify-before-use",category:"verification",generatedAt:l?.generatedAt??o,now:t,status:l?.exists?void 0:"unknown",sourceArtifact:l?.path??r,sourcePath:b([i,"evidence",d]),verifyBeforeUse:true,reason:l?.exists?"Evidence reports can expire or become stale after source changes.":"Missing evidence must be generated before this fact is used for verification."}}));}for(let[n,a]of Object.entries(e.evidence))s.push(v({id:`workspace.evidence.${n}`,label:`Workspace ${n} evidence`,scope:"evidence",value:a?{path:a.path,exists:a.exists,status:a.status??null}:null,freshness:{kind:a?.exists?"evidence-backed":"verify-before-use",category:"verification",generatedAt:a?.generatedAt??o,now:t,status:a?.exists?void 0:"unknown",sourceArtifact:a?.path??r,sourcePath:b(["evidence",n]),verifyBeforeUse:true,reason:a?.exists?"Workspace evidence can expire or become stale after project, dependency, or policy changes.":"Missing workspace evidence must be generated before release or repair decisions."}}));return s}async function ae(e){let t=f.resolve(e.workspacePath),r=e.includeAbsolutePaths===true,o$1=e.includeEvidence===true,s=be(e.observableScanDepth),n=e.now??new Date,[a$4,i,c,d,l]=await Promise.all([a$1(t),Ee(t),a$2(t),a$3(t,{descendIntoMatchedProjects:false}),je(t,s)]),p=Ce([...d,...l,...c.map(g=>f.isAbsolute(g.path)?g.path:f.join(t,g.path))]),u=e.reuseProjectModels,m=await Promise.all(p.map(g=>{if(u){let ut=f.relative(t,f.resolve(g)).split(f.sep).join("/"),Se=u.get(ut);if(Se)return Promise.resolve(Se)}return ar(t,g,{includeAbsolutePaths:r,includeEvidence:o$1})})),E=typeof i?.workspace_name=="string"?i.workspace_name:typeof i?.name=="string"?i.name:a$4?.name||f.basename(t),w=typeof i?.profile=="string"?i.profile:typeof i?.mode=="string"?i.mode:void 0,G=Array.from(new Set(m.map(g=>g.kind))).sort(),A=Array.from(new Set(m.map(g=>g.runtime))).sort(),ie=Array.from(new Set(m.map(g=>g.framework))).sort(),O=[".workspai/policies.yml",".workspai/policies.yaml",".rapidkit/policies.yml",".rapidkit/policies.yaml"].find(g=>P.existsSync(f.join(t,g))),_=o(t,"workspace.contract.json").map(g=>f.relative(t,g).split(f.sep).join("/")).find(g=>P.existsSync(f.join(t,g)))??".workspai/workspace.contract.json",W=await P.pathExists(f.join(t,_)),z={schemaVersion:Qt,generatedAt:n.toISOString(),workspace:{name:E,root:t,...w?{profile:w}:{},type:a$4?"rapidkit-workspace":"observed-workspace",...a$4?{marker:{createdBy:a$4.createdBy,version:a$4.version,createdAt:a$4.createdAt}}:{}},identity:{workspaceType:ir(m),surfaces:G,runtimeFamilies:A,businessCapabilities:cr(m)},discovery:{observableScanDepth:s},projects:m,policies:{mode:typeof i?.policy_mode=="string"?i.policy_mode:typeof i?.policyMode=="string"?i.policyMode:"warn",source:O??null,exists:!!O},contracts:{workspaceContractPath:_,exists:W,status:W?"known":"missing"},evidence:{doctor:await S(t,a.doctor,o$1),projectDoctor:await S(t,".workspai/reports/doctor-project-last-run.json",o$1),doctorRemediationPlan:await S(t,".workspai/reports/doctor-remediation-plan-last-run.json",o$1),artifactRemediationPlan:await S(t,".workspai/reports/artifact-remediation-plan-last-run.json",o$1),doctorFixResult:await S(t,".workspai/reports/doctor-fix-result-last-run.json",o$1),analyze:await S(t,a.analyze,o$1),readiness:await S(t,a.readiness,o$1),pipeline:await S(t,".workspai/reports/pipeline-last-run.json",o$1)},summary:{projectCount:m.length,runtimes:A,frameworks:ie,firstClassProjects:m.filter(g=>g.supportTier==="first-class").length,observedProjects:m.filter(g=>g.supportTier==="observed").length}},N=await fr(t,z,{contractExists:W,now:n,incrementalGraph:e.incrementalGraph}),T={...z,graph:N},y=lt(T),j=dr({...T},n),I=at({facts:j,generatedAt:n.toISOString(),now:n});return {...T,facts:j,factFreshness:I,validation:y}}async function hn(e){if(e.cache!==true)return {model:await ae(e),cache:"disabled"};let t=f.resolve(e.workspacePath),r=be(e.observableScanDepth),o=we(),[s,n,a,i,c]=await Promise.all([a$1(t),Ee(t),a$2(t),a$3(t,{descendIntoMatchedProjects:false}),je(t,r)]),d=Ce([...i,...c,...a.map(w=>f.isAbsolute(w.path)?w.path:f.join(t,w.path))]),l=await oe({workspacePath:t,cliVersion:o,flags:{includeAbsolutePaths:e.includeAbsolutePaths===true,includeEvidence:e.includeEvidence===true,observableScanDepth:r},projectPaths:d,workspaceJson:n,marker:s}),p=await ve(t);if(p&&p.cliVersion===o&&p.inputsHash===l)return {model:p.model,cache:"hit"};let u=await ae({...e}),[m,E]=await Promise.all([re(t,d),ne(t)]);return await se(t,{cliVersion:o,inputsHash:l,generatedAt:(e.now??new Date).toISOString(),model:u,projectSignatures:m,workspaceFileSignatures:E}),{model:u,cache:"miss"}}function pr(e,t){let r=new Set,o=new Set,s=new Set;for(let[n,a]of Object.entries(t))n in e?e[n]!==a&&r.add(n):o.add(n);for(let n of Object.keys(e))n in t||s.add(n);return {changed:r,added:o,removed:s}}function lr(e={},t={}){let r=new Set([...Object.keys(e),...Object.keys(t)]);for(let o of r)if(e[o]!==t[o])return false;return true}async function kn(e){let t=f.resolve(e.workspacePath),r=be(e.observableScanDepth),o=we(),s=e.now??new Date,[n,a,i,c,d]=await Promise.all([a$1(t),Ee(t),a$2(t),a$3(t,{descendIntoMatchedProjects:false}),je(t,r)]),l=Ce([...c,...d,...i.map(y=>f.isAbsolute(y.path)?y.path:f.join(t,y.path))]),p=await ve(t),u=async()=>{let y=await ae({...e}),j=await oe({workspacePath:t,cliVersion:o,flags:{includeAbsolutePaths:e.includeAbsolutePaths===true,includeEvidence:e.includeEvidence===true,observableScanDepth:r},projectPaths:l,workspaceJson:a,marker:n}),[I,g]=await Promise.all([re(t,l),ne(t)]);return await se(t,{cliVersion:o,inputsHash:j,generatedAt:s.toISOString(),model:y,projectSignatures:I,workspaceFileSignatures:g}),{model:y,mode:"full"}};if(!p||p.cliVersion!==o||!p.projectSignatures||!p.model?.graph)return u();let m=await ne(t);if(!lr(p.workspaceFileSignatures,m))return u();let E=await re(t,l),{changed:w,added:G,removed:A}=pr(p.projectSignatures,E);if(w.size===0&&G.size===0&&A.size===0)return {model:p.model,mode:"unchanged"};let ie=new Set([...w,...G]),O=new Map;for(let y of p.model.projects){let j=y.path.split(f.sep).join("/");!ie.has(j)&&!A.has(j)&&O.set(j,y);}let _=new Set,W=false;for(let y of p.model.projects){let j=y.path.split(f.sep).join("/");w.has(j)&&_.add(y.name);}let z=G.size>0||A.size>0,N=await ae({...e,reuseProjectModels:O,incrementalGraph:{previousGraph:p.model.graph,changedProjectIds:_,structuralChange:z||W}});for(let y of p.model.projects){let j=y.path.split(f.sep).join("/");if(!w.has(j))continue;let I=N.projects.find(g=>g.path.split(f.sep).join("/")===j);if(I&&I.name!==y.name){W=true;break}}if(W)return u();let T=await oe({workspacePath:t,cliVersion:o,flags:{includeAbsolutePaths:e.includeAbsolutePaths===true,includeEvidence:e.includeEvidence===true,observableScanDepth:r},projectPaths:l,workspaceJson:a,marker:n});return await se(t,{cliVersion:o,inputsHash:T,generatedAt:s.toISOString(),model:N,projectSignatures:E,workspaceFileSignatures:m}),{model:N,mode:"incremental"}}async function ur(e){try{let{contract:t}=await k({workspacePath:e});return t&&typeof t=="object"?t:null}catch{return null}}async function fr(e,t,r){let o=r.contractExists?await ur(e):null;try{return r.incrementalGraph?await rt({workspacePath:e,model:t,contract:o,now:r.now,previousGraph:r.incrementalGraph.previousGraph,changedProjectIds:r.incrementalGraph.changedProjectIds,structuralChange:r.incrementalGraph.structuralChange}):await tt({workspacePath:e,model:t,contract:o,now:r.now})}catch{let s=t.projects.map(n=>({id:n.name,path:n.path}));return {schemaVersion:"workspace-dependency-graph.v1",generatedAt:r.now.toISOString(),nodes:s,edges:[],stats:{nodeCount:s.length,edgeCount:0,inferredEdges:0,contractEdges:0,manualEdges:0,authoritativeEdges:0,lowConfidenceEdges:0,orphanCount:s.length,connectedNodeCount:0,density:0,edgeCoverageRatio:s.length>0?0:1,evidenceCoverageRatio:1,hotspotCount:0,hasCycle:false},diagnostics:s.length>1?[{code:"graph.inference.failed",severity:"warning",message:"Dependency graph inference failed; model contains projects but no dependency edges.",recommendation:"Run workspace model again after fixing graph inputs, or add workspace contract/manual graph overrides.",nodeIds:s.map(n=>n.id).sort((n,a)=>n.localeCompare(a))}]:void 0}}}async function yn(e,t){return g(t,ct,a$4(e))}export{Wr as a,M as b,st as c,v as d,at as e,Ve as f,br as g,$e as h,Ke as i,Qt as j,ct as k,gn as l,dr as m,ae as n,hn as o,kn as p,yn as q};