sdx-cli 0.2.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/LICENSE +21 -0
- package/README.md +266 -0
- package/bin/dev.js +11 -0
- package/bin/run.js +3 -0
- package/dist/commands/bootstrap/consumer.js +75 -0
- package/dist/commands/bootstrap/org.js +29 -0
- package/dist/commands/bootstrap/quick.js +82 -0
- package/dist/commands/codex/run.js +36 -0
- package/dist/commands/contracts/extract.js +22 -0
- package/dist/commands/docs/generate.js +22 -0
- package/dist/commands/handoff/draft.js +41 -0
- package/dist/commands/init.js +14 -0
- package/dist/commands/map/build.js +44 -0
- package/dist/commands/map/create.js +40 -0
- package/dist/commands/map/exclude.js +25 -0
- package/dist/commands/map/include.js +25 -0
- package/dist/commands/map/remove-override.js +25 -0
- package/dist/commands/map/status.js +30 -0
- package/dist/commands/migrate/artifacts.js +68 -0
- package/dist/commands/plan/review.js +60 -0
- package/dist/commands/prompt.js +62 -0
- package/dist/commands/publish/notices.js +98 -0
- package/dist/commands/publish/sync.js +67 -0
- package/dist/commands/publish/wiki.js +39 -0
- package/dist/commands/repo/add.js +29 -0
- package/dist/commands/repo/sync.js +30 -0
- package/dist/commands/service/propose.js +40 -0
- package/dist/commands/status.js +37 -0
- package/dist/commands/version.js +16 -0
- package/dist/index.js +10 -0
- package/dist/lib/artifactMigration.js +29 -0
- package/dist/lib/bootstrap.js +43 -0
- package/dist/lib/bootstrapConsumer.js +187 -0
- package/dist/lib/bootstrapQuick.js +27 -0
- package/dist/lib/codex.js +138 -0
- package/dist/lib/config.js +40 -0
- package/dist/lib/constants.js +26 -0
- package/dist/lib/contractChanges.js +347 -0
- package/dist/lib/contracts.js +93 -0
- package/dist/lib/db.js +41 -0
- package/dist/lib/docs.js +46 -0
- package/dist/lib/fileScan.js +34 -0
- package/dist/lib/fs.js +36 -0
- package/dist/lib/github.js +52 -0
- package/dist/lib/githubPublish.js +161 -0
- package/dist/lib/handoff.js +62 -0
- package/dist/lib/mapBuilder.js +182 -0
- package/dist/lib/paths.js +39 -0
- package/dist/lib/planReview.js +88 -0
- package/dist/lib/project.js +65 -0
- package/dist/lib/promptParser.js +88 -0
- package/dist/lib/publishContracts.js +876 -0
- package/dist/lib/repoRegistry.js +92 -0
- package/dist/lib/scope.js +110 -0
- package/dist/lib/serviceNoticePlan.js +130 -0
- package/dist/lib/serviceProposal.js +82 -0
- package/dist/lib/status.js +34 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/version.js +17 -0
- package/dist/lib/workflows.js +70 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dana0550
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="./assets/readme/banner_v2.png" alt="SDX hero" width="100%" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">SDX CLI</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
System design intelligence across many repositories, with one docs-first workspace.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://github.com/dana0550/system-desiigner/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/dana0550/system-desiigner/ci.yml?branch=main&label=CI" alt="CI"></a>
|
|
13
|
+
<a href="https://github.com/dana0550/system-desiigner/actions/workflows/release.yml"><img src="https://img.shields.io/github/actions/workflow/status/dana0550/system-desiigner/release.yml?branch=main&label=Release" alt="Release"></a>
|
|
14
|
+
<a href="https://github.com/dana0550/system-desiigner/releases"><img src="https://img.shields.io/github/v/release/dana0550/system-desiigner" alt="GitHub release"></a>
|
|
15
|
+
<img src="https://img.shields.io/badge/node-%3E%3D20-339933" alt="Node 20+">
|
|
16
|
+
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-0E8A92" alt="MIT"></a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="#one-command-setup">One-Command Setup</a> •
|
|
21
|
+
<a href="#daily-workflow">Daily Workflow</a> •
|
|
22
|
+
<a href="#for-codex-agents">For Codex Agents</a> •
|
|
23
|
+
<a href="#release-process">Release Process</a>
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
## What SDX is
|
|
27
|
+
SDX gives your team a single architecture workspace that sits above service repos.
|
|
28
|
+
|
|
29
|
+
You use it to:
|
|
30
|
+
- map services across repos,
|
|
31
|
+
- track contracts,
|
|
32
|
+
- review new service plans,
|
|
33
|
+
- draft cross-team integration handoffs,
|
|
34
|
+
- publish cross-repo spec-system contract-change PRs,
|
|
35
|
+
- generate Codex-ready context packs.
|
|
36
|
+
|
|
37
|
+
v1 remains manual-triggered. SDX can open draft notice PRs when you run publish commands, but it does not autonomously mutate runtime infrastructure.
|
|
38
|
+
|
|
39
|
+
## One-Command Setup
|
|
40
|
+
### Org Initialization
|
|
41
|
+
Run this to initialize SDX for a GitHub org:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx --yes sdx-cli@latest bootstrap quick <org>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Default naming rule:
|
|
48
|
+
- org-only input uses `<org>-system-designer` as the design repo/workspace name.
|
|
49
|
+
- explicit `<org>/<design-repo>` remains fully supported as an override.
|
|
50
|
+
|
|
51
|
+
This requires `sdx-cli` to be available on npm.
|
|
52
|
+
|
|
53
|
+
Examples:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# default design repo name: <org>-system-designer
|
|
57
|
+
npx --yes sdx-cli@latest bootstrap quick dana0550
|
|
58
|
+
|
|
59
|
+
# explicit design repo name override
|
|
60
|
+
npx --yes sdx-cli@latest bootstrap quick dana0550/platform-architecture
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If npm publishing is not enabled yet in your org, use source mode:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git clone https://github.com/dana0550/system-desiigner.git
|
|
67
|
+
cd system-desiigner
|
|
68
|
+
npm ci && npm run build
|
|
69
|
+
node ./bin/run.js bootstrap quick <org>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This creates a dedicated workspace and a pinned wrapper script:
|
|
73
|
+
- `.sdx/config.json`
|
|
74
|
+
- `.sdx/install.json`
|
|
75
|
+
- `scripts/sdx`
|
|
76
|
+
|
|
77
|
+
Then run:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
cd ./<org>-system-designer
|
|
81
|
+
./scripts/sdx status
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Quick bootstrap flags
|
|
85
|
+
```bash
|
|
86
|
+
npx --yes sdx-cli@latest bootstrap quick dana0550 \
|
|
87
|
+
--seed \
|
|
88
|
+
--createRemote
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- `--seed`: auto-runs repo sync + default map seed (`all-services`) when `GITHUB_TOKEN` is present.
|
|
92
|
+
- `--createRemote` (alias: `--create-remote`): creates the design repo remotely (dedicated mode).
|
|
93
|
+
- `--inPlace` (alias: `--in-place`): initialize current directory instead of `./<design-repo>`.
|
|
94
|
+
- `--dir <path>`: override target directory.
|
|
95
|
+
- `--pin <version>`: pin wrapper to a specific CLI version.
|
|
96
|
+
|
|
97
|
+
## Daily Workflow
|
|
98
|
+
From your SDX workspace root:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
./scripts/sdx repo sync --org <org>
|
|
102
|
+
./scripts/sdx repo add --name <repo-name> --path </abs/path/to/local/clone>
|
|
103
|
+
|
|
104
|
+
./scripts/sdx map create platform-core --org <org>
|
|
105
|
+
./scripts/sdx map include platform-core repo-a repo-b
|
|
106
|
+
./scripts/sdx map exclude platform-core legacy-repo
|
|
107
|
+
./scripts/sdx map build platform-core
|
|
108
|
+
|
|
109
|
+
./scripts/sdx contracts extract --map platform-core
|
|
110
|
+
./scripts/sdx docs generate --map platform-core
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
For planning and rollout:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
./scripts/sdx plan review --map platform-core --plan ./plans/new-service.md
|
|
117
|
+
./scripts/sdx service propose --map platform-core --brief ./plans/new-service-brief.md
|
|
118
|
+
./scripts/sdx handoff draft --map platform-core --service payments-orchestrator
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For Codex:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
./scripts/sdx codex run implementation-plan --map platform-core --input ./plans/new-service.md
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Cross-Repo Tech-Lead PRs (Spec-System Native)
|
|
128
|
+
Use this flow when SDX should create real `CC-*` contract-change PRs in downstream repos that have spec-system initialized.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# 1) Publish contract-change assignments (draft PRs by default)
|
|
132
|
+
./scripts/sdx publish notices --map platform-core --source-repo spec-system
|
|
133
|
+
|
|
134
|
+
# optionally publish one CC only
|
|
135
|
+
./scripts/sdx publish notices --map platform-core --source-repo spec-system --contract-change-id CC-101
|
|
136
|
+
|
|
137
|
+
# service onboarding mode: build source CC (`change_type: service_added`) from plan, then publish downstream PRs
|
|
138
|
+
./scripts/sdx publish notices --map platform-core --source-repo spec-system \
|
|
139
|
+
--notice-type service \
|
|
140
|
+
--plan ./plans/new-service-notice.md
|
|
141
|
+
|
|
142
|
+
# make PRs ready-for-review instead of drafts
|
|
143
|
+
./scripts/sdx publish notices --map platform-core --source-repo spec-system --ready
|
|
144
|
+
|
|
145
|
+
# dry run preview
|
|
146
|
+
./scripts/sdx publish notices --map platform-core --source-repo spec-system --dry-run
|
|
147
|
+
|
|
148
|
+
# 2) Refresh lifecycle state from existing PR URLs
|
|
149
|
+
./scripts/sdx publish sync --map platform-core --source-repo spec-system
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Notes:
|
|
153
|
+
- SDX creates/updates target repo spec-system artifacts:
|
|
154
|
+
- `docs/CONTRACT_CHANGES.md`
|
|
155
|
+
- `docs/contracts/CC-###-<slug>.md`
|
|
156
|
+
- If a target repo is missing valid spec-system docs, publish fails fast with an explicit error.
|
|
157
|
+
- Source writeback still uses source sync PRs (no direct default-branch writes).
|
|
158
|
+
- Tokens need `contents:write` and `pull_requests:write` on source + target repos.
|
|
159
|
+
|
|
160
|
+
### Service Plan Requirements (`--notice-type service --plan <file>`)
|
|
161
|
+
The plan file must include these sections:
|
|
162
|
+
|
|
163
|
+
- `## Service Identity` with bullets for `service_id` and/or `name`
|
|
164
|
+
- `## Summary`
|
|
165
|
+
- `## Contract Surface`
|
|
166
|
+
- `## Compatibility and Migration Guidance`
|
|
167
|
+
- `## Target Repositories` with table columns: `repo | owner | context`
|
|
168
|
+
|
|
169
|
+
## Prompt-Driven Scope Edits
|
|
170
|
+
Preview first, apply second:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
./scripts/sdx prompt "exclude legacy-repo from map" --map platform-core
|
|
174
|
+
./scripts/sdx prompt "exclude legacy-repo from map" --map platform-core --apply
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## For Codex Agents
|
|
178
|
+
Use this minimal runbook when an agent needs architecture context quickly:
|
|
179
|
+
|
|
180
|
+
1. `./scripts/sdx status`
|
|
181
|
+
2. `./scripts/sdx map status <map-id>`
|
|
182
|
+
3. `./scripts/sdx map build <map-id>`
|
|
183
|
+
4. `./scripts/sdx contracts extract --map <map-id>`
|
|
184
|
+
5. `./scripts/sdx codex run <task-type> --map <map-id> --input <file>`
|
|
185
|
+
|
|
186
|
+
Where outputs land:
|
|
187
|
+
- `maps/<map-id>/service-map.json|md|mmd`
|
|
188
|
+
- `maps/<map-id>/contracts.json|md`
|
|
189
|
+
- `codex/context-packs/*.json`
|
|
190
|
+
- `codex/runs/*.md|json`
|
|
191
|
+
|
|
192
|
+
## Command Surface
|
|
193
|
+
```bash
|
|
194
|
+
sdx init
|
|
195
|
+
sdx bootstrap org
|
|
196
|
+
sdx bootstrap consumer
|
|
197
|
+
sdx bootstrap quick
|
|
198
|
+
|
|
199
|
+
sdx repo sync
|
|
200
|
+
sdx repo add
|
|
201
|
+
|
|
202
|
+
sdx map create|include|exclude|remove-override|status|build
|
|
203
|
+
sdx prompt
|
|
204
|
+
|
|
205
|
+
sdx contracts extract
|
|
206
|
+
sdx docs generate
|
|
207
|
+
sdx plan review
|
|
208
|
+
sdx service propose
|
|
209
|
+
sdx handoff draft
|
|
210
|
+
sdx publish notices|sync|wiki
|
|
211
|
+
sdx codex run
|
|
212
|
+
|
|
213
|
+
sdx status
|
|
214
|
+
sdx version
|
|
215
|
+
sdx migrate artifacts
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Full help:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
sdx --help
|
|
222
|
+
sdx <topic> --help
|
|
223
|
+
sdx <topic> <command> --help
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Release Process
|
|
227
|
+
This repo uses Changesets and releases from `main`.
|
|
228
|
+
|
|
229
|
+
- Add a changeset for user-facing changes:
|
|
230
|
+
- `npm run changeset`
|
|
231
|
+
- Merges to `main` trigger the release workflow.
|
|
232
|
+
- Workflow behavior:
|
|
233
|
+
- versions packages from pending changesets,
|
|
234
|
+
- commits and pushes the release version/changelog to `main`,
|
|
235
|
+
- publishes to npm,
|
|
236
|
+
- creates a GitHub Release tag (`vX.Y.Z`).
|
|
237
|
+
- Manual recovery mode:
|
|
238
|
+
- run the `release` workflow via `workflow_dispatch` with `publish_existing=true` to publish the current `package.json` version when prior npm publish failed.
|
|
239
|
+
- Publish prerequisites:
|
|
240
|
+
- configure npm auth for CI (`NPM_TOKEN` repo secret),
|
|
241
|
+
- allow workflow pushes to `main` under your branch protection policy.
|
|
242
|
+
|
|
243
|
+
Maintainer commands:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
npm run version-packages
|
|
247
|
+
npm run release
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Environment
|
|
251
|
+
```bash
|
|
252
|
+
export GITHUB_TOKEN=<token>
|
|
253
|
+
export CODEX_CMD=<optional-codex-binary-name>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Local Development
|
|
257
|
+
```bash
|
|
258
|
+
npm ci
|
|
259
|
+
npm run typecheck
|
|
260
|
+
npm test
|
|
261
|
+
npm run build
|
|
262
|
+
node ./bin/run.js --help
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## License
|
|
266
|
+
MIT
|
package/bin/dev.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const {spawnSync} = require('node:child_process')
|
|
4
|
+
const path = require('node:path')
|
|
5
|
+
|
|
6
|
+
const tsxBin = path.join(__dirname, '..', 'node_modules', '.bin', process.platform === 'win32' ? 'tsx.cmd' : 'tsx')
|
|
7
|
+
const result = spawnSync(tsxBin, ['src/index.ts', ...process.argv.slice(2)], {
|
|
8
|
+
stdio: 'inherit',
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
process.exit(result.status ?? 1)
|
package/bin/run.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const bootstrapConsumer_1 = require("../../lib/bootstrapConsumer");
|
|
5
|
+
class BootstrapConsumerCommand extends core_1.Command {
|
|
6
|
+
static description = 'Initialize an sdx workspace for use in another org/repository';
|
|
7
|
+
static flags = {
|
|
8
|
+
org: core_1.Flags.string({ char: 'o', required: true, description: 'GitHub organization name' }),
|
|
9
|
+
designRepo: core_1.Flags.string({
|
|
10
|
+
required: true,
|
|
11
|
+
aliases: ['design-repo'],
|
|
12
|
+
description: 'Design repository name for this sdx instance',
|
|
13
|
+
}),
|
|
14
|
+
mode: core_1.Flags.string({
|
|
15
|
+
options: ['dedicated', 'in-place'],
|
|
16
|
+
default: 'dedicated',
|
|
17
|
+
description: 'Bootstrap mode (default dedicated repo, optional in-place repo initialization)',
|
|
18
|
+
}),
|
|
19
|
+
targetDir: core_1.Flags.string({
|
|
20
|
+
required: false,
|
|
21
|
+
aliases: ['target-dir'],
|
|
22
|
+
description: 'Optional target directory (default: ./<design-repo> for dedicated, . for in-place)',
|
|
23
|
+
}),
|
|
24
|
+
pin: core_1.Flags.string({
|
|
25
|
+
required: false,
|
|
26
|
+
description: 'Pin wrapper script to a specific sdx-cli version (defaults to current CLI package version)',
|
|
27
|
+
}),
|
|
28
|
+
seedDefaultMap: core_1.Flags.boolean({
|
|
29
|
+
default: false,
|
|
30
|
+
aliases: ['seed-default-map'],
|
|
31
|
+
description: 'Seed all-services map by running repo sync + map create + map build',
|
|
32
|
+
}),
|
|
33
|
+
createRemote: core_1.Flags.boolean({
|
|
34
|
+
default: false,
|
|
35
|
+
aliases: ['create-remote'],
|
|
36
|
+
description: 'Create the remote design repository in GitHub (dedicated mode only)',
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
async run() {
|
|
40
|
+
const { flags } = await this.parse(BootstrapConsumerCommand);
|
|
41
|
+
const result = await (0, bootstrapConsumer_1.bootstrapConsumer)({
|
|
42
|
+
org: flags.org,
|
|
43
|
+
designRepo: flags.designRepo,
|
|
44
|
+
mode: flags.mode,
|
|
45
|
+
targetDir: flags.targetDir,
|
|
46
|
+
pin: flags.pin,
|
|
47
|
+
seedDefaultMap: flags.seedDefaultMap,
|
|
48
|
+
createRemote: flags.createRemote,
|
|
49
|
+
cwd: process.cwd(),
|
|
50
|
+
});
|
|
51
|
+
this.log(`Consumer bootstrap complete.`);
|
|
52
|
+
this.log(`Target directory: ${result.targetDir}`);
|
|
53
|
+
this.log(`Mode: ${result.mode}`);
|
|
54
|
+
this.log(`Pinned CLI version: ${result.pinnedVersion}`);
|
|
55
|
+
if (result.remoteUrl) {
|
|
56
|
+
this.log(`Remote repository: ${result.remoteUrl} (${result.remoteCreated ? 'created' : 'already existed'})`);
|
|
57
|
+
}
|
|
58
|
+
if (result.seededDefaultMap) {
|
|
59
|
+
this.log(`Seeded map: all-services`);
|
|
60
|
+
}
|
|
61
|
+
if (result.warnings.length > 0) {
|
|
62
|
+
this.log('Warnings:');
|
|
63
|
+
for (const warning of result.warnings) {
|
|
64
|
+
this.log(`- ${warning}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (result.nextSteps.length > 0) {
|
|
68
|
+
this.log('Next steps:');
|
|
69
|
+
for (const step of result.nextSteps) {
|
|
70
|
+
this.log(`- ${step}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.default = BootstrapConsumerCommand;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const bootstrap_1 = require("../../lib/bootstrap");
|
|
5
|
+
const project_1 = require("../../lib/project");
|
|
6
|
+
const config_1 = require("../../lib/config");
|
|
7
|
+
class BootstrapOrgCommand extends core_1.Command {
|
|
8
|
+
static description = 'Bootstrap this repository as an org-level system design workspace';
|
|
9
|
+
static flags = {
|
|
10
|
+
org: core_1.Flags.string({ char: 'o', required: true, description: 'GitHub organization name' }),
|
|
11
|
+
repo: core_1.Flags.string({ char: 'r', required: true, description: 'Design repository name' }),
|
|
12
|
+
};
|
|
13
|
+
static args = {
|
|
14
|
+
target: core_1.Args.string({ required: false, description: 'Optional reserved positional arg' }),
|
|
15
|
+
};
|
|
16
|
+
async run() {
|
|
17
|
+
const { flags } = await this.parse(BootstrapOrgCommand);
|
|
18
|
+
const context = (0, project_1.loadProject)(process.cwd());
|
|
19
|
+
(0, bootstrap_1.createBootstrapStructure)(flags.org, flags.repo, context.cwd);
|
|
20
|
+
context.config.outputRepo.org = flags.org;
|
|
21
|
+
context.config.outputRepo.repo = flags.repo;
|
|
22
|
+
context.config.github.defaultOrg = flags.org;
|
|
23
|
+
(0, config_1.saveConfig)(context.config, context.cwd);
|
|
24
|
+
(0, project_1.recordRun)(context.db, 'bootstrap_org', 'ok', undefined, { org: flags.org, repo: flags.repo });
|
|
25
|
+
context.db.close();
|
|
26
|
+
this.log(`Bootstrapped for org '${flags.org}' and design repo '${flags.repo}'.`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.default = BootstrapOrgCommand;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const bootstrapConsumer_1 = require("../../lib/bootstrapConsumer");
|
|
5
|
+
const bootstrapQuick_1 = require("../../lib/bootstrapQuick");
|
|
6
|
+
class BootstrapQuickCommand extends core_1.Command {
|
|
7
|
+
static description = 'One-command bootstrap for a consumer workspace';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> <%= command.id %> dana0550',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> dana0550/dana0550-system-designer --seed',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
target: core_1.Args.string({
|
|
14
|
+
required: true,
|
|
15
|
+
description: 'GitHub org or org/design-repo target',
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
static flags = {
|
|
19
|
+
inPlace: core_1.Flags.boolean({
|
|
20
|
+
default: false,
|
|
21
|
+
aliases: ['in-place'],
|
|
22
|
+
description: 'Initialize in the current directory instead of creating ./<design-repo>',
|
|
23
|
+
}),
|
|
24
|
+
dir: core_1.Flags.string({
|
|
25
|
+
required: false,
|
|
26
|
+
description: 'Optional target directory override',
|
|
27
|
+
}),
|
|
28
|
+
pin: core_1.Flags.string({
|
|
29
|
+
required: false,
|
|
30
|
+
description: 'Optional pinned sdx-cli version for scripts/sdx wrapper',
|
|
31
|
+
}),
|
|
32
|
+
seed: core_1.Flags.boolean({
|
|
33
|
+
default: false,
|
|
34
|
+
description: 'Seed all-services map after bootstrap (requires GITHUB_TOKEN)',
|
|
35
|
+
}),
|
|
36
|
+
createRemote: core_1.Flags.boolean({
|
|
37
|
+
default: false,
|
|
38
|
+
aliases: ['create-remote'],
|
|
39
|
+
description: 'Create remote design repo in GitHub (dedicated mode only)',
|
|
40
|
+
}),
|
|
41
|
+
};
|
|
42
|
+
async run() {
|
|
43
|
+
const { args, flags } = await this.parse(BootstrapQuickCommand);
|
|
44
|
+
const target = (0, bootstrapQuick_1.parseBootstrapQuickTarget)(args.target);
|
|
45
|
+
const mode = flags.inPlace ? 'in-place' : 'dedicated';
|
|
46
|
+
const result = await (0, bootstrapConsumer_1.bootstrapConsumer)({
|
|
47
|
+
org: target.org,
|
|
48
|
+
designRepo: target.designRepo,
|
|
49
|
+
mode,
|
|
50
|
+
targetDir: flags.dir,
|
|
51
|
+
pin: flags.pin,
|
|
52
|
+
seedDefaultMap: flags.seed,
|
|
53
|
+
createRemote: flags.createRemote,
|
|
54
|
+
cwd: process.cwd(),
|
|
55
|
+
});
|
|
56
|
+
this.log('Bootstrap complete.');
|
|
57
|
+
this.log(`Design repo: ${target.designRepo}`);
|
|
58
|
+
this.log(`Workspace: ${result.targetDir}`);
|
|
59
|
+
this.log(`Pinned version: ${result.pinnedVersion}`);
|
|
60
|
+
this.log(`Wrapper: ${result.targetDir}/scripts/sdx`);
|
|
61
|
+
this.log('');
|
|
62
|
+
this.log('Start here:');
|
|
63
|
+
this.log(`- cd ${result.targetDir}`);
|
|
64
|
+
this.log('- ./scripts/sdx status');
|
|
65
|
+
this.log('- ./scripts/sdx repo sync --org <org>');
|
|
66
|
+
if (result.seededDefaultMap) {
|
|
67
|
+
this.log('- ./scripts/sdx map status all-services');
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.log('- ./scripts/sdx map create all-services --org <org>');
|
|
71
|
+
this.log('- ./scripts/sdx map build all-services');
|
|
72
|
+
}
|
|
73
|
+
if (result.warnings.length > 0) {
|
|
74
|
+
this.log('');
|
|
75
|
+
this.log('Warnings:');
|
|
76
|
+
for (const warning of result.warnings) {
|
|
77
|
+
this.log(`- ${warning}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.default = BootstrapQuickCommand;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const codex_1 = require("../../lib/codex");
|
|
5
|
+
const project_1 = require("../../lib/project");
|
|
6
|
+
class CodexRunCommand extends core_1.Command {
|
|
7
|
+
static description = 'Run Codex CLI with generated architecture context pack';
|
|
8
|
+
static flags = {
|
|
9
|
+
map: core_1.Flags.string({ required: true, description: 'Map identifier' }),
|
|
10
|
+
input: core_1.Flags.string({ required: false, description: 'Optional additional input file path' }),
|
|
11
|
+
};
|
|
12
|
+
static args = {
|
|
13
|
+
taskType: core_1.Args.string({ required: true, description: 'Codex task type label' }),
|
|
14
|
+
};
|
|
15
|
+
async run() {
|
|
16
|
+
const { args, flags } = await this.parse(CodexRunCommand);
|
|
17
|
+
const context = (0, project_1.loadProject)(process.cwd());
|
|
18
|
+
const result = (0, codex_1.runCodexTask)({
|
|
19
|
+
mapId: flags.map,
|
|
20
|
+
taskType: args.taskType,
|
|
21
|
+
codexCommand: context.config.codex.cmd,
|
|
22
|
+
inputFile: flags.input,
|
|
23
|
+
cwd: context.cwd,
|
|
24
|
+
});
|
|
25
|
+
(0, project_1.recordRun)(context.db, 'codex_run', result.exitCode === 0 ? 'ok' : 'error', flags.map, result);
|
|
26
|
+
context.db.close();
|
|
27
|
+
this.log(`Codex run completed with exit code ${result.exitCode}.`);
|
|
28
|
+
this.log(`Context pack: ${result.contextPackPath}`);
|
|
29
|
+
this.log(`Prompt file: ${result.promptPath}`);
|
|
30
|
+
this.log(`Run output: ${result.runMarkdownPath}`);
|
|
31
|
+
if (result.exitCode !== 0) {
|
|
32
|
+
throw new Error(`Codex run failed with non-zero exit code ${result.exitCode}. See ${result.runMarkdownPath}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.default = CodexRunCommand;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const project_1 = require("../../lib/project");
|
|
5
|
+
const workflows_1 = require("../../lib/workflows");
|
|
6
|
+
class ContractsExtractCommand extends core_1.Command {
|
|
7
|
+
static description = 'Extract and catalog API/event contracts for a map scope';
|
|
8
|
+
static flags = {
|
|
9
|
+
map: core_1.Flags.string({ required: true, description: 'Map identifier' }),
|
|
10
|
+
};
|
|
11
|
+
async run() {
|
|
12
|
+
const { flags } = await this.parse(ContractsExtractCommand);
|
|
13
|
+
const context = (0, project_1.loadProject)(process.cwd());
|
|
14
|
+
const result = (0, workflows_1.extractContractArtifacts)(flags.map, context.db, context.cwd);
|
|
15
|
+
(0, project_1.recordRun)(context.db, 'contracts_extract', 'ok', flags.map, { count: result.count });
|
|
16
|
+
context.db.close();
|
|
17
|
+
this.log(`Extracted ${result.count} contracts for map '${flags.map}'.`);
|
|
18
|
+
this.log(`JSON: ${result.jsonPath}`);
|
|
19
|
+
this.log(`Markdown: ${result.markdownPath}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.default = ContractsExtractCommand;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const project_1 = require("../../lib/project");
|
|
5
|
+
const workflows_1 = require("../../lib/workflows");
|
|
6
|
+
class DocsGenerateCommand extends core_1.Command {
|
|
7
|
+
static description = 'Generate architecture docs and dependency notes for a map';
|
|
8
|
+
static flags = {
|
|
9
|
+
map: core_1.Flags.string({ required: true, description: 'Map identifier' }),
|
|
10
|
+
};
|
|
11
|
+
async run() {
|
|
12
|
+
const { flags } = await this.parse(DocsGenerateCommand);
|
|
13
|
+
const context = (0, project_1.loadProject)(process.cwd());
|
|
14
|
+
const result = (0, workflows_1.generateDocsArtifacts)(flags.map, context.db, context.cwd);
|
|
15
|
+
(0, project_1.recordRun)(context.db, 'docs_generate', 'ok', flags.map, result);
|
|
16
|
+
context.db.close();
|
|
17
|
+
this.log(`Generated docs for map '${flags.map}'.`);
|
|
18
|
+
this.log(`Architecture: ${result.architecturePath}`);
|
|
19
|
+
this.log(`Dependencies: ${result.dependencyPath}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.default = DocsGenerateCommand;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
7
|
+
const core_1 = require("@oclif/core");
|
|
8
|
+
const contracts_1 = require("../../lib/contracts");
|
|
9
|
+
const fs_1 = require("../../lib/fs");
|
|
10
|
+
const handoff_1 = require("../../lib/handoff");
|
|
11
|
+
const project_1 = require("../../lib/project");
|
|
12
|
+
const repoRegistry_1 = require("../../lib/repoRegistry");
|
|
13
|
+
const scope_1 = require("../../lib/scope");
|
|
14
|
+
class HandoffDraftCommand extends core_1.Command {
|
|
15
|
+
static description = 'Generate per-repository handoff integration drafts for a new service';
|
|
16
|
+
static flags = {
|
|
17
|
+
map: core_1.Flags.string({ required: true, description: 'Map identifier' }),
|
|
18
|
+
service: core_1.Flags.string({ required: true, description: 'New service identifier' }),
|
|
19
|
+
};
|
|
20
|
+
async run() {
|
|
21
|
+
const { flags } = await this.parse(HandoffDraftCommand);
|
|
22
|
+
const context = (0, project_1.loadProject)(process.cwd());
|
|
23
|
+
const scope = (0, scope_1.loadScopeManifest)(flags.map, context.cwd);
|
|
24
|
+
const repoMap = new Map((0, repoRegistry_1.listAllRepos)(context.db).map((repo) => [repo.name, repo]));
|
|
25
|
+
const contracts = (0, contracts_1.extractContracts)(flags.map, scope, repoMap);
|
|
26
|
+
const handoff = (0, handoff_1.buildHandoff)(flags.map, flags.service, scope, contracts);
|
|
27
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
28
|
+
const outJsonPath = node_path_1.default.join(context.cwd, 'handoffs', `${stamp}-${flags.map}-${flags.service}.json`);
|
|
29
|
+
const outMdPath = node_path_1.default.join(context.cwd, 'handoffs', `${stamp}-${flags.map}-${flags.service}.md`);
|
|
30
|
+
(0, fs_1.writeJsonFile)(outJsonPath, handoff);
|
|
31
|
+
(0, fs_1.writeTextFile)(outMdPath, (0, handoff_1.renderHandoffMarkdown)(handoff));
|
|
32
|
+
(0, project_1.recordRun)(context.db, 'handoff_draft', 'ok', flags.map, {
|
|
33
|
+
service: flags.service,
|
|
34
|
+
targets: handoff.targets.length,
|
|
35
|
+
output: outMdPath,
|
|
36
|
+
});
|
|
37
|
+
context.db.close();
|
|
38
|
+
this.log(`Handoff draft generated: ${outMdPath}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.default = HandoffDraftCommand;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const project_1 = require("../lib/project");
|
|
5
|
+
class InitCommand extends core_1.Command {
|
|
6
|
+
static description = 'Initialize sdx config, database, and output directories';
|
|
7
|
+
async run() {
|
|
8
|
+
const context = (0, project_1.initProject)(process.cwd());
|
|
9
|
+
context.db.close();
|
|
10
|
+
this.log('Initialized sdx workspace.');
|
|
11
|
+
this.log(`Root: ${context.rootDir}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.default = InitCommand;
|