oi-gantry 0.2.0__tar.gz
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.
- oi_gantry-0.2.0/.gitignore +12 -0
- oi_gantry-0.2.0/CHANGELOG.md +96 -0
- oi_gantry-0.2.0/PKG-INFO +133 -0
- oi_gantry-0.2.0/README.md +120 -0
- oi_gantry-0.2.0/SampleProject/README.md +50 -0
- oi_gantry-0.2.0/VERSION +1 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/acquire.md +348 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/ask.md +162 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/batch.md +574 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/connect.md +256 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/decide.md +512 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/diagnose.md +483 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/escalate.md +577 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/fix.md +357 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/hitl.md +288 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/memory.md +234 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/observe.md +488 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/pass.md +352 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/pull.md +329 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/report.md +179 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/resume.md +271 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/select.md +527 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/status.md +241 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/sync.md +313 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/take.md +618 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry/verify.md +668 -0
- oi_gantry-0.2.0/dist/claude/commands/gantry.md +565 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-acquire.md +345 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-ask.md +158 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-batch.md +570 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-connect.md +252 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-decide.md +508 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-diagnose.md +480 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-escalate.md +573 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-fix.md +354 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-hitl.md +284 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-memory.md +230 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-observe.md +485 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-pass.md +348 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-pull.md +326 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-report.md +176 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-resume.md +268 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-select.md +524 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-status.md +238 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-sync.md +310 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-take.md +614 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry-verify.md +665 -0
- oi_gantry-0.2.0/dist/codex/prompts/gantry.md +561 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-acquire.prompt.md +348 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-ask.prompt.md +161 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-batch.prompt.md +573 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-connect.prompt.md +255 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-decide.prompt.md +511 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-diagnose.prompt.md +483 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-escalate.prompt.md +576 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-fix.prompt.md +357 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-hitl.prompt.md +287 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-memory.prompt.md +233 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-observe.prompt.md +488 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-pass.prompt.md +351 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-pull.prompt.md +329 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-report.prompt.md +179 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-resume.prompt.md +271 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-select.prompt.md +527 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-status.prompt.md +241 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-sync.prompt.md +313 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-take.prompt.md +617 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry-verify.prompt.md +668 -0
- oi_gantry-0.2.0/dist/copilot/prompts/gantry.prompt.md +564 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-acquire.md +347 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-ask.md +160 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-batch.md +572 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-connect.md +254 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-decide.md +510 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-diagnose.md +482 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-escalate.md +575 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-fix.md +356 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-hitl.md +286 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-memory.md +232 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-observe.md +487 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-pass.md +350 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-pull.md +328 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-report.md +178 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-resume.md +270 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-select.md +526 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-status.md +240 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-sync.md +312 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-take.md +616 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry-verify.md +667 -0
- oi_gantry-0.2.0/dist/cursor/commands/gantry.md +563 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/acquire.toml +347 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/ask.toml +160 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/batch.toml +572 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/connect.toml +254 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/decide.toml +510 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/diagnose.toml +482 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/escalate.toml +575 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/fix.toml +356 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/hitl.toml +286 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/memory.toml +232 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/observe.toml +487 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/pass.toml +350 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/pull.toml +328 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/report.toml +178 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/resume.toml +270 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/select.toml +526 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/status.toml +240 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/sync.toml +312 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/take.toml +616 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry/verify.toml +667 -0
- oi_gantry-0.2.0/dist/gemini/commands/gantry.toml +563 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-acquire.md +347 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-ask.md +160 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-batch.md +572 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-connect.md +254 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-decide.md +510 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-diagnose.md +482 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-escalate.md +575 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-fix.md +356 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-hitl.md +286 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-memory.md +232 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-observe.md +487 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-pass.md +350 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-pull.md +328 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-report.md +178 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-resume.md +270 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-select.md +526 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-status.md +240 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-sync.md +312 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-take.md +616 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry-verify.md +667 -0
- oi_gantry-0.2.0/dist/windsurf/workflows/gantry.md +563 -0
- oi_gantry-0.2.0/examples/README.md +69 -0
- oi_gantry-0.2.0/install.py +241 -0
- oi_gantry-0.2.0/pyproject.toml +51 -0
- oi_gantry-0.2.0/spec/feedback.md +146 -0
- oi_gantry-0.2.0/spec/lexicon.md +228 -0
- oi_gantry-0.2.0/spec/phases/acquire.md +134 -0
- oi_gantry-0.2.0/spec/phases/ask.md +57 -0
- oi_gantry-0.2.0/spec/phases/batch.md +90 -0
- oi_gantry-0.2.0/spec/phases/connect.md +29 -0
- oi_gantry-0.2.0/spec/phases/decide.md +176 -0
- oi_gantry-0.2.0/spec/phases/diagnose.md +38 -0
- oi_gantry-0.2.0/spec/phases/escalate.md +119 -0
- oi_gantry-0.2.0/spec/phases/fix.md +117 -0
- oi_gantry-0.2.0/spec/phases/gantry.md +81 -0
- oi_gantry-0.2.0/spec/phases/hitl.md +61 -0
- oi_gantry-0.2.0/spec/phases/memory.md +129 -0
- oi_gantry-0.2.0/spec/phases/observe.md +43 -0
- oi_gantry-0.2.0/spec/phases/pass.md +221 -0
- oi_gantry-0.2.0/spec/phases/pull.md +115 -0
- oi_gantry-0.2.0/spec/phases/report.md +87 -0
- oi_gantry-0.2.0/spec/phases/resume.md +31 -0
- oi_gantry-0.2.0/spec/phases/select.md +82 -0
- oi_gantry-0.2.0/spec/phases/status.md +27 -0
- oi_gantry-0.2.0/spec/phases/sync.md +73 -0
- oi_gantry-0.2.0/spec/phases/take.md +134 -0
- oi_gantry-0.2.0/spec/phases/verify.md +197 -0
- oi_gantry-0.2.0/spec/rules.md +55 -0
- oi_gantry-0.2.0/spec/surface.md +119 -0
- oi_gantry-0.2.0/src/gantry_adl/__init__.py +39 -0
- oi_gantry-0.2.0/src/gantry_adl/__main__.py +112 -0
- oi_gantry-0.2.0/src/gantry_adl/selfcheck.py +120 -0
- oi_gantry-0.2.0/tools/gantry_feedback.py +703 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Behavioural changes to the commands. Each entry says what an agent will *do differently*, because
|
|
4
|
+
that is the only thing a spec change can be judged on.
|
|
5
|
+
|
|
6
|
+
Commands are generated — edit `spec/`, run `build/compile.py`, reinstall. Never edit `dist/`.
|
|
7
|
+
|
|
8
|
+
## 0.2.0 — packaged, versioned, self-updating
|
|
9
|
+
|
|
10
|
+
**A session now knows whether its own rules are current, before it takes the lock.**
|
|
11
|
+
|
|
12
|
+
- **Shipped as a Python distribution (`oi-gantry`).** `pip install -U oi-gantry` fetches the plugin;
|
|
13
|
+
`gantry sync` writes it into all six agent configs (claude, cursor, codex, windsurf, copilot,
|
|
14
|
+
gemini). One package, six agents, one upgrade path.
|
|
15
|
+
- **`acquire` step 0 — version check.** `gantry selfcheck` exits 10 when stale, and
|
|
16
|
+
`gantry selfcheck --update` upgrades and re-syncs in the same firing. A stale plugin used to be
|
|
17
|
+
invisible: it ran, it reported, and it did so under superseded rules.
|
|
18
|
+
- An unreachable index degrades to *unknown* and **does not block the run** — telemetry may never
|
|
19
|
+
stop delivery.
|
|
20
|
+
- A **major** version gap is refused, not auto-applied: it can change the phase contract the
|
|
21
|
+
session is part-way through, so it escalates as an operator decision.
|
|
22
|
+
- **Version is single-sourced** from `VERSION` and read by the package, the CLI, and the reporter's
|
|
23
|
+
`X-Gantry-Version` header. The installer now ships `VERSION` beside `gantry_feedback.py`, so a run
|
|
24
|
+
invoked with an unrelated interpreter no longer stamps every report `0+unknown`.
|
|
25
|
+
- **Fixed: `install.py --dir` was ignored for `--scope user`**, so any install or test silently
|
|
26
|
+
targeted the operator's real agent configs instead of the directory asked for. An explicit
|
|
27
|
+
`--dir` now wins for both scopes; `$HOME` remains the default.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 2026-08-08 — grounding, parallelism, and the local loop
|
|
32
|
+
|
|
33
|
+
**21 commands** (was 19: `decide` and `batch` added).
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- **`decide`** — adjudicate a blocker instead of reporting it. Four questions that must pass before
|
|
38
|
+
"blocked" is allowed (named and probed *this firing*, body read not just the status code, two
|
|
39
|
+
alternatives tried, and — most often decisive — is the rule in this spec or one you invented), an
|
|
40
|
+
authority ladder defaulting to decide-and-act, and four ordered tiebreaks for contradictions.
|
|
41
|
+
Written because two of a session's three "genuinely blocked" items were false, one of them because
|
|
42
|
+
of a claim this spec had told it.
|
|
43
|
+
- **`batch`** — the unit of work is a conflict-free set, not a task. A cycle costs the same for one
|
|
44
|
+
task as for eight, so the speedup is amortising setup, **not** running more agents (the lock is
|
|
45
|
+
project-wide; there is no per-task lease). Batch the execution, never the evidence.
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- **Evidence grammar for closes.** If you did not run it this firing, it is not evidence. Inference,
|
|
50
|
+
recall and absence are each named as impostors, with absence flagged as the dangerous one because
|
|
51
|
+
it feels like a finding.
|
|
52
|
+
- **Local-first loop.** `pull` now brings the stack up locally before editing; `verify` states the
|
|
53
|
+
division — local proves the change works, cloud proves it is what the platform and users will see.
|
|
54
|
+
Remote iteration is where the `exec` 504s, the 120s lock TTL and container-snapshot staleness bite.
|
|
55
|
+
- **`supersede-task` has three evidence shapes** — `by`, `by_tasks[]`, and `justification` for the
|
|
56
|
+
no-single-author case. Naming one sibling of a four-task suite is a guess dressed as provenance.
|
|
57
|
+
- **`PENDING` is not blocked** — it may be unpromoted. Read `startable` from `task-graph`, not
|
|
58
|
+
`status`.
|
|
59
|
+
- **Target triage before building.** `task-graph` reports `target_status`; a task whose target is
|
|
60
|
+
`missing_path` or `unresolvable_bucket_key` cannot be gated, so repair it first. `ns::…::general`
|
|
61
|
+
never grounds — derive the target from the description, `PUT` the file first (retarget rejects a
|
|
62
|
+
path that does not exist), then retarget.
|
|
63
|
+
- **Platform vocabulary in task text** — a word with no domain referent may be *platform* vocabulary,
|
|
64
|
+
not boilerplate. With the counter-caution: `lane`, `worker`, `gate` are ordinary domain words in
|
|
65
|
+
real products, and treating them as leaks discards genuine requirements.
|
|
66
|
+
- **Security sweeps must cover every method.** A GET-only sweep is why a publicly writable endpoint
|
|
67
|
+
survived. `401` vs `422` is the whole diagnosis.
|
|
68
|
+
- **`queued` has three endings** — applied, pending, or dead-lettered.
|
|
69
|
+
- **Proxy `404` is two different failures** — read the body, not the code.
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
|
|
73
|
+
- **The reporter path was never the file, it was the cwd.** Reported missing three rounds running;
|
|
74
|
+
the file was always present, but the path was *relative* and the workflow requires the agent to
|
|
75
|
+
`cd` into the pulled repo. Now absolutised at install time, with the installer aborting if a
|
|
76
|
+
relative one survives.
|
|
77
|
+
- **Feedback had nowhere to go.** Every session printed `queued: no-endpoint`; the endpoint now
|
|
78
|
+
derives from `PROJECT_URL`.
|
|
79
|
+
- **Retracted: "HITL can never land while paused."** Wrong, and shipped by this spec. `SubmitHitl`
|
|
80
|
+
always had an arm; the queue is drained by the worker poll loop, ungated by `paused`.
|
|
81
|
+
- **Retracted: "a proxy 404 means no route."** It also means the app answered.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 2026-08-06 — first feedback round
|
|
86
|
+
|
|
87
|
+
- `retarget-task` documented; an orphan target became a fix rather than an escalation.
|
|
88
|
+
- `manual-pass` takes `project_id`, not `project`.
|
|
89
|
+
- Reporter stopped discarding the session it exists to record (134 of 141 events were being dropped).
|
|
90
|
+
- Lock lifecycle for `/loop` firings.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 2026-08-05 — initial
|
|
95
|
+
|
|
96
|
+
19 commands across six vendors, compiled from one spec with a conformance gate.
|
oi_gantry-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: oi-gantry
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: GANTRY — the ADL plugin layer that drives a coding agent through a governed delivery loop
|
|
5
|
+
Author: Orion Innovation
|
|
6
|
+
License: Proprietary
|
|
7
|
+
Keywords: adl,claude,codex,coding-agent,copilot,cursor,gantry,gemini,windsurf
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# GANTRY
|
|
15
|
+
|
|
16
|
+
`/gantry` slash commands that turn any capable coding agent (Claude Code, Cursor, Codex, Windsurf,
|
|
17
|
+
Copilot, Gemini CLI) into a debugging **and coding** harness for one Encore/Nova project — driven
|
|
18
|
+
over the project's HTTP API, with the actual build-run-test work done on local disk.
|
|
19
|
+
|
|
20
|
+
- The rules themselves: [`spec/`](spec/) — every phase, in the order an agent runs them
|
|
21
|
+
- Mandatory feedback mechanism: [spec/feedback.md](spec/feedback.md)
|
|
22
|
+
- What changes per release, including retractions: [CHANGELOG.md](CHANGELOG.md)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## The general rule: GANTRY always runs with the swarm OFF
|
|
27
|
+
|
|
28
|
+
**`/gantry` must always turn the swarm off before it does anything.** The swarm and the coding agent
|
|
29
|
+
must never write to the same project at the same time — two writers on one tree produce reverts,
|
|
30
|
+
half-merges, and gate failures that belong to neither of them.
|
|
31
|
+
|
|
32
|
+
This holds **whether you run `/gantry` once or in a loop**, and it is not conditional on what you
|
|
33
|
+
intend to do. Even a read-only look is safer taken against a quiesced project.
|
|
34
|
+
|
|
35
|
+
- **Run to success** = the swarm does **no** coding. `/gantry` loops are the code producer: pull the
|
|
36
|
+
repo locally, complete the task with the real toolchain (docker, playwright, tests), push back to
|
|
37
|
+
git, sync the workspace, and flag the result.
|
|
38
|
+
- Because no swarm runs, **no gate runs either**. A task completed and proven locally is closed with
|
|
39
|
+
`pass` (ADL §8 preconditions enforced: cause not shared, real vantage-named proof, re-diff
|
|
40
|
+
immediately before passing). That is the intended path here, not a workaround.
|
|
41
|
+
- `acquire` performs the `swarm/stop` and verifies `paused==true`. If it cannot confirm `paused`,
|
|
42
|
+
**nothing else runs.**
|
|
43
|
+
|
|
44
|
+
**`is_on` is not the swarm.** Three orthogonal states — `is_on` (the container stack), `paused` (the
|
|
45
|
+
swarm's writing), and per-service subapp status. Turning the project on does not start the swarm, and
|
|
46
|
+
pausing the swarm does not stop the containers. Use `swarm/stop` to stop coding; never
|
|
47
|
+
`toggle {is_on:false}`, which tears the stack down and does not set `paused`.
|
|
48
|
+
|
|
49
|
+
## The local workspace
|
|
50
|
+
|
|
51
|
+
GANTRY mirrors Nova's own layout so compose bind-mounts and relative paths resolve identically:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
${ENCORE_LOCAL_LWD}/<PROJECT_ID>/<Project Name>/ # default base: /mnt/encore
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
e.g. `/mnt/encore/proj-example-hifi/EXAMPLE-HIFI/`. Quote the paths — project names contain spaces. Point
|
|
58
|
+
`ENCORE_LOCAL_LWD` elsewhere to work outside `/mnt`.
|
|
59
|
+
|
|
60
|
+
## Get started
|
|
61
|
+
|
|
62
|
+
**Copy the sample folder** — [SampleProject/](SampleProject/) has the commands pre-installed for all
|
|
63
|
+
six agents:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cp -r SampleProject ~/GantryProjects/proj-xxxx
|
|
67
|
+
cd ~/GantryProjects/proj-xxxx && export ENCORE_LOCAL_LWD=~/GantryProjects
|
|
68
|
+
# fill in GANTRY-KICKOFF.md, then run /gantry
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Or bootstrap it pre-filled** from a read-only probe of the live project:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
export GANTRY_API_KEY='...' # out-of-band; never an argument, never in a file
|
|
75
|
+
python3 examples/new-project.py --project-id proj-xxxx \
|
|
76
|
+
--url https://your-nova-host --dir ~/GantryProjects
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Creates the project folder, installs the commands into it, and writes a `GANTRY-KICKOFF.md`
|
|
80
|
+
pre-filled from the live project — task counts, `is_on`/`paused`, lock state, git remote, and any
|
|
81
|
+
blocker it can prove. See [examples/](examples/) for the template and a worked example.
|
|
82
|
+
|
|
83
|
+
## Install manually
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
python3 build/compile.py # spec/ -> dist/ (+ conformance gate)
|
|
87
|
+
python3 install.py --target claude --scope project --dir ~/GantryProjects
|
|
88
|
+
python3 install.py --list # all supported targets and their layouts
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Then `/gantry` in that folder. `--target all` installs every vendor; `--uninstall` removes exactly
|
|
92
|
+
what was installed.
|
|
93
|
+
|
|
94
|
+
## Commands
|
|
95
|
+
|
|
96
|
+
`gantry` (router) · `connect` `acquire` `observe` `select` `diagnose` `fix` `verify` `hitl` `resume`
|
|
97
|
+
`escalate` `report` `status` · `pull` `sync` `take` `pass` · `ask` `memory`
|
|
98
|
+
|
|
99
|
+
### `/gantry <prompt>` — just ask it
|
|
100
|
+
|
|
101
|
+
`/gantry` takes a free-form prompt and routes it, so you don't have to know the command names:
|
|
102
|
+
|
|
103
|
+
| You type | It does |
|
|
104
|
+
|---|---|
|
|
105
|
+
| `/gantry why is REQ-01b866c7 stuck?` | **Answers** from read-only state. No lock, no pause, no edits. |
|
|
106
|
+
| `/gantry pull it locally` | Runs that phase, and says which one it picked. |
|
|
107
|
+
| `/gantry finish the payment task` | Runs the full loop, scoped to that. |
|
|
108
|
+
| `/gantry should cancel refund before releasing inventory?` | Reaches a human via `ask` — it will not invent a requirement. |
|
|
109
|
+
| `/gantry` | Full loop. |
|
|
110
|
+
|
|
111
|
+
**Questions are answered, not executed.** When a prompt is ambiguous, GANTRY takes the cheaper,
|
|
112
|
+
reversible path — reply, or ask — rather than freezing the swarm. Reaching a human via
|
|
113
|
+
`POST /api/projects/{id}/chat` takes no lock and disturbs nothing; replies come back on the event
|
|
114
|
+
stream. It never blocks the session waiting for a reply, and never guesses an answer.
|
|
115
|
+
|
|
116
|
+
## Non-negotiables
|
|
117
|
+
|
|
118
|
+
HTTP surface only — no SSH, no DB edits, no platform patching. Fix the real **shared** cause. Escalate
|
|
119
|
+
anything outside the surface rather than reaching around it. Every session writes a feedback report
|
|
120
|
+
before releasing the lock.
|
|
121
|
+
|
|
122
|
+
## Documentation map
|
|
123
|
+
|
|
124
|
+
| File | For | Contains |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| `spec/` → `dist/` | the **agent** | the rules themselves — edit `spec/`, never `dist/` |
|
|
127
|
+
| [`CHANGELOG.md`](CHANGELOG.md) | **everyone** | what an agent will do differently, per release, including retractions |
|
|
128
|
+
| [`SampleProject/`](SampleProject/) | **new users** | the commands pre-installed for all six agents |
|
|
129
|
+
| [`examples/`](examples/) | **new users** | the kickoff template and a worked example |
|
|
130
|
+
|
|
131
|
+
**Retractions live in the changelog on purpose.** Two rules this spec shipped were wrong and were
|
|
132
|
+
believed by agents reasoning correctly from them — "HITL can never land while paused" and "a proxy
|
|
133
|
+
404 means no route". A spec that quietly corrects itself teaches agents to distrust the correction.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# GANTRY
|
|
2
|
+
|
|
3
|
+
`/gantry` slash commands that turn any capable coding agent (Claude Code, Cursor, Codex, Windsurf,
|
|
4
|
+
Copilot, Gemini CLI) into a debugging **and coding** harness for one Encore/Nova project — driven
|
|
5
|
+
over the project's HTTP API, with the actual build-run-test work done on local disk.
|
|
6
|
+
|
|
7
|
+
- The rules themselves: [`spec/`](spec/) — every phase, in the order an agent runs them
|
|
8
|
+
- Mandatory feedback mechanism: [spec/feedback.md](spec/feedback.md)
|
|
9
|
+
- What changes per release, including retractions: [CHANGELOG.md](CHANGELOG.md)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## The general rule: GANTRY always runs with the swarm OFF
|
|
14
|
+
|
|
15
|
+
**`/gantry` must always turn the swarm off before it does anything.** The swarm and the coding agent
|
|
16
|
+
must never write to the same project at the same time — two writers on one tree produce reverts,
|
|
17
|
+
half-merges, and gate failures that belong to neither of them.
|
|
18
|
+
|
|
19
|
+
This holds **whether you run `/gantry` once or in a loop**, and it is not conditional on what you
|
|
20
|
+
intend to do. Even a read-only look is safer taken against a quiesced project.
|
|
21
|
+
|
|
22
|
+
- **Run to success** = the swarm does **no** coding. `/gantry` loops are the code producer: pull the
|
|
23
|
+
repo locally, complete the task with the real toolchain (docker, playwright, tests), push back to
|
|
24
|
+
git, sync the workspace, and flag the result.
|
|
25
|
+
- Because no swarm runs, **no gate runs either**. A task completed and proven locally is closed with
|
|
26
|
+
`pass` (ADL §8 preconditions enforced: cause not shared, real vantage-named proof, re-diff
|
|
27
|
+
immediately before passing). That is the intended path here, not a workaround.
|
|
28
|
+
- `acquire` performs the `swarm/stop` and verifies `paused==true`. If it cannot confirm `paused`,
|
|
29
|
+
**nothing else runs.**
|
|
30
|
+
|
|
31
|
+
**`is_on` is not the swarm.** Three orthogonal states — `is_on` (the container stack), `paused` (the
|
|
32
|
+
swarm's writing), and per-service subapp status. Turning the project on does not start the swarm, and
|
|
33
|
+
pausing the swarm does not stop the containers. Use `swarm/stop` to stop coding; never
|
|
34
|
+
`toggle {is_on:false}`, which tears the stack down and does not set `paused`.
|
|
35
|
+
|
|
36
|
+
## The local workspace
|
|
37
|
+
|
|
38
|
+
GANTRY mirrors Nova's own layout so compose bind-mounts and relative paths resolve identically:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
${ENCORE_LOCAL_LWD}/<PROJECT_ID>/<Project Name>/ # default base: /mnt/encore
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
e.g. `/mnt/encore/proj-example-hifi/EXAMPLE-HIFI/`. Quote the paths — project names contain spaces. Point
|
|
45
|
+
`ENCORE_LOCAL_LWD` elsewhere to work outside `/mnt`.
|
|
46
|
+
|
|
47
|
+
## Get started
|
|
48
|
+
|
|
49
|
+
**Copy the sample folder** — [SampleProject/](SampleProject/) has the commands pre-installed for all
|
|
50
|
+
six agents:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cp -r SampleProject ~/GantryProjects/proj-xxxx
|
|
54
|
+
cd ~/GantryProjects/proj-xxxx && export ENCORE_LOCAL_LWD=~/GantryProjects
|
|
55
|
+
# fill in GANTRY-KICKOFF.md, then run /gantry
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Or bootstrap it pre-filled** from a read-only probe of the live project:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
export GANTRY_API_KEY='...' # out-of-band; never an argument, never in a file
|
|
62
|
+
python3 examples/new-project.py --project-id proj-xxxx \
|
|
63
|
+
--url https://your-nova-host --dir ~/GantryProjects
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Creates the project folder, installs the commands into it, and writes a `GANTRY-KICKOFF.md`
|
|
67
|
+
pre-filled from the live project — task counts, `is_on`/`paused`, lock state, git remote, and any
|
|
68
|
+
blocker it can prove. See [examples/](examples/) for the template and a worked example.
|
|
69
|
+
|
|
70
|
+
## Install manually
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
python3 build/compile.py # spec/ -> dist/ (+ conformance gate)
|
|
74
|
+
python3 install.py --target claude --scope project --dir ~/GantryProjects
|
|
75
|
+
python3 install.py --list # all supported targets and their layouts
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Then `/gantry` in that folder. `--target all` installs every vendor; `--uninstall` removes exactly
|
|
79
|
+
what was installed.
|
|
80
|
+
|
|
81
|
+
## Commands
|
|
82
|
+
|
|
83
|
+
`gantry` (router) · `connect` `acquire` `observe` `select` `diagnose` `fix` `verify` `hitl` `resume`
|
|
84
|
+
`escalate` `report` `status` · `pull` `sync` `take` `pass` · `ask` `memory`
|
|
85
|
+
|
|
86
|
+
### `/gantry <prompt>` — just ask it
|
|
87
|
+
|
|
88
|
+
`/gantry` takes a free-form prompt and routes it, so you don't have to know the command names:
|
|
89
|
+
|
|
90
|
+
| You type | It does |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `/gantry why is REQ-01b866c7 stuck?` | **Answers** from read-only state. No lock, no pause, no edits. |
|
|
93
|
+
| `/gantry pull it locally` | Runs that phase, and says which one it picked. |
|
|
94
|
+
| `/gantry finish the payment task` | Runs the full loop, scoped to that. |
|
|
95
|
+
| `/gantry should cancel refund before releasing inventory?` | Reaches a human via `ask` — it will not invent a requirement. |
|
|
96
|
+
| `/gantry` | Full loop. |
|
|
97
|
+
|
|
98
|
+
**Questions are answered, not executed.** When a prompt is ambiguous, GANTRY takes the cheaper,
|
|
99
|
+
reversible path — reply, or ask — rather than freezing the swarm. Reaching a human via
|
|
100
|
+
`POST /api/projects/{id}/chat` takes no lock and disturbs nothing; replies come back on the event
|
|
101
|
+
stream. It never blocks the session waiting for a reply, and never guesses an answer.
|
|
102
|
+
|
|
103
|
+
## Non-negotiables
|
|
104
|
+
|
|
105
|
+
HTTP surface only — no SSH, no DB edits, no platform patching. Fix the real **shared** cause. Escalate
|
|
106
|
+
anything outside the surface rather than reaching around it. Every session writes a feedback report
|
|
107
|
+
before releasing the lock.
|
|
108
|
+
|
|
109
|
+
## Documentation map
|
|
110
|
+
|
|
111
|
+
| File | For | Contains |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| `spec/` → `dist/` | the **agent** | the rules themselves — edit `spec/`, never `dist/` |
|
|
114
|
+
| [`CHANGELOG.md`](CHANGELOG.md) | **everyone** | what an agent will do differently, per release, including retractions |
|
|
115
|
+
| [`SampleProject/`](SampleProject/) | **new users** | the commands pre-installed for all six agents |
|
|
116
|
+
| [`examples/`](examples/) | **new users** | the kickoff template and a worked example |
|
|
117
|
+
|
|
118
|
+
**Retractions live in the changelog on purpose.** Two rules this spec shipped were wrong and were
|
|
119
|
+
believed by agents reasoning correctly from them — "HITL can never land while paused" and "a proxy
|
|
120
|
+
404 means no route". A spec that quietly corrects itself teaches agents to distrust the correction.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# SampleProject — copy this folder to start
|
|
2
|
+
|
|
3
|
+
A ready-to-use GANTRY project folder with the `/gantry` commands already installed for **all six
|
|
4
|
+
agents**. Copy it, fill in the kickoff, and run.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
cp -r SampleProject ~/GantryProjects/proj-xxxx
|
|
8
|
+
cd ~/GantryProjects/proj-xxxx
|
|
9
|
+
export ENCORE_LOCAL_LWD=~/GantryProjects
|
|
10
|
+
export GANTRY_API_KEY='...' # out-of-band; never write it into a file
|
|
11
|
+
# fill in GANTRY-KICKOFF.md, then:
|
|
12
|
+
/gantry
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Prefer it pre-filled? `examples/new-project.py` does the same thing and populates the kickoff from a
|
|
16
|
+
read-only probe of the live project — task counts, `is_on`/`paused`, lock state, git remote:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
python3 examples/new-project.py --project-id proj-xxxx --url https://your-nova-host \
|
|
20
|
+
--dir ~/GantryProjects
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## What's here
|
|
24
|
+
|
|
25
|
+
| | |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `.claude/` `.cursor/` `.codex/` `.windsurf/` `.github/` `.gemini/` | the 19 `/gantry` commands, per agent |
|
|
28
|
+
| `GANTRY-KICKOFF.md` | the kickoff template — **fill this in before your first run** |
|
|
29
|
+
|
|
30
|
+
Only your agent's directory matters; delete the rest if you like. Each carries a
|
|
31
|
+
`.gantry-manifest.json` recording what GANTRY installed, so `install.py --uninstall` removes exactly
|
|
32
|
+
that and nothing else.
|
|
33
|
+
|
|
34
|
+
These command files are **generated** from `spec/` by `build/compile.py` and verified against
|
|
35
|
+
`dist/` by `compile.py --check`. Don't hand-edit them — edit the spec and rebuild, or your changes
|
|
36
|
+
vanish on the next build.
|
|
37
|
+
|
|
38
|
+
## Before your first run
|
|
39
|
+
|
|
40
|
+
**The swarm will be turned off and kept off.** `/gantry` pauses it and verifies `paused==true` before
|
|
41
|
+
it writes anything. The swarm and a coding agent must never write to the same tree. You are the code
|
|
42
|
+
producer for the session.
|
|
43
|
+
|
|
44
|
+
**No swarm means no gate.** Nothing is running to award a task Done, so a task you finish and prove
|
|
45
|
+
locally is closed with `pass` — which enforces the preconditions (cause not shared, real
|
|
46
|
+
vantage-named proof, re-diff immediately before passing). A task still red gets **escalated**, not
|
|
47
|
+
passed.
|
|
48
|
+
|
|
49
|
+
**Fill in the kickoff.** It's the first thing an agent reads. Every fact you put there is one the
|
|
50
|
+
session doesn't have to re-derive — and one it can't get wrong.
|
oi_gantry-0.2.0/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.2.0
|