@julioborges/gantry 0.1.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 (46) hide show
  1. package/.agents/skills/gantry/SKILL.md +166 -0
  2. package/.agents/skills/gantry/capabilities/claude-code.json +15 -0
  3. package/.agents/skills/gantry/capabilities/codex.json +14 -0
  4. package/.agents/skills/gantry/capabilities/opencode.json +15 -0
  5. package/.agents/skills/gantry/dashboard/static/app.js +100 -0
  6. package/.agents/skills/gantry/dashboard/static/index.html +16 -0
  7. package/.agents/skills/gantry/dashboard/static/style.css +74 -0
  8. package/.agents/skills/gantry/hooks/claude-code.settings.json +56 -0
  9. package/.agents/skills/gantry/hooks/codex.hooks.json +4 -0
  10. package/.agents/skills/gantry/hooks/git/pre-commit +77 -0
  11. package/.agents/skills/gantry/hooks/git/pre-push +123 -0
  12. package/.agents/skills/gantry/hooks/git/skipscan.py +88 -0
  13. package/.agents/skills/gantry/hooks/opencode.plugin.js +44 -0
  14. package/.agents/skills/gantry/reference/plan-workflow.md +383 -0
  15. package/.agents/skills/gantry/reference/round-workflow.md +755 -0
  16. package/.agents/skills/gantry/schemas/critic.json +93 -0
  17. package/.agents/skills/gantry/schemas/implementer.json +52 -0
  18. package/.agents/skills/gantry/schemas/learner.json +35 -0
  19. package/.agents/skills/gantry/schemas/plan-critic.json +39 -0
  20. package/.agents/skills/gantry/schemas/planner.json +64 -0
  21. package/.agents/skills/gantry/schemas/requirement-critic.json +48 -0
  22. package/.agents/skills/gantry/schemas/reviewer.json +52 -0
  23. package/.agents/skills/gantry/scripts/acceptance.py +66 -0
  24. package/.agents/skills/gantry/scripts/budget.py +162 -0
  25. package/.agents/skills/gantry/scripts/cleanup.py +186 -0
  26. package/.agents/skills/gantry/scripts/common.py +361 -0
  27. package/.agents/skills/gantry/scripts/dashboard.py +233 -0
  28. package/.agents/skills/gantry/scripts/frontier.py +192 -0
  29. package/.agents/skills/gantry/scripts/gates.py +401 -0
  30. package/.agents/skills/gantry/scripts/guard.py +568 -0
  31. package/.agents/skills/gantry/scripts/learner.py +99 -0
  32. package/.agents/skills/gantry/scripts/result.py +104 -0
  33. package/.agents/skills/gantry/scripts/roadmap.py +212 -0
  34. package/.agents/skills/gantry/scripts/runlog.py +491 -0
  35. package/.agents/skills/gantry/scripts/setup.py +139 -0
  36. package/.agents/skills/gantry/scripts/spec.py +252 -0
  37. package/.agents/skills/gantry/templates/issue.md +32 -0
  38. package/.agents/skills/gantry/templates/prd.md +26 -0
  39. package/.agents/skills/gantry/templates/spec.md +48 -0
  40. package/.agents/skills/gantry-dashboard/SKILL.md +55 -0
  41. package/.agents/skills/gantry-setup/SKILL.md +30 -0
  42. package/LICENSE +201 -0
  43. package/README.md +437 -0
  44. package/bin/gantry.mjs +45 -0
  45. package/package.json +36 -0
  46. package/scripts/ensure-npm-author.mjs +29 -0
package/README.md ADDED
@@ -0,0 +1,437 @@
1
+ # Gantry
2
+
3
+ **Turn an approved Spec into verified software deliveries inside your coding
4
+ harness.**
5
+
6
+ [![License: Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
7
+ [![Python: 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](#requirements)
8
+ [![Agent Skills](https://img.shields.io/badge/Agent-Skills-orange.svg)](#installation)
9
+ [![Status: early development](https://img.shields.io/badge/status-early%20development-yellow.svg)](#project-status)
10
+
11
+ Gantry is an open source, harness-neutral skill pack for agentic software
12
+ development. Deterministic scripts decide which Issues are ready and whether
13
+ checks pass. Fresh agents implement, review, and challenge each delivery. You
14
+ approve the plan and decide how the resulting Run is handed off.
15
+
16
+ [Get started](#quick-start) · [Greenfield example](#greenfield-build-a-new-project) ·
17
+ [Brownfield example](#brownfield-extend-an-existing-project) ·
18
+ [Contribute](#contributing)
19
+
20
+ ## Why Gantry?
21
+
22
+ Agent-written code needs more than a passing test suite and a completion summary.
23
+ Gantry gives each delivery a repeatable path from requirements to independent
24
+ verification:
25
+
26
+ - **Plan before building.** Validate the Spec, create vertical-slice Issues, and
27
+ critique the breakdown before asking for your approval.
28
+ - **Verify independently.** A fresh Critic runs acceptance checks and real
29
+ repository gates, demanding evidence for every criterion.
30
+ - **Respect dependencies.** Scripts compute readiness from the blocker graph;
31
+ accepted branches integrate serially with gates after every merge.
32
+ - **Track delivery in Git.** Markdown Issues and `ROADMAP.md` record completion;
33
+ only the roadmap script updates authoritative status and checkboxes.
34
+ - **Keep decisions in your harness.** Review plans, proposed lessons, draft PRs,
35
+ and cleanup without a separate execution service.
36
+
37
+ Named after the [gantry crane](https://en.wikipedia.org/wiki/Gantry_crane), the
38
+ pack provides the rails for the work. See [ADR-0004](docs/adr/0004-skill-pack-instead-of-an-engine.md)
39
+ for the product boundary.
40
+
41
+ ## Project status
42
+
43
+ The canonical pack lives in `.agents/skills/`. Gantry is under active development.
44
+ Capability files declare harness tiers; fixture validation is required before
45
+ claiming support for a particular integration. See [PRD §13](PRD.md#13-harness-support)
46
+ for harness support and fixture requirements. A declared tier does not prove every harness version
47
+ has been exercised.
48
+
49
+ The npm installer is configured locally as `@julioborges/gantry` version `0.1.0`;
50
+ publication is a separate release step. Use the GitHub installation below until
51
+ an npm release is available.
52
+
53
+ ## Requirements
54
+
55
+ | Component | Requirement |
56
+ |---|---|
57
+ | Workflow | Python 3.10+ and Git |
58
+ | Agent environment | A coding harness that can load skills and run commands |
59
+ | npm installer | Node.js 22.20.0+ |
60
+ | Draft Run PR (optional) | `gh`, authenticated with access to the repository |
61
+ | Project checks | Your project's own toolchain and dependencies |
62
+
63
+ Gantry's workflow scripts use only the Python standard library. Your project's
64
+ checks can require additional tools. Keep the host harness open during a Run;
65
+ Gantry does not continue as a background service.
66
+
67
+ ## Installation
68
+
69
+ Run this in the project where you want to use Gantry:
70
+
71
+ ```bash
72
+ npx skills add JulioBorges/gantry
73
+ ```
74
+
75
+ Select all three skills and your harness in the installer:
76
+
77
+ | Skill | Purpose |
78
+ |---|---|
79
+ | `gantry-setup` | Configure artifact locations, templates, checks, Git policy, and hooks |
80
+ | `gantry` | Plan and execute verified Issues |
81
+ | `gantry-dashboard` | Open the read-only kanban for recorded Runs |
82
+
83
+ You can also copy or symlink the three directories into
84
+ `<repo>/.agents/skills/` or `~/.agents/skills/`. The repository copy wins.
85
+
86
+ Once the npm package is published, its bundled installer supports:
87
+
88
+ ```bash
89
+ npx @julioborges/gantry add
90
+ npx @julioborges/gantry add --agent codex --yes
91
+ npx @julioborges/gantry add --global
92
+ npx @julioborges/gantry add --list
93
+ ```
94
+
95
+ `add` delegates to a pinned version of the [skills CLI](https://github.com/vercel-labs/skills)
96
+ using the bundled files. Agent selection and global installation options pass
97
+ through unchanged. The npm command installs skills; it does not execute a Run.
98
+
99
+ ## Quick start
100
+
101
+ After installation, open your coding harness in the repository and send:
102
+
103
+ ```text
104
+ Use gantry-setup to configure this repository. Present the proposed artifact
105
+ locations, templates, check commands, Git target, and hook settings for approval
106
+ before applying the policy.
107
+ ```
108
+
109
+ Approve the reviewed setup, prepare a Spec using the
110
+ [default template](.agents/skills/gantry/templates/spec.md) or your repository's
111
+ configured equivalent, and commit the setup and Spec. Start from a clean Git
112
+ working tree, then send:
113
+
114
+ ```text
115
+ Use gantry for Spec delivery-api. Validate the Spec and prepare the Issue
116
+ breakdown. Stop for my planning approval before implementation.
117
+ ```
118
+
119
+ Review the resulting Issues, criteria, dependencies, and plan critique. If you
120
+ accept that particular breakdown, send:
121
+
122
+ ```text
123
+ I approve the delivery-api Spec and the Issue breakdown just presented.
124
+ Use gantry delivery-api --limit 4 --budget 2 to execute all approved Issues.
125
+ ```
126
+
127
+ These are **prompts in your coding harness**, not terminal commands. Use its
128
+ skill invocation syntax when available, or explicitly name the skill in prose.
129
+ `delivery-api` identifies your Spec scope, normally
130
+ `.scratch/delivery-api/spec.md`; it is not a filename to copy verbatim.
131
+
132
+ ## Complete execution examples
133
+
134
+ The examples below cover setup, Spec preparation, planning approval,
135
+ implementation, and handoff. Spec authoring happens before the Gantry Run;
136
+ Gantry reads and critiques the Spec rather than rewriting it.
137
+
138
+ ### Greenfield: build a new project
139
+
140
+ Build a small Python CLI that adds and lists tasks in a local JSON file. Start
141
+ with an initial Git commit so the Run has a target branch to branch from:
142
+
143
+ ```bash
144
+ mkdir task-cli
145
+ cd task-cli
146
+ git init -b main
147
+ printf '# Task CLI\n' > README.md
148
+ git add README.md
149
+ git commit -m "Initialize task CLI repository"
150
+ npx skills add JulioBorges/gantry
151
+ ```
152
+
153
+ **1. Configure the repository.** Open your harness in `task-cli` and send:
154
+
155
+ ```text
156
+ Use gantry-setup for this new Python project. Propose main as the Git target,
157
+ .scratch/<slug>/ for Specs and Issues, and unittest discovery as the test gate.
158
+ There is no test suite yet: identify the bootstrap requirement, and do not
159
+ accept no_gates or an empty test run as proof of completion. Present the full
160
+ policy and hook choices before writing them.
161
+ ```
162
+
163
+ Review and approve the proposed policy. The bootstrap Issue must establish and
164
+ exercise meaningful tests before it can complete.
165
+
166
+ **2. Prepare the Spec outside the Run.** Create
167
+ `.scratch/task-cli/spec.md` from the effective template and fill every required
168
+ section. Define these outcomes and boundaries:
169
+
170
+ - `python3 -m task_cli add "Buy milk" --file tasks.json` creates a stored task
171
+ with a unique ID and reports it to the user.
172
+ - `python3 -m task_cli list --file tasks.json` lists stored tasks; a missing file
173
+ produces an empty list without an error.
174
+ - Tasks persist across separate CLI invocations. Empty titles and malformed JSON
175
+ produce a clear error and a nonzero exit code without overwriting stored data.
176
+ - Tests exercise the CLI with temporary files. No network, accounts, task
177
+ deletion, or UI is included.
178
+
179
+ Include observable Given/When/Then scenarios and regression guardrails in the
180
+ Spec. Commit the installation files, approved setup, and completed Spec before
181
+ starting the Run.
182
+
183
+ **3. Request and review the plan.** Send:
184
+
185
+ ```text
186
+ Use gantry task-cli --limit 2 --budget 2. Validate the Spec and prepare vertical
187
+ slices covering every outcome, including bootstrap tests. Show the dependencies
188
+ and plan critique, then stop for my approval.
189
+ ```
190
+
191
+ A possible breakdown is an add-and-persist slice with real tests, followed by a
192
+ list-and-error-handling slice. Review the actual generated plan rather than
193
+ assuming these example slices are authoritative. Amend the Spec if Requirement
194
+ Review finds a blocker, then request planning again.
195
+
196
+ **4. Approve the concrete plan and execute.** After reviewing the draft Issues:
197
+
198
+ ```text
199
+ I approve the task-cli Spec and the exact Issue breakdown just presented.
200
+ Use gantry task-cli --limit 2 --budget 2 to execute the approved scope in a
201
+ dedicated Run worktree. Keep the bootstrap test gate meaningful.
202
+ ```
203
+
204
+ Answer the preflight worktree and model choices. Gantry schedules ready Issues,
205
+ implements each with TDD, reviews it, runs independent Critic verification, and
206
+ integrates accepted work into the Run branch. Successful rounds advance until
207
+ the scope completes; a failed round stops with evidence and preserved work.
208
+
209
+ **5. Review the handoff.** Expect criterion evidence, integration gate results,
210
+ updated Issues and roadmap, the declared support tier, remaining frontier,
211
+ optional lesson candidates, and a cleanup plan. If you want the offered PR:
212
+
213
+ ```text
214
+ Open the draft Run pull request from the reported Run branch to main using the
215
+ verified delivery evidence. Leave merging for my review.
216
+ ```
217
+
218
+ If `gh` is unavailable, the Run branch is the handoff. Review the proposed
219
+ cleanup separately before authorizing removal of any branches or worktrees.
220
+
221
+ ### Brownfield: extend an existing project
222
+
223
+ Add pagination to an existing `GET /orders` endpoint while preserving its
224
+ current behavior for clients that do not request pagination.
225
+
226
+ **1. Establish the baseline and install.** In your existing repository, review
227
+ `git status`, resolve uncommitted work, install project dependencies, and run the
228
+ current checks using the repository's documented commands. Then install Gantry:
229
+
230
+ ```bash
231
+ npx skills add JulioBorges/gantry
232
+ ```
233
+
234
+ **2. Adapt setup to existing conventions.** Open your harness and send:
235
+
236
+ ```text
237
+ Use gantry-setup for this existing repository. Inspect AGENTS.md, the canonical
238
+ Specs and Issues, ADRs, test commands, and target branch. Reuse those locations
239
+ and templates; propose equivalent heading mappings where needed. Preserve
240
+ existing hooks and present any conflicts. Show the full proposed policy before
241
+ writing it. Keep tests absolute; offer differential checks only where real
242
+ structured output supports comparison.
243
+ ```
244
+
245
+ Approve the concrete settings. Existing debt in a differential check remains
246
+ visible; new or aggravated findings block. An absolute check still has to pass.
247
+ Setup does not waive a failing baseline or approve the feature plan.
248
+
249
+ **3. Prepare or adapt the canonical Spec.** Use the agreed location and template
250
+ for the `orders-pagination` scope. Include these explicit behaviors:
251
+
252
+ - Requests without pagination parameters keep the existing response shape,
253
+ ordering, and authorization behavior.
254
+ - Requests with `page` and `pageSize` return the agreed paginated contract,
255
+ including stable ordering and the defined metadata.
256
+ - Invalid values return the repository's standard client error. Define default
257
+ values, maximum page size, and out-of-range behavior in the Spec.
258
+ - Existing clients and access restrictions have regression scenarios. Tests use
259
+ the repository's established integration fixtures and required real services.
260
+ - No schema migration, authorization redesign, or unrelated refactoring is
261
+ included.
262
+
263
+ Replace every undecided detail with an agreed value before planning. If an
264
+ existing Spec is missing required content, review and amend it in its canonical
265
+ format. Commit the installation, approved setup, and Spec so preflight sees a
266
+ clean working tree.
267
+
268
+ **4. Plan, approve, and execute.** Send:
269
+
270
+ ```text
271
+ Use gantry orders-pagination --limit 2 --budget 2. Validate the canonical Spec,
272
+ inspect existing endpoint and integration tests, and propose vertical slices
273
+ with compatibility criteria. Stop after the plan critique for my approval.
274
+ ```
275
+
276
+ After reviewing that exact breakdown, send:
277
+
278
+ ```text
279
+ I approve the orders-pagination Spec and the Issue breakdown just presented.
280
+ Use gantry orders-pagination --limit 2 --budget 2 in a dedicated Run worktree.
281
+ Execute the approved scope with the configured gates and regression checks.
282
+ ```
283
+
284
+ Answer the worktree and model choices. Each accepted Issue integrates into the
285
+ Run branch serially; gates run after every merge. A red integration gate stops
286
+ the Run. Changes to approved behavior or dependencies require a plan amendment.
287
+
288
+ **5. Inspect results and resume when needed.** Review the same evidence-backed
289
+ handoff described in the greenfield example. To revisit an interrupted scope:
290
+
291
+ ```text
292
+ Use gantry orders-pagination. Report remaining ready and blocked Issues and
293
+ any in-flight worktrees. Offer continuation in the preserved worktree before
294
+ starting new work, retaining correction attempts already spent.
295
+ ```
296
+
297
+ Continuation is an operator choice, not an automatic budget reset. Once the
298
+ scope completes, explicitly authorize the offered draft Run PR if desired,
299
+ review it under the repository's normal process, and approve cleanup separately.
300
+
301
+ ## How a Run works
302
+
303
+ ```text
304
+ Preflight → Spec validation → Requirement Review → Plan → Plan critique
305
+
306
+ Operator approval
307
+
308
+ Ready Issues → Implement (TDD) → Review → Critic → Serial integration
309
+ ↑ │ + gates
310
+ └── bounded corrections ┘ ↓
311
+ Roadmap update
312
+
313
+ Next round or final report + PR offer
314
+ ```
315
+
316
+ Already planned scopes skip planning. `--limit` caps Issues per round (default
317
+ 4); `--budget` caps Critic correction attempts per Issue (default 2). The single
318
+ review fix pass is separate. These limits do not approve a plan or restrict a
319
+ Run to a single round.
320
+
321
+ | Scope | Meaning |
322
+ |---|---|
323
+ | `delivery-api` | One Spec's Issues |
324
+ | `delivery-api#01` | One Issue |
325
+ | `wave:1` | A roadmap wave |
326
+ | `frontier` | Currently ready work |
327
+ | `all` | All discovered Issues |
328
+ | `"free-text goal"` | Unplanned scope; draft planning stops for approval |
329
+
330
+ Workflow scripts own readiness (`frontier.py`), criteria (`acceptance.py`),
331
+ gates (`gates.py`), Spec structure (`spec.py`), context estimates (`budget.py`),
332
+ result validation (`result.py`), and status updates (`roadmap.py`). Guard hooks
333
+ block shortcuts and record events; they never grant completion.
334
+
335
+ Only Critic acceptance, passing gates, and a clean worktree permit completion.
336
+ Gantry offers one draft PR per Run after explicit approval. It never merges
337
+ into the target branch. Lessons stay proposals, and cleanup requires approval
338
+ of the printed plan.
339
+
340
+ ## Harness capabilities
341
+
342
+ The current [capability files](.agents/skills/gantry/capabilities/) declare:
343
+
344
+ | Tier | Harness | Declared capabilities |
345
+ |---|---|---|
346
+ | Reference | Claude Code | Parallel rounds, native structured output, worktree isolation, per-role models, hooks |
347
+ | Supported | OpenCode | Per-role models and plugin hooks; script-validated results; manually managed isolation |
348
+ | Compatible | Codex | Manually driven chain and script-validated results; no hooks or native parallel rounds declared |
349
+
350
+ Use the host's available features without assuming parity. Every final Run
351
+ report states its declared tier. Gantry does not provide session security or
352
+ output redaction; apply your harness's policy layer for those concerns.
353
+
354
+ ## Dashboard and artifacts
355
+
356
+ Ask your harness to `use gantry-dashboard` to open the read-only local kanban.
357
+ It displays recorded Runs and operator waits; decisions remain in the harness.
358
+
359
+ | Artifact | Default location |
360
+ |---|---|
361
+ | Spec | `.scratch/<slug>/spec.md` |
362
+ | Issues | `.scratch/<slug>/issues/` |
363
+ | Delivery roadmap | `ROADMAP.md` |
364
+ | Repository policy | `.gantry/config.json` |
365
+ | Custom templates | `.gantry/templates/` |
366
+ | Run logs | `~/.gantry/state/<unit-id>/runs/<run-id>.jsonl` |
367
+
368
+ Setup can map existing repository locations. Issue status and criteria are the
369
+ authority on delivery state; Run logs provide observation across a clone's
370
+ worktrees.
371
+
372
+ ## Documentation
373
+
374
+ - [Product requirements](PRD.md): scope, workflow, and acceptance requirements.
375
+ - [Domain glossary](CONTEXT.md): canonical terms and product boundaries.
376
+ - [Architecture decisions](docs/adr/): standing decisions.
377
+ - [Agent contribution rules](AGENTS.md): repository instructions.
378
+ - [Delivery roadmap](ROADMAP.md): implementation progress and dependencies.
379
+ - [Workflow skill](.agents/skills/gantry/SKILL.md): execution protocol and references.
380
+
381
+ ## Contributing
382
+
383
+ Bug reports, documentation improvements, and focused pull requests are welcome.
384
+ Use [GitHub Issues](https://github.com/JulioBorges/gantry/issues) to describe a
385
+ reproducible problem or propose a change. Delivery Issues used by Gantry itself
386
+ remain local Markdown artifacts.
387
+
388
+ Before changing the pack, read `PRD.md`, `CONTEXT.md`, `docs/adr/`, and `AGENTS.md`.
389
+ Keep documentation and generated artifacts in English. Explain behavior changes
390
+ and include validation evidence in your pull request.
391
+
392
+ Run the Python suite from the repository root:
393
+
394
+ ```bash
395
+ make test
396
+ ```
397
+
398
+ For installer or packaging changes, also run:
399
+
400
+ ```bash
401
+ npm ci
402
+ npm run test:package
403
+ npm pack --dry-run
404
+ ```
405
+
406
+ Frontend changes require Playwright validation under `AGENTS.md`. Complete
407
+ roadmap Issues only when all criteria are met, using `roadmap.py done`, and
408
+ verify with `roadmap.py check`.
409
+
410
+ ### Publishing to npm
411
+
412
+ The package is configured for public publication as `@julioborges/gantry`, initially version `0.1.0`.
413
+ Only the installer, three skill directories, README and license are included; Python caches,
414
+ project Issues, fixtures, local configuration and runtime state are excluded.
415
+
416
+ ```bash
417
+ npm ci
418
+ npm run test:package
419
+ npm pack --dry-run
420
+ # After approving the release and authenticating with an account allowed to publish the scope:
421
+ make release
422
+ ```
423
+
424
+ `make release` verifies the npm account before installing locked dependencies with `npm ci` and publishing the current version from
425
+ `package.json` to npm. Update that version before publishing a subsequent release.
426
+ `prepublishOnly` first checks `npm whoami` against npmjs.org and refuses publication unless the
427
+ authenticated account is exactly `julioborges`. Authentication and network failures block publication.
428
+ This applies to both `make release` and direct `npm publish`; npm's registry permissions remain the
429
+ authority, and lifecycle hooks can be bypassed with npm options.
430
+ After authorization, it runs the repository test suite and the tarball installation test once before publication.
431
+ The tarball test executes `npx` and installs all three skills in a temporary project using the packed
432
+ artifact. See [npm's package metadata documentation](https://docs.npmjs.com/cli/v11/configuring-npm/package-json/)
433
+ for the `bin`, `files` and `publishConfig` settings. No automatic publication is configured.
434
+
435
+ ## License
436
+
437
+ Gantry is licensed under the [Apache License 2.0](LICENSE).
package/bin/gantry.mjs ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from 'node:child_process';
3
+ import { readFileSync } from 'node:fs';
4
+ import { createRequire } from 'node:module';
5
+ import { dirname, resolve } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
9
+ const [command, ...options] = process.argv.slice(2);
10
+
11
+ if (!command || ['--help', '-h', 'help'].includes(command)) {
12
+ console.log(`Gantry skill pack installer
13
+
14
+ Usage: gantry add [skills options]
15
+ gantry --version
16
+
17
+ Install into the current project:
18
+ npx @julioborges/gantry add
19
+ npx @julioborges/gantry add --agent codex --yes
20
+
21
+ Install into your user environment:
22
+ npx @julioborges/gantry add --global
23
+
24
+ List bundled skills without installing:
25
+ npx @julioborges/gantry add --list
26
+
27
+ Options are passed to the skills CLI. After installation, invoke gantry-setup
28
+ inside your coding harness. Runs execute in the harness, not this installer.`);
29
+ } else if (['--version', '-v'].includes(command)) {
30
+ console.log(JSON.parse(readFileSync(resolve(packageRoot, 'package.json'), 'utf8')).version);
31
+ } else if (command === 'add') {
32
+ const require = createRequire(import.meta.url);
33
+ const skillsRoot = dirname(require.resolve('skills/package.json'));
34
+ const manifest = JSON.parse(readFileSync(resolve(skillsRoot, 'package.json'), 'utf8'));
35
+ const result = spawnSync(process.execPath, [
36
+ resolve(skillsRoot, manifest.bin.skills), 'add', resolve(packageRoot, '.agents/skills'), ...options,
37
+ ], { stdio: 'inherit' });
38
+ if (result.error) {
39
+ console.error(`Gantry installation failed: ${result.error.message}`);
40
+ }
41
+ process.exitCode = result.status ?? 1;
42
+ } else {
43
+ console.error(`Unknown command: ${command}. Use gantry --help.`);
44
+ process.exitCode = 1;
45
+ }
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@julioborges/gantry",
3
+ "version": "0.1.0",
4
+ "description": "Install the Gantry harness-neutral agentic SDLC skill pack.",
5
+ "type": "commonjs",
6
+ "license": "Apache-2.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/JulioBorges/gantry.git"
10
+ },
11
+ "homepage": "https://github.com/JulioBorges/gantry#readme",
12
+ "bugs": "https://github.com/JulioBorges/gantry/issues",
13
+ "keywords": ["agent-skills", "gantry", "sdlc", "claude-code", "codex", "opencode"],
14
+ "engines": {"node": ">=22.20.0"},
15
+ "bin": {"gantry": "bin/gantry.mjs"},
16
+ "files": [
17
+ "bin/gantry.mjs",
18
+ "scripts/ensure-npm-author.mjs",
19
+ ".agents/skills/gantry",
20
+ ".agents/skills/gantry-setup",
21
+ ".agents/skills/gantry-dashboard",
22
+ "README.md",
23
+ "LICENSE",
24
+ "!**/__pycache__/**",
25
+ "!**/*.pyc",
26
+ "!**/.DS_Store"
27
+ ],
28
+ "scripts": {
29
+ "test": "make test",
30
+ "test:package": "node --test tests/npm-package.test.mjs tests/npm-author.test.mjs",
31
+ "pack:check": "npm run test:package",
32
+ "prepublishOnly": "node scripts/ensure-npm-author.mjs && npm test && npm run test:package"
33
+ },
34
+ "dependencies": {"skills": "1.5.26"},
35
+ "publishConfig": {"access": "public", "registry": "https://registry.npmjs.org/"}
36
+ }
@@ -0,0 +1,29 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { pathToFileURL } from 'node:url';
3
+
4
+ const author = 'julioborges';
5
+ const registry = 'https://registry.npmjs.org/';
6
+
7
+ export function ensureNpmAuthor(run = spawnSync) {
8
+ const args = ['whoami', '--registry', registry];
9
+ const result = process.env.npm_execpath
10
+ ? run(process.execPath, [process.env.npm_execpath, ...args], { encoding: 'utf8', timeout: 30_000 })
11
+ : run(process.platform === 'win32' ? 'npm.cmd' : 'npm', args, {
12
+ encoding: 'utf8', timeout: 30_000, shell: process.platform === 'win32',
13
+ });
14
+ if (result.error || result.status !== 0) {
15
+ throw new Error('Publication blocked: could not verify the npm account. Run npm login for npmjs.org.');
16
+ }
17
+ if (result.stdout.trim() !== author) {
18
+ throw new Error(`Publication blocked: only npm account ${author} may publish this package.`);
19
+ }
20
+ }
21
+
22
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
23
+ try {
24
+ ensureNpmAuthor();
25
+ } catch (error) {
26
+ console.error(error.message);
27
+ process.exitCode = 1;
28
+ }
29
+ }