@tiangong-lca/cli 0.0.1
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.
- package/README.md +368 -0
- package/bin/tiangong.d.ts +1 -0
- package/bin/tiangong.js +32 -0
- package/dist/scripts/assert-full-coverage.js +77 -0
- package/dist/scripts/assert-full-coverage.js.map +1 -0
- package/dist/src/cli.js +2740 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/lib/artifacts.js +86 -0
- package/dist/src/lib/artifacts.js.map +1 -0
- package/dist/src/lib/dotenv.js +36 -0
- package/dist/src/lib/dotenv.js.map +1 -0
- package/dist/src/lib/env.js +139 -0
- package/dist/src/lib/env.js.map +1 -0
- package/dist/src/lib/errors.js +38 -0
- package/dist/src/lib/errors.js.map +1 -0
- package/dist/src/lib/flow-build-alias-map.js +299 -0
- package/dist/src/lib/flow-build-alias-map.js.map +1 -0
- package/dist/src/lib/flow-get.js +81 -0
- package/dist/src/lib/flow-get.js.map +1 -0
- package/dist/src/lib/flow-governance.js +164 -0
- package/dist/src/lib/flow-governance.js.map +1 -0
- package/dist/src/lib/flow-list.js +187 -0
- package/dist/src/lib/flow-list.js.map +1 -0
- package/dist/src/lib/flow-publish-reviewed-data.js +808 -0
- package/dist/src/lib/flow-publish-reviewed-data.js.map +1 -0
- package/dist/src/lib/flow-publish-version.js +541 -0
- package/dist/src/lib/flow-publish-version.js.map +1 -0
- package/dist/src/lib/flow-read.js +310 -0
- package/dist/src/lib/flow-read.js.map +1 -0
- package/dist/src/lib/flow-regen-product.js +1396 -0
- package/dist/src/lib/flow-regen-product.js.map +1 -0
- package/dist/src/lib/flow-remediate.js +821 -0
- package/dist/src/lib/flow-remediate.js.map +1 -0
- package/dist/src/lib/http.js +45 -0
- package/dist/src/lib/http.js.map +1 -0
- package/dist/src/lib/io.js +30 -0
- package/dist/src/lib/io.js.map +1 -0
- package/dist/src/lib/kb-search.js +83 -0
- package/dist/src/lib/kb-search.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-auto-build.js +1328 -0
- package/dist/src/lib/lifecyclemodel-auto-build.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-orchestrate.js +1556 -0
- package/dist/src/lib/lifecyclemodel-orchestrate.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-publish-build.js +296 -0
- package/dist/src/lib/lifecyclemodel-publish-build.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-publish-resulting-process.js +101 -0
- package/dist/src/lib/lifecyclemodel-publish-resulting-process.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-resulting-process.js +1152 -0
- package/dist/src/lib/lifecyclemodel-resulting-process.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-validate-build.js +238 -0
- package/dist/src/lib/lifecyclemodel-validate-build.js.map +1 -0
- package/dist/src/lib/llm.js +383 -0
- package/dist/src/lib/llm.js.map +1 -0
- package/dist/src/lib/process-auto-build.js +717 -0
- package/dist/src/lib/process-auto-build.js.map +1 -0
- package/dist/src/lib/process-batch-build.js +409 -0
- package/dist/src/lib/process-batch-build.js.map +1 -0
- package/dist/src/lib/process-get.js +66 -0
- package/dist/src/lib/process-get.js.map +1 -0
- package/dist/src/lib/process-publish-build.js +451 -0
- package/dist/src/lib/process-publish-build.js.map +1 -0
- package/dist/src/lib/process-resume-build.js +364 -0
- package/dist/src/lib/process-resume-build.js.map +1 -0
- package/dist/src/lib/publish.js +562 -0
- package/dist/src/lib/publish.js.map +1 -0
- package/dist/src/lib/remote.js +88 -0
- package/dist/src/lib/remote.js.map +1 -0
- package/dist/src/lib/review-flow.js +1110 -0
- package/dist/src/lib/review-flow.js.map +1 -0
- package/dist/src/lib/review-lifecyclemodel.js +727 -0
- package/dist/src/lib/review-lifecyclemodel.js.map +1 -0
- package/dist/src/lib/review-process.js +702 -0
- package/dist/src/lib/review-process.js.map +1 -0
- package/dist/src/lib/run.js +106 -0
- package/dist/src/lib/run.js.map +1 -0
- package/dist/src/lib/state-lock.js +150 -0
- package/dist/src/lib/state-lock.js.map +1 -0
- package/dist/src/lib/supabase-client.js +269 -0
- package/dist/src/lib/supabase-client.js.map +1 -0
- package/dist/src/lib/supabase-json-ordered-write.js +186 -0
- package/dist/src/lib/supabase-json-ordered-write.js.map +1 -0
- package/dist/src/lib/supabase-rest.js +138 -0
- package/dist/src/lib/supabase-rest.js.map +1 -0
- package/dist/src/lib/supabase-session.js +424 -0
- package/dist/src/lib/supabase-session.js.map +1 -0
- package/dist/src/lib/tidas-sdk-package-validator.js +493 -0
- package/dist/src/lib/tidas-sdk-package-validator.js.map +1 -0
- package/dist/src/lib/unstructured.js +203 -0
- package/dist/src/lib/unstructured.js.map +1 -0
- package/dist/src/lib/user-api-key.js +75 -0
- package/dist/src/lib/user-api-key.js.map +1 -0
- package/dist/src/lib/validation.js +191 -0
- package/dist/src/lib/validation.js.map +1 -0
- package/dist/src/main.js +38 -0
- package/dist/src/main.js.map +1 -0
- package/package.json +81 -0
package/README.md
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# TianGong LCA CLI
|
|
2
|
+
|
|
3
|
+
`tiangong-lca-cli` is the unified TianGong command-line entrypoint.
|
|
4
|
+
|
|
5
|
+
Current implementation choices:
|
|
6
|
+
|
|
7
|
+
- TypeScript on Node 24
|
|
8
|
+
- ship built JavaScript artifacts from `dist/`
|
|
9
|
+
- direct REST / Edge Function calls instead of MCP
|
|
10
|
+
- file-first input and JSON-first output
|
|
11
|
+
- one stable command surface for humans, agents, CI, and skills
|
|
12
|
+
- explicit npm production runtime dependencies only where they reduce long-term maintenance risk: native `@supabase/supabase-js` and direct `@tiangong-lca/tidas-sdk`
|
|
13
|
+
|
|
14
|
+
## MCP replacement policy
|
|
15
|
+
|
|
16
|
+
The CLI replaces MCP with two explicit strategies:
|
|
17
|
+
|
|
18
|
+
- strategy 1: call domain APIs directly through `tiangong-lca-edge-functions` (Edge Functions / REST)
|
|
19
|
+
- strategy 2: access Supabase directly without MCP through the native `@supabase/supabase-js` client, while keeping deterministic query semantics and stable artifact/report contracts inside the CLI
|
|
20
|
+
|
|
21
|
+
This prevents reintroducing a generic MCP transport layer into the CLI runtime.
|
|
22
|
+
|
|
23
|
+
## Implemented commands
|
|
24
|
+
|
|
25
|
+
- `tiangong doctor`
|
|
26
|
+
- `tiangong search flow`
|
|
27
|
+
- `tiangong search process`
|
|
28
|
+
- `tiangong search lifecyclemodel`
|
|
29
|
+
- `tiangong process get`
|
|
30
|
+
- `tiangong process auto-build`
|
|
31
|
+
- `tiangong process resume-build`
|
|
32
|
+
- `tiangong process publish-build`
|
|
33
|
+
- `tiangong process batch-build`
|
|
34
|
+
- `tiangong lifecyclemodel auto-build`
|
|
35
|
+
- `tiangong lifecyclemodel validate-build`
|
|
36
|
+
- `tiangong lifecyclemodel publish-build`
|
|
37
|
+
- `tiangong lifecyclemodel build-resulting-process`
|
|
38
|
+
- `tiangong lifecyclemodel publish-resulting-process`
|
|
39
|
+
- `tiangong lifecyclemodel orchestrate`
|
|
40
|
+
- `tiangong review process`
|
|
41
|
+
- `tiangong review flow`
|
|
42
|
+
- `tiangong review lifecyclemodel`
|
|
43
|
+
- `tiangong flow get`
|
|
44
|
+
- `tiangong flow list`
|
|
45
|
+
- `tiangong flow remediate`
|
|
46
|
+
- `tiangong flow publish-version`
|
|
47
|
+
- `tiangong flow publish-reviewed-data`
|
|
48
|
+
- `tiangong flow build-alias-map`
|
|
49
|
+
- `tiangong flow scan-process-flow-refs`
|
|
50
|
+
- `tiangong flow plan-process-flow-repairs`
|
|
51
|
+
- `tiangong flow apply-process-flow-repairs`
|
|
52
|
+
- `tiangong flow regen-product`
|
|
53
|
+
- `tiangong flow validate-processes`
|
|
54
|
+
- `tiangong publish run`
|
|
55
|
+
- `tiangong validation run`
|
|
56
|
+
- `tiangong admin embedding-run`
|
|
57
|
+
|
|
58
|
+
## Remaining planned command surface
|
|
59
|
+
|
|
60
|
+
The remaining planned placeholders in the documented surface are now limited to `auth *` and `job *`.
|
|
61
|
+
|
|
62
|
+
The stable launcher is `bin/tiangong.js`. It loads the compiled runtime at `dist/src/main.js`, while `npm start -- ...` rebuilds and dogfoods the same launcher path.
|
|
63
|
+
|
|
64
|
+
## Quality gate
|
|
65
|
+
|
|
66
|
+
The repository enforces:
|
|
67
|
+
|
|
68
|
+
- `npm run lint`
|
|
69
|
+
- `npm run prettier`
|
|
70
|
+
- `npm test`
|
|
71
|
+
- `npm run test:coverage`
|
|
72
|
+
- `npm run test:coverage:assert-full`
|
|
73
|
+
- `npm run prepush:gate`
|
|
74
|
+
|
|
75
|
+
`npm run lint` is the required local gate. It runs `eslint`, deprecated API diagnostics, `prettier --check`, a coverage-ignore guard, and `tsc`. Coverage is enforced at 100% for `src/**/*.ts`. Launcher smoke tests remain in the normal test suite, and coverage-ignore pragmas are forbidden as a substitute for test coverage.
|
|
76
|
+
|
|
77
|
+
## Releases
|
|
78
|
+
|
|
79
|
+
The public npm package name for this repository is `@tiangong-lca/cli`.
|
|
80
|
+
|
|
81
|
+
Normal releases are tag-driven and published by GitHub Actions:
|
|
82
|
+
|
|
83
|
+
- open a release-prep PR from `main`
|
|
84
|
+
- bump only the CLI package version in `package.json`
|
|
85
|
+
- after merge, `.github/workflows/tag-release-from-merge.yml` creates `cli-vX.Y.Z`
|
|
86
|
+
- `.github/workflows/publish.yml` publishes from that immutable tag through npm Trusted Publishing
|
|
87
|
+
|
|
88
|
+
One-time repository and npm Trusted Publisher setup lives in [docs/release-setup.md](./docs/release-setup.md).
|
|
89
|
+
|
|
90
|
+
## Quick start
|
|
91
|
+
|
|
92
|
+
Install Node.js `24.x` with any platform-native path you already use. The CLI only requires a working Node 24 runtime; it does not depend on `bash`, `nvm`, or other Unix-only setup tools. Examples that work well:
|
|
93
|
+
|
|
94
|
+
- Windows: the official Node.js `24.x` installer
|
|
95
|
+
- macOS: the official Node.js `24.x` installer, `fnm`, or `nvm`
|
|
96
|
+
- Linux: your preferred Node 24 package/install method
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npm ci
|
|
100
|
+
npm run build
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Once the package is published, install it with:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npm install --global @tiangong-lca/cli
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Initialize `.env` by duplicating `.env.example` to `.env` with your editor or file manager. Any equivalent copy action is fine on macOS, Linux, or Windows.
|
|
110
|
+
|
|
111
|
+
Recommended cross-platform launchers:
|
|
112
|
+
|
|
113
|
+
- `npm exec tiangong -- ...`
|
|
114
|
+
- `node ./bin/tiangong.js ...`
|
|
115
|
+
- `node ./dist/src/main.js ...`
|
|
116
|
+
|
|
117
|
+
`npm start -- ...` is still available for local CLI development, but it is a rebuild-and-run convenience wrapper rather than the canonical public entrypoint.
|
|
118
|
+
|
|
119
|
+
Repository-local quality gate:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npm run lint
|
|
123
|
+
npm test
|
|
124
|
+
npm run test:coverage
|
|
125
|
+
npm run test:coverage:assert-full
|
|
126
|
+
npm run prepush:gate
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Current public CLI env contract:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
TIANGONG_LCA_API_BASE_URL=
|
|
133
|
+
TIANGONG_LCA_API_KEY=
|
|
134
|
+
TIANGONG_LCA_REGION=us-east-1
|
|
135
|
+
TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY=
|
|
136
|
+
TIANGONG_LCA_SESSION_FILE=
|
|
137
|
+
TIANGONG_LCA_DISABLE_SESSION_CACHE=false
|
|
138
|
+
TIANGONG_LCA_FORCE_REAUTH=false
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`TIANGONG_LCA_API_KEY` is the TianGong user API key generated from the account page, not a Supabase project key. The CLI uses it only as a bootstrap credential, exchanges it for a user session with `TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY`, then reuses the resolved access token for both Edge Functions and direct Supabase access.
|
|
142
|
+
|
|
143
|
+
Optional review-only env block: ignore it unless `tiangong review process --enable-llm` or `tiangong review flow --enable-llm` is enabled. `TIANGONG_LCA_REVIEW_LLM_BASE_URL` must point to an OpenAI-compatible Responses API base URL; the CLI calls `<base_url>/responses`.
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
TIANGONG_LCA_REVIEW_LLM_BASE_URL=
|
|
147
|
+
TIANGONG_LCA_REVIEW_LLM_API_KEY=
|
|
148
|
+
TIANGONG_LCA_REVIEW_LLM_MODEL=
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Internal/preparatory env surface already normalized in the repo, but not consumed by any current public `tiangong` command:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
TIANGONG_LCA_KB_SEARCH_API_BASE_URL=
|
|
155
|
+
TIANGONG_LCA_KB_SEARCH_API_KEY=
|
|
156
|
+
TIANGONG_LCA_KB_SEARCH_REGION=us-east-1
|
|
157
|
+
|
|
158
|
+
TIANGONG_LCA_UNSTRUCTURED_API_BASE_URL=
|
|
159
|
+
TIANGONG_LCA_UNSTRUCTURED_API_KEY=
|
|
160
|
+
TIANGONG_LCA_UNSTRUCTURED_PROVIDER=
|
|
161
|
+
TIANGONG_LCA_UNSTRUCTURED_MODEL=
|
|
162
|
+
TIANGONG_LCA_UNSTRUCTURED_CHUNK_TYPE=false
|
|
163
|
+
TIANGONG_LCA_UNSTRUCTURED_RETURN_TXT=true
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
No extra generic `SUPABASE_URL`, `SUPABASE_KEY`, or `TIANGONG_LCA_TIDAS_SDK_DIR` env is required. The CLI derives the native `@supabase/supabase-js` client from `TIANGONG_LCA_API_BASE_URL`, bootstraps the user session from `TIANGONG_LCA_API_KEY` plus `TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY`, and loads `@tiangong-lca/tidas-sdk` directly from `package.json` dependencies.
|
|
167
|
+
|
|
168
|
+
Command-level env reality:
|
|
169
|
+
|
|
170
|
+
| Command group | Required env |
|
|
171
|
+
| --- | --- |
|
|
172
|
+
| `doctor` | none |
|
|
173
|
+
| `search *` | `TIANGONG_LCA_API_BASE_URL`, `TIANGONG_LCA_API_KEY`, `TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY`, optional `TIANGONG_LCA_REGION` |
|
|
174
|
+
| `admin embedding-run` | `TIANGONG_LCA_API_BASE_URL`, `TIANGONG_LCA_API_KEY`, `TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY`, optional `TIANGONG_LCA_REGION` |
|
|
175
|
+
| `process get` | `TIANGONG_LCA_API_BASE_URL`, `TIANGONG_LCA_API_KEY`, `TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY` |
|
|
176
|
+
| `process auto-build` | none |
|
|
177
|
+
| `process resume-build` | none |
|
|
178
|
+
| `process publish-build` | none |
|
|
179
|
+
| `process batch-build` | none |
|
|
180
|
+
| `lifecyclemodel auto-build` | none |
|
|
181
|
+
| `lifecyclemodel validate-build` | none |
|
|
182
|
+
| `lifecyclemodel publish-build` | none |
|
|
183
|
+
| `lifecyclemodel orchestrate` | none |
|
|
184
|
+
| `lifecyclemodel build-resulting-process` | none for local-only runs; `TIANGONG_LCA_API_BASE_URL`, `TIANGONG_LCA_API_KEY`, and `TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY` when `process_sources.allow_remote_lookup=true` |
|
|
185
|
+
| `lifecyclemodel publish-resulting-process` | none |
|
|
186
|
+
| `review process` | none for rule-only review; optional `TIANGONG_LCA_REVIEW_LLM_BASE_URL`, `TIANGONG_LCA_REVIEW_LLM_API_KEY`, and `TIANGONG_LCA_REVIEW_LLM_MODEL` when `--enable-llm` is set |
|
|
187
|
+
| `review flow` | none for rule-only review; optional `TIANGONG_LCA_REVIEW_LLM_BASE_URL`, `TIANGONG_LCA_REVIEW_LLM_API_KEY`, and `TIANGONG_LCA_REVIEW_LLM_MODEL` when `--enable-llm` is set |
|
|
188
|
+
| `review lifecyclemodel` | none |
|
|
189
|
+
| `flow get` | `TIANGONG_LCA_API_BASE_URL`, `TIANGONG_LCA_API_KEY`, `TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY` |
|
|
190
|
+
| `flow list` | `TIANGONG_LCA_API_BASE_URL`, `TIANGONG_LCA_API_KEY`, `TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY` |
|
|
191
|
+
| `flow remediate` | none |
|
|
192
|
+
| `flow publish-version` | `TIANGONG_LCA_API_BASE_URL`, `TIANGONG_LCA_API_KEY`, `TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY` |
|
|
193
|
+
| `flow publish-reviewed-data` | none for local dry-run; `TIANGONG_LCA_API_BASE_URL`, `TIANGONG_LCA_API_KEY`, and `TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY` when `--commit` publishes prepared flow/process rows |
|
|
194
|
+
| `flow build-alias-map` | none |
|
|
195
|
+
| `flow scan-process-flow-refs` | none |
|
|
196
|
+
| `flow plan-process-flow-repairs` | none |
|
|
197
|
+
| `flow apply-process-flow-repairs` | none |
|
|
198
|
+
| `flow regen-product` | none |
|
|
199
|
+
| `flow validate-processes` | none |
|
|
200
|
+
| `publish run` | none |
|
|
201
|
+
| `validation run` | none |
|
|
202
|
+
|
|
203
|
+
This CLI does not currently require KB, TianGong unstructured service, MCP, or `OPENAI_*` env keys for any public command. Optional semantic review now goes through the review-only `TIANGONG_LCA_REVIEW_LLM_*` keys instead of legacy provider-specific names. Those variables are optional as a block and only apply when `--enable-llm` is set on supported review commands. The repo already contains internal helper modules for KB and TianGong unstructured integrations; their env keys are listed in `.env.example` as internal/preparatory only, not as a public command contract.
|
|
204
|
+
|
|
205
|
+
Run the CLI:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
npm exec tiangong -- --help
|
|
209
|
+
npm exec tiangong -- doctor
|
|
210
|
+
npm exec tiangong -- doctor --json
|
|
211
|
+
npm exec tiangong -- search flow --input ./request.json --dry-run
|
|
212
|
+
npm exec tiangong -- process get --id <process-id> --version <version> --json
|
|
213
|
+
npm exec tiangong -- process auto-build --input ./examples/process-auto-build.request.json --json
|
|
214
|
+
npm exec tiangong -- process resume-build --run-id <run-id> --json
|
|
215
|
+
npm exec tiangong -- process publish-build --run-id <run-id> --json
|
|
216
|
+
npm exec tiangong -- process batch-build --input ./examples/process-batch-build.request.json --json
|
|
217
|
+
npm exec tiangong -- lifecyclemodel auto-build --input ./examples/lifecyclemodel-auto-build.request.json --json
|
|
218
|
+
npm exec tiangong -- lifecyclemodel validate-build --run-dir ./artifacts/lifecyclemodel_auto_build/<run_id> --json
|
|
219
|
+
npm exec tiangong -- lifecyclemodel publish-build --run-dir ./artifacts/lifecyclemodel_auto_build/<run_id> --json
|
|
220
|
+
npm exec tiangong -- lifecyclemodel orchestrate plan --input ./lifecyclemodel-orchestrate.request.json --out-dir ./artifacts/lifecyclemodel_recursive/<run_id> --json
|
|
221
|
+
npm exec tiangong -- lifecyclemodel build-resulting-process --input ./request.json --json
|
|
222
|
+
npm exec tiangong -- lifecyclemodel publish-resulting-process --run-dir ./runs/example --publish-processes --publish-relations --json
|
|
223
|
+
npm exec tiangong -- review process --run-root ./artifacts/process_from_flow/<run_id> --run-id <run_id> --out-dir ./review --json
|
|
224
|
+
npm exec tiangong -- review flow --rows-file ./flows.json --out-dir ./flow-review --json
|
|
225
|
+
npm exec tiangong -- review lifecyclemodel --run-dir ./artifacts/lifecyclemodel_auto_build/<run_id> --out-dir ./lifecyclemodel-review --json
|
|
226
|
+
npm exec tiangong -- flow get --id <flow-id> --version <version> --json
|
|
227
|
+
npm exec tiangong -- flow list --id <flow-id> --state-code 100 --limit 20 --json
|
|
228
|
+
npm exec tiangong -- flow remediate --input-file ./invalid-flows.jsonl --out-dir ./flow-remediation --json
|
|
229
|
+
npm exec tiangong -- flow publish-version --input-file ./ready-flows.jsonl --out-dir ./flow-publish --dry-run --json
|
|
230
|
+
npm exec tiangong -- flow publish-reviewed-data --flow-rows-file ./reviewed-flows.jsonl --original-flow-rows-file ./original-flows.jsonl --out-dir ./flow-publish-reviewed --dry-run --json
|
|
231
|
+
npm exec tiangong -- flow build-alias-map --old-flow-file ./old-flows.jsonl --new-flow-file ./new-flows.jsonl --out-dir ./flow-alias-map --json
|
|
232
|
+
npm exec tiangong -- flow scan-process-flow-refs --processes-file ./processes.jsonl --scope-flow-file ./flows.jsonl --out-dir ./flow-scan --json
|
|
233
|
+
npm exec tiangong -- flow plan-process-flow-repairs --processes-file ./processes.jsonl --scope-flow-file ./flows.jsonl --scan-findings ./flow-scan/scan-findings.json --out-dir ./flow-repair-plan --json
|
|
234
|
+
npm exec tiangong -- flow apply-process-flow-repairs --processes-file ./processes.jsonl --scope-flow-file ./flows.jsonl --scan-findings ./flow-scan/scan-findings.json --out-dir ./flow-repair-apply --json
|
|
235
|
+
npm exec tiangong -- flow regen-product --processes-file ./processes.jsonl --scope-flow-file ./flows.jsonl --out-dir ./flow-regen --apply --json
|
|
236
|
+
npm exec tiangong -- flow validate-processes --original-processes-file ./before.jsonl --patched-processes-file ./after.jsonl --scope-flow-file ./flows.jsonl --out-dir ./flow-validate --json
|
|
237
|
+
npm exec tiangong -- publish run --input ./examples/publish-run.request.json --dry-run
|
|
238
|
+
npm exec tiangong -- validation run --input-dir ./tidas-package --engine auto
|
|
239
|
+
npm exec tiangong -- admin embedding-run --input ./jobs.json --dry-run
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Process build scaffold
|
|
243
|
+
|
|
244
|
+
`tiangong process get` is the CLI-owned read-only process detail surface. It derives a deterministic Supabase read target from `TIANGONG_LCA_API_BASE_URL`, executes through the native `@supabase/supabase-js` client, resolves one process row by `id/version` with a latest-version fallback, and returns one structured JSON payload without reintroducing MCP, Python, or a generic transport layer.
|
|
245
|
+
|
|
246
|
+
`tiangong process auto-build` is the first migrated `process_from_flow` slice. It reads one request JSON from `--input`, loads the referenced ILCD flow dataset from `flow_file`, preserves the old run id contract (`pfw_<flow_code>_<flow_uuid8>_<operation>_<UTC_TIMESTAMP>`), and writes a local run scaffold under `artifacts/process_from_flow/<run_id>/` or `--out-dir`.
|
|
247
|
+
|
|
248
|
+
The command keeps the legacy per-run layout that later stages still expect, including `input/`, `exports/processes/`, `exports/sources/`, `cache/process_from_flow_state.json`, and `cache/agent_handoff_summary.json`. It also adds CLI-owned manifests such as the normalized request snapshot, flow summary, assembly plan, lineage manifest, invocation index, run manifest, and a compact report artifact.
|
|
249
|
+
|
|
250
|
+
`tiangong process resume-build` is the second migrated `process_from_flow` slice. It reopens one existing local run by `--run-id` or `--run-dir`, validates the required run artifacts, takes the local state lock, clears any persisted `stop_after` checkpoint, records `resume-metadata.json` and `resume-history.jsonl`, updates `invocation-index.json`, rewrites `agent_handoff_summary.json`, and emits `process-resume-build-report.json`.
|
|
251
|
+
|
|
252
|
+
`tiangong process publish-build` is the third migrated `process_from_flow` slice. It reopens one existing local run by `--run-id` or `--run-dir`, validates `process_from_flow_state.json`, `agent_handoff_summary.json`, `run-manifest.json`, and `invocation-index.json`, collects canonical process/source datasets from `exports/` or state fallbacks, writes `stage_outputs/10_publish/publish-bundle.json`, `publish-request.json`, `publish-intent.json`, rewrites `agent_handoff_summary.json`, updates the run state and invocation index, and emits `process-publish-build-report.json`.
|
|
253
|
+
|
|
254
|
+
`tiangong process batch-build` is the fourth migrated `process_from_flow` slice. It reads one batch manifest, prepares a self-contained batch root, fans out multiple local `process auto-build` runs through the CLI-owned contract, writes a structured per-item aggregate report, and preserves deterministic item-level artifact paths for downstream `resume-build` or `publish-build` steps.
|
|
255
|
+
|
|
256
|
+
`resume-build`, `publish-build`, and `batch-build` all still stop at local handoff boundaries. They do not execute remote publish CRUD or commit mode themselves; that boundary remains in `tiangong publish run`.
|
|
257
|
+
|
|
258
|
+
`tiangong lifecyclemodel auto-build` is the first migrated `lifecyclemodel_automated_builder` slice. It reads one local-run manifest from `--input`, resolves one or more `process-automated-builder` run directories, infers the process graph from shared flow UUIDs, chooses one reference process, computes `@multiplicationFactor`, writes native `json_ordered` lifecyclemodel datasets plus `run-plan.json`, `resolved-manifest.json`, `selection/selection-brief.md`, `discovery/reference-model-summary.json`, `models/**/summary.json`, `connections.json`, and `process-catalog.json`, and keeps the run local-only and read-only.
|
|
259
|
+
|
|
260
|
+
The canonical `tiangong-lca-skills/lifecyclemodel-automated-builder` entrypoint now uses a native Node `.mjs` wrapper that delegates directly to `tiangong lifecyclemodel auto-build`. The canonical build path no longer routes through Bash, Python, or MCP.
|
|
261
|
+
|
|
262
|
+
`tiangong lifecyclemodel validate-build` is the second migrated `lifecyclemodel_automated_builder` slice. It reopens one existing local lifecyclemodel build run by `--run-dir`, scans `models/*/tidas_bundle/lifecyclemodels/*.json`, runs the unified validation module against each model bundle, writes per-model reports under `reports/model-validations/`, updates `manifests/invocation-index.json`, and emits `reports/lifecyclemodel-validate-build-report.json`.
|
|
263
|
+
|
|
264
|
+
`tiangong lifecyclemodel publish-build` is the third migrated `lifecyclemodel_automated_builder` slice. It reopens one existing local lifecyclemodel build run by `--run-dir`, collects native lifecyclemodel payloads from `models/*/tidas_bundle/lifecyclemodels/*.json`, reads the aggregate validation summary when present, writes `stage_outputs/10_publish/publish-bundle.json`, `publish-request.json`, and `publish-intent.json`, updates `manifests/invocation-index.json`, and emits `reports/lifecyclemodel-publish-build-report.json`.
|
|
265
|
+
|
|
266
|
+
The current lifecyclemodel build family intentionally keeps three boundaries out of the auto-build slice:
|
|
267
|
+
|
|
268
|
+
- no remote lifecyclemodel CRUD
|
|
269
|
+
- no reference-model discovery against MCP / KB / LLM services
|
|
270
|
+
- no automatic chaining into validate-build or publish-build
|
|
271
|
+
|
|
272
|
+
`tiangong lifecyclemodel build-resulting-process` remains local-first, but it no longer hard-fails when a request explicitly enables `process_sources.allow_remote_lookup`. In that mode the CLI derives a deterministic Supabase read target from `TIANGONG_LCA_API_BASE_URL`, resolves missing process datasets by exact `id/version` with a latest-version fallback through the native `@supabase/supabase-js` client, and keeps the same local artifact contract instead of routing through MCP or semantic search.
|
|
273
|
+
|
|
274
|
+
`tiangong lifecyclemodel orchestrate` is the native recursive assembly command for multi-node product-system runs. `plan` writes `assembly-plan.json`, `graph-manifest.json`, `lineage-manifest.json`, and `boundary-report.json`; `execute` invokes only native CLI-backed builder slices and records per-invocation results under `invocations/`; `publish` reopens one orchestrator run and prepares `publish-bundle.json` plus `publish-summary.json` from prior local artifacts. The `process_builder` request surface is now intentionally narrow: only CLI-native local-build fields are accepted, and extra builder knobs are rejected during request normalization.
|
|
275
|
+
|
|
276
|
+
`tiangong review process` is the first migrated review slice. It reopens one local `process_from_flow` run under `exports/processes/`, replays the existing artifact-first review contract, writes bilingual markdown findings plus structured JSON reports, and keeps optional semantic review behind the CLI-owned `TIANGONG_LCA_REVIEW_LLM_*` abstraction instead of direct `OPENAI_*` calls in a skill script.
|
|
277
|
+
|
|
278
|
+
`tiangong review flow` is the flow-side local governance review slice. It accepts exactly one of `--rows-file`, `--flows-dir`, or `--run-root`, materializes explicit local flow snapshots when needed, writes `rule_findings.jsonl`, `llm_findings.jsonl`, `findings.jsonl`, `flow_summaries.jsonl`, `similarity_pairs.jsonl`, `flow_review_summary.json`, `flow_review_zh.md`, `flow_review_en.md`, `flow_review_timing.md`, and `flow_review_report.json`, and keeps optional semantic review behind the same CLI-owned `TIANGONG_LCA_REVIEW_LLM_*` abstraction. The current CLI slice is intentionally local-first and does not implement `--with-reference-context` or local registry enrichment yet.
|
|
279
|
+
|
|
280
|
+
`tiangong review lifecyclemodel` is the lifecyclemodel-side local review slice. It reopens one existing lifecyclemodel build run by `--run-dir`, scans `models/*/tidas_bundle/lifecyclemodels/*.json`, reuses `summary.json`, `connections.json`, `process-catalog.json`, and the aggregate `reports/lifecyclemodel-validate-build-report.json` when present, writes `model_summaries.jsonl`, `findings.jsonl`, `lifecyclemodel_review_summary.json`, `lifecyclemodel_review_zh.md`, `lifecyclemodel_review_en.md`, `lifecyclemodel_review_timing.md`, and `lifecyclemodel_review_report.json`, and stays local-first without introducing Python, LangGraph, or skill-local review runtimes.
|
|
281
|
+
|
|
282
|
+
`tiangong flow get` is the CLI-owned read-only flow detail surface. It derives a deterministic Supabase read target from `TIANGONG_LCA_API_BASE_URL`, resolves one visible flow row by `id` plus optional `version` / `user_id` / `state_code` through the native `@supabase/supabase-js` client, falls back to the latest visible version when an exact version lookup misses, and rejects ambiguous visible matches instead of guessing.
|
|
283
|
+
|
|
284
|
+
`tiangong flow list` is the CLI-owned deterministic flow enumeration surface. It queries `flows` through the native `@supabase/supabase-js` client while preserving stable `/rest/v1/flows` filter semantics such as repeated `--id`, `--state-code`, and `--type-of-dataset`, defaults to `order=id.asc,version.asc`, and can fetch all matching rows through explicit offset pagination via `--all --page-size <n>` without reintroducing MCP or skill-local transport code.
|
|
285
|
+
|
|
286
|
+
`tiangong flow remediate` is the first CLI-owned remediation slice for flow governance. It reads one invalid-flow JSON or JSONL input, applies deterministic round1 local remediation, and writes the historical remediation artifacts under one output directory without reintroducing Python or MCP.
|
|
287
|
+
|
|
288
|
+
`tiangong flow publish-version` is the first CLI-owned remote write slice for flow governance. It reads one ready-for-publish JSON or JSONL input, derives a deterministic Supabase write target from `TIANGONG_LCA_API_BASE_URL`, performs dry-run or commit mode through the native `@supabase/supabase-js` client against `/rest/v1/flows`, and preserves the historical success-list, remote-failure, and sync-report artifact names for downstream follow-up. It still does not implement round2 retry; post-governance product-side regeneration now lives in `tiangong flow regen-product`.
|
|
289
|
+
|
|
290
|
+
`tiangong flow publish-reviewed-data` is the CLI-owned reviewed publish preparation slice for flow governance. It reads reviewed flow rows and/or reviewed process rows from local JSON or JSONL inputs, can use `--original-flow-rows-file` to skip unchanged flow rows before planning publish, supports `skip | append_only_bump | upsert_current_version`, writes `prepared-flow-rows.json`, `prepared-process-rows.json`, `flow-version-map.json`, `skipped-unchanged-flow-rows.json`, `process-flow-ref-rewrite-evidence.jsonl`, and `publish-report.json`, and preserves the historical success-list / remote-failure / sync-report files for downstream follow-up. The native CLI path now covers local process-row preparation, optional process flow-ref rewrites, and commit-time process publish through the same `@supabase/supabase-js` writer layer; no legacy fallback path remains for reviewed process rows.
|
|
291
|
+
|
|
292
|
+
`tiangong flow build-alias-map` is the CLI-owned deterministic alias-map slice for flow governance. It reads one or more old flow snapshots plus one or more new flow snapshots, optionally consumes a seed alias map, writes `alias-plan.json`, `alias-plan.jsonl`, `flow-alias-map.json`, `manual-review-queue.jsonl`, and `alias-summary.json`, and keeps the boundary local-only instead of routing through skill-local Python.
|
|
293
|
+
|
|
294
|
+
`tiangong flow scan-process-flow-refs` is the CLI-owned standalone process-reference scan slice for flow governance. It reads one local process row set plus one or more local scope/catalog flow row sets, classifies every `referenceToFlowDataSet`, optionally excludes emergy-named processes up front, and writes stable `emergy-excluded-processes.json`, `scan-summary.json`, `scan-findings.json`, and `scan-findings.jsonl` artifacts without falling back to skill-local Python.
|
|
295
|
+
|
|
296
|
+
`tiangong flow plan-process-flow-repairs` is the CLI-owned standalone deterministic repair-planning slice for flow governance. It reads one local process row set plus one or more local scope flow row sets, optionally consumes prior `scan-findings`, applies the explicit `disabled | alias-only | alias-or-unique-name` auto-patch boundary, and writes `repair-plan.json`, `repair-plan.jsonl`, `manual-review-queue.jsonl`, and `repair-summary.json`.
|
|
297
|
+
|
|
298
|
+
`tiangong flow apply-process-flow-repairs` is the CLI-owned standalone deterministic repair-apply slice for flow governance. It reuses the same local process/scope/alias/scan contract as the planning command, applies only the deterministic subset, emits per-process patch evidence under `process-patches/`, writes `patched-processes.json`, and can sync exact-version rows back into a local `process-pool-file`.
|
|
299
|
+
|
|
300
|
+
`tiangong flow regen-product` is the CLI-owned local product-side regeneration slice for flow governance. It reads one local process row set plus one or more local scope/catalog flow row sets, runs `scan -> repair plan -> optional apply -> optional validate` under one run root, writes stable `scan/`, `repair/`, `repair-apply/`, `validate/`, and `flow-regen-product-report.json` artifacts, and keeps exit code `1` reserved for validation failures after `--apply`.
|
|
301
|
+
|
|
302
|
+
`tiangong flow validate-processes` is the CLI-owned standalone validation slice for locally patched process rows after governance repair. It reads one original process snapshot, one patched process snapshot, and one or more scope flow snapshots, verifies that only `referenceToFlowDataSet` paths changed, keeps quantitative references stable, optionally runs local TIDAS validation through the CLI-owned validator assembled from the direct `@tiangong-lca/tidas-sdk` dependency, and writes `validation-report.json` plus `validation-failures.jsonl` without falling back to skill-local Python.
|
|
303
|
+
|
|
304
|
+
## Publish and validation
|
|
305
|
+
|
|
306
|
+
`tiangong process publish-build` is the process-side local publish handoff command. It prepares the local bundle/request/intent artifacts expected by `tiangong publish run` without reintroducing Python, MCP, or legacy remote writers into the CLI.
|
|
307
|
+
|
|
308
|
+
`tiangong process batch-build` is the process-side local batch orchestration command. It keeps batch execution file-first and JSON-first, reuses the single-run `process auto-build` contract for each item, and emits one batch report instead of pushing shell loops or Python coordinators back onto the caller.
|
|
309
|
+
|
|
310
|
+
`tiangong lifecyclemodel validate-build` is the lifecyclemodel-side local validation command. It keeps validation file-first, reuses the unified `tiangong validation run` module under the hood, and writes both per-model reports and one aggregate build report without reintroducing Python or MCP into the CLI.
|
|
311
|
+
|
|
312
|
+
`tiangong lifecyclemodel publish-build` is the lifecyclemodel-side local publish handoff command. It prepares the local bundle/request/intent artifacts expected by `tiangong publish run` without reintroducing Python, MCP, or legacy remote writers into the CLI.
|
|
313
|
+
|
|
314
|
+
`tiangong lifecyclemodel publish-resulting-process` is the lifecyclemodel-side local publish handoff command. It reads a prior resulting-process run, writes `publish-bundle.json` and `publish-intent.json`, and preserves the old builder's artifact contract without reintroducing Python or MCP into the CLI.
|
|
315
|
+
|
|
316
|
+
`tiangong publish run` is the CLI-side publish contract boundary. It normalizes publish requests, ingests upstream `publish-bundle.json` inputs, writes `normalized-request.json`, `collected-inputs.json`, `relation-manifest.json`, and `publish-report.json`, and keeps commit-mode execution behind explicit executors instead of reintroducing MCP-specific logic into the CLI.
|
|
317
|
+
|
|
318
|
+
`tiangong validation run` is the CLI-side validation boundary. It standardizes local TIDAS package validation through one JSON report shape, supports `--engine auto|sdk`, and keeps the local package-validation path inside the CLI-owned validator assembled from the direct `@tiangong-lca/tidas-sdk` dependency instead of shelling out to `tidas-tools` or loading sibling-repo artifacts.
|
|
319
|
+
|
|
320
|
+
Run the built artifact directly:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
node ./bin/tiangong.js doctor
|
|
324
|
+
node ./bin/tiangong.js process get --id <process-id> --json
|
|
325
|
+
node ./bin/tiangong.js flow get --id <flow-id> --json
|
|
326
|
+
node ./bin/tiangong.js flow list --state-code 100 --limit 20 --json
|
|
327
|
+
node ./bin/tiangong.js flow publish-reviewed-data --flow-rows-file ./reviewed-flows.jsonl --out-dir ./flow-publish-reviewed --dry-run --json
|
|
328
|
+
node ./bin/tiangong.js flow build-alias-map --old-flow-file ./old-flows.jsonl --new-flow-file ./new-flows.jsonl --out-dir ./flow-alias-map --json
|
|
329
|
+
node ./bin/tiangong.js flow scan-process-flow-refs --processes-file ./processes.jsonl --scope-flow-file ./flows.jsonl --out-dir ./flow-scan --json
|
|
330
|
+
node ./bin/tiangong.js flow plan-process-flow-repairs --processes-file ./processes.jsonl --scope-flow-file ./flows.jsonl --scan-findings ./flow-scan/scan-findings.json --out-dir ./flow-repair-plan --json
|
|
331
|
+
node ./bin/tiangong.js flow apply-process-flow-repairs --processes-file ./processes.jsonl --scope-flow-file ./flows.jsonl --scan-findings ./flow-scan/scan-findings.json --out-dir ./flow-repair-apply --json
|
|
332
|
+
node ./bin/tiangong.js flow regen-product --processes-file ./processes.jsonl --scope-flow-file ./flows.jsonl --out-dir ./flow-regen --apply --json
|
|
333
|
+
node ./bin/tiangong.js process auto-build --input ./examples/process-auto-build.request.json --json
|
|
334
|
+
node ./bin/tiangong.js process resume-build --run-id <run-id> --json
|
|
335
|
+
node ./bin/tiangong.js process publish-build --run-id <run-id> --json
|
|
336
|
+
node ./bin/tiangong.js process batch-build --input ./examples/process-batch-build.request.json --json
|
|
337
|
+
node ./bin/tiangong.js lifecyclemodel auto-build --input ./examples/lifecyclemodel-auto-build.request.json --json
|
|
338
|
+
node ./bin/tiangong.js lifecyclemodel validate-build --run-dir ./artifacts/lifecyclemodel_auto_build/<run_id> --json
|
|
339
|
+
node ./bin/tiangong.js lifecyclemodel publish-build --run-dir ./artifacts/lifecyclemodel_auto_build/<run_id> --json
|
|
340
|
+
node ./bin/tiangong.js lifecyclemodel orchestrate plan --input ./lifecyclemodel-orchestrate.request.json --out-dir ./artifacts/lifecyclemodel_recursive/<run_id> --json
|
|
341
|
+
node ./bin/tiangong.js flow publish-version --input-file ./ready-flows.jsonl --out-dir ./flow-publish --dry-run --json
|
|
342
|
+
node ./bin/tiangong.js publish run --input ./examples/publish-run.request.json --dry-run --json
|
|
343
|
+
node ./bin/tiangong.js validation run --input-dir ./package --engine auto --json
|
|
344
|
+
node ./dist/src/main.js doctor --json
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Examples
|
|
348
|
+
|
|
349
|
+
Minimal example requests are available under `examples/`:
|
|
350
|
+
|
|
351
|
+
- `examples/process-auto-build.request.json`
|
|
352
|
+
- `examples/process-batch-build.request.json`
|
|
353
|
+
- `examples/lifecyclemodel-auto-build.request.json`
|
|
354
|
+
- `examples/publish-run.request.json`
|
|
355
|
+
|
|
356
|
+
## Workspace usage
|
|
357
|
+
|
|
358
|
+
`tiangong-lca-skills` should stay as thin Node `.mjs` wrappers over this CLI instead of keeping parallel runtimes. The current contract is:
|
|
359
|
+
|
|
360
|
+
- skills call `tiangong` as the stable entrypoint
|
|
361
|
+
- deleted Python, MCP, and OpenClaw runtimes are not supported compatibility paths
|
|
362
|
+
- new capability must land as a native `tiangong <noun> <verb>` command before a skill depends on it
|
|
363
|
+
|
|
364
|
+
## Docs
|
|
365
|
+
|
|
366
|
+
- Chinese setup guide: [DEV_CN.md](./DEV_CN.md)
|
|
367
|
+
- Detailed implementation guide: [docs/IMPLEMENTATION_GUIDE_CN.md](./docs/IMPLEMENTATION_GUIDE_CN.md)
|
|
368
|
+
- Skills migration checklist: [docs/SKILLS_TO_CLI_MIGRATION_CHECKLIST_CN.md](./docs/SKILLS_TO_CLI_MIGRATION_CHECKLIST_CN.md)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function runFromBin(argv?: string[], env?: NodeJS.ProcessEnv): Promise<number>;
|
package/bin/tiangong.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
9
|
+
const entryPath = path.join(rootDir, 'dist', 'src', 'main.js');
|
|
10
|
+
|
|
11
|
+
export async function runFromBin(argv = process.argv.slice(2), env = process.env) {
|
|
12
|
+
if (!existsSync(entryPath)) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
"Missing built CLI artifacts at 'dist/src/main.js'. Run 'npm run build' or reinstall dependencies to regenerate dist.",
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const entryUrl = pathToFileURL(entryPath).href;
|
|
19
|
+
const { main } = await import(entryUrl);
|
|
20
|
+
return main(argv, env);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const invokedUrl = process.argv[1] ? pathToFileURL(path.resolve(process.argv[1])).href : null;
|
|
24
|
+
|
|
25
|
+
if (invokedUrl && import.meta.url === invokedUrl) {
|
|
26
|
+
try {
|
|
27
|
+
process.exitCode = await runFromBin();
|
|
28
|
+
} catch (error) {
|
|
29
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
const COVERAGE_METRIC_KEYS = ['lines', 'statements', 'functions', 'branches'];
|
|
4
|
+
function listTrackedSourceFiles(rootDir, relativeDir) {
|
|
5
|
+
const absoluteDir = path.join(rootDir, relativeDir);
|
|
6
|
+
const entries = readdirSync(absoluteDir, { withFileTypes: true });
|
|
7
|
+
const files = [];
|
|
8
|
+
for (const entry of entries) {
|
|
9
|
+
const relativePath = path.join(relativeDir, entry.name);
|
|
10
|
+
if (entry.isDirectory()) {
|
|
11
|
+
files.push(...listTrackedSourceFiles(rootDir, relativePath));
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (relativePath.endsWith('.d.ts')) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (relativePath.endsWith('.ts') || relativePath.endsWith('.js')) {
|
|
18
|
+
files.push(path.join(rootDir, relativePath));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return files;
|
|
22
|
+
}
|
|
23
|
+
function isCoverageMetric(value) {
|
|
24
|
+
return Boolean(value &&
|
|
25
|
+
typeof value === 'object' &&
|
|
26
|
+
typeof value.total === 'number' &&
|
|
27
|
+
typeof value.covered === 'number' &&
|
|
28
|
+
typeof value.skipped === 'number' &&
|
|
29
|
+
typeof value.pct === 'number');
|
|
30
|
+
}
|
|
31
|
+
function isCoverageFileSummary(value) {
|
|
32
|
+
if (!value || typeof value !== 'object') {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return COVERAGE_METRIC_KEYS.every((key) => isCoverageMetric(value[key]));
|
|
36
|
+
}
|
|
37
|
+
function aggregateCoverage(entries) {
|
|
38
|
+
return Object.fromEntries(COVERAGE_METRIC_KEYS.map((key) => {
|
|
39
|
+
const total = entries.reduce((sum, entry) => sum + entry[key].total, 0);
|
|
40
|
+
const covered = entries.reduce((sum, entry) => sum + entry[key].covered, 0);
|
|
41
|
+
const skipped = entries.reduce((sum, entry) => sum + entry[key].skipped, 0);
|
|
42
|
+
return [
|
|
43
|
+
key,
|
|
44
|
+
{
|
|
45
|
+
total,
|
|
46
|
+
covered,
|
|
47
|
+
skipped,
|
|
48
|
+
pct: total === 0 ? 100 : (covered / total) * 100,
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
const summaryPath = path.join(process.cwd(), 'coverage', 'coverage-summary.json');
|
|
54
|
+
const summary = JSON.parse(readFileSync(summaryPath, 'utf8'));
|
|
55
|
+
const coveredFiles = new Set(Object.keys(summary).filter((key) => key !== 'total'));
|
|
56
|
+
const expectedFiles = listTrackedSourceFiles(process.cwd(), 'src');
|
|
57
|
+
const expectedCoverageEntries = expectedFiles.map((filePath) => {
|
|
58
|
+
const coverageEntry = summary[filePath];
|
|
59
|
+
if (!isCoverageFileSummary(coverageEntry)) {
|
|
60
|
+
throw new Error(`Expected coverage summary to include ${filePath}, but it was missing.`);
|
|
61
|
+
}
|
|
62
|
+
return coverageEntry;
|
|
63
|
+
});
|
|
64
|
+
const aggregate = aggregateCoverage(expectedCoverageEntries);
|
|
65
|
+
for (const key of COVERAGE_METRIC_KEYS) {
|
|
66
|
+
const value = aggregate[key];
|
|
67
|
+
if (value.covered !== value.total || value.pct !== 100) {
|
|
68
|
+
throw new Error(`Expected ${key} coverage across src files to equal 100 but received ${value.pct} (${value.covered}/${value.total}).`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (const filePath of expectedFiles) {
|
|
72
|
+
if (!coveredFiles.has(filePath)) {
|
|
73
|
+
throw new Error(`Expected coverage summary to include ${filePath}, but it was missing.`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
process.stdout.write('Coverage assertion passed: 100% on lines, statements, functions, and branches across src files.\n');
|
|
77
|
+
//# sourceMappingURL=assert-full-coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assert-full-coverage.js","sourceRoot":"","sources":["../../scripts/assert-full-coverage.ts"],"names":[],"mappings":"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","sourcesContent":["import { readdirSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\n\ntype CoverageMetric = {\n total: number;\n covered: number;\n skipped: number;\n pct: number;\n};\n\ntype CoverageMetricKey = 'lines' | 'statements' | 'functions' | 'branches';\n\ntype CoverageFileSummary = Record<CoverageMetricKey, CoverageMetric>;\n\ntype CoverageSummary = {\n total: CoverageFileSummary;\n} & Record<string, unknown>;\n\nconst COVERAGE_METRIC_KEYS: CoverageMetricKey[] = ['lines', 'statements', 'functions', 'branches'];\n\nfunction listTrackedSourceFiles(rootDir: string, relativeDir: string): string[] {\n const absoluteDir = path.join(rootDir, relativeDir);\n const entries = readdirSync(absoluteDir, { withFileTypes: true });\n const files: string[] = [];\n\n for (const entry of entries) {\n const relativePath = path.join(relativeDir, entry.name);\n if (entry.isDirectory()) {\n files.push(...listTrackedSourceFiles(rootDir, relativePath));\n continue;\n }\n if (relativePath.endsWith('.d.ts')) {\n continue;\n }\n if (relativePath.endsWith('.ts') || relativePath.endsWith('.js')) {\n files.push(path.join(rootDir, relativePath));\n }\n }\n\n return files;\n}\n\nfunction isCoverageMetric(value: unknown): value is CoverageMetric {\n return Boolean(\n value &&\n typeof value === 'object' &&\n typeof (value as CoverageMetric).total === 'number' &&\n typeof (value as CoverageMetric).covered === 'number' &&\n typeof (value as CoverageMetric).skipped === 'number' &&\n typeof (value as CoverageMetric).pct === 'number',\n );\n}\n\nfunction isCoverageFileSummary(value: unknown): value is CoverageFileSummary {\n if (!value || typeof value !== 'object') {\n return false;\n }\n\n return COVERAGE_METRIC_KEYS.every((key) => isCoverageMetric((value as CoverageFileSummary)[key]));\n}\n\nfunction aggregateCoverage(entries: CoverageFileSummary[]): CoverageFileSummary {\n return Object.fromEntries(\n COVERAGE_METRIC_KEYS.map((key) => {\n const total = entries.reduce((sum, entry) => sum + entry[key].total, 0);\n const covered = entries.reduce((sum, entry) => sum + entry[key].covered, 0);\n const skipped = entries.reduce((sum, entry) => sum + entry[key].skipped, 0);\n return [\n key,\n {\n total,\n covered,\n skipped,\n pct: total === 0 ? 100 : (covered / total) * 100,\n },\n ];\n }),\n ) as CoverageFileSummary;\n}\n\nconst summaryPath = path.join(process.cwd(), 'coverage', 'coverage-summary.json');\nconst summary = JSON.parse(readFileSync(summaryPath, 'utf8')) as CoverageSummary;\nconst coveredFiles = new Set(Object.keys(summary).filter((key) => key !== 'total'));\nconst expectedFiles = listTrackedSourceFiles(process.cwd(), 'src');\nconst expectedCoverageEntries = expectedFiles.map((filePath) => {\n const coverageEntry = summary[filePath];\n\n if (!isCoverageFileSummary(coverageEntry)) {\n throw new Error(`Expected coverage summary to include ${filePath}, but it was missing.`);\n }\n\n return coverageEntry;\n});\nconst aggregate = aggregateCoverage(expectedCoverageEntries);\n\nfor (const key of COVERAGE_METRIC_KEYS) {\n const value = aggregate[key];\n if (value.covered !== value.total || value.pct !== 100) {\n throw new Error(\n `Expected ${key} coverage across src files to equal 100 but received ${value.pct} (${value.covered}/${value.total}).`,\n );\n }\n}\n\nfor (const filePath of expectedFiles) {\n if (!coveredFiles.has(filePath)) {\n throw new Error(`Expected coverage summary to include ${filePath}, but it was missing.`);\n }\n}\n\nprocess.stdout.write(\n 'Coverage assertion passed: 100% on lines, statements, functions, and branches across src files.\\n',\n);\n"]}
|