forge-orkes 0.73.1 → 0.74.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.
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@ Read these before acting on any intake. Jarvis **relays and triggers — it neve
|
|
|
15
15
|
|
|
16
16
|
- **No routing.** Dispatch passes the model map (`model_by_phase_type`) through **untouched** — per-phase model selection is step 5. If intake starts *choosing models*, STOP: that is not this door's job.
|
|
17
17
|
- **No approval, ever.** Jarvis never approves, waives, lowers, or carries an approval. Promotions are approved on GitHub's Environment surface (step 2); holds are waived by your recorded host acts. Jarvis *tells* you an approval is waiting and *where* — the act happens there.
|
|
18
|
+
- **UAT is the human's act — Jarvis never stands in for it.** UAT = the **operator** tests the work locally, with their own eyes and hands. An agent's browser/Playwright run, an e2e suite, or green CI is *automated verification* — necessary, **never sufficient, and never called UAT**. Agents are not users of the system, so "the agent tested it" can never satisfy UAT. The invariant this door holds: **a PR exists only after the operator's explicit in-session UAT confirmation** — there is **no agent-attestation path to PR-open**. This is Forge's Human Verification Gate (`in_session_signoff`) applied at the **merge boundary** instead of milestone-close. The failure mode it refuses: a session self-attesting "Real browser UAT" in a PR body and auto-merging on green CI — the agent's own run is not the human's acceptance. If you catch yourself about to open a PR because *you* checked the work, STOP: that is the gate this door exists to hold.
|
|
18
19
|
- **No status memory.** "What's in play?" is **computed** from board / disk-glob / fold every time (B5), never remembered. If a question seems to need a Jarvis-owned status store, that is the drift class (pain 4): compute it or route out. The ONLY durable Jarvis state is the B4 relay markers.
|
|
19
20
|
- **No new notification infrastructure.** PushNotification + the Monitor `tail -F` + the runner's existing log. No queue, no broker, no third-party service.
|
|
20
21
|
- **No runner changes.** Jarvis consumes the runner's seams (env vars, the notify log, the m-35 answer-file convention) and never edits the loop. Runner work lives in its own milestone.
|
|
@@ -89,24 +90,56 @@ When a watched log grows, pipe it back through the relay core — do **not** buz
|
|
|
89
90
|
`--scan` relays every **unmarked** line and prints the relay text (one line per new ping); fire **PushNotification** with each. Inside, the helper recomputes host truth (the fold / `gh` / board) before building any state claim, so:
|
|
90
91
|
|
|
91
92
|
- an **ambiguity** reaches the phone as the question verbatim (it is a question, not a claim);
|
|
92
|
-
- a
|
|
93
|
+
- a **`done`** means **"ready for the operator's local UAT"** — the slice's work is built in its worktree and **no PR exists yet**. It is a *cue to UAT*, not a merge claim; relay it as such and hand off to the UAT gate (below). A payload that claims a merge or a PR at `done` contradicts the flow and is relayed as a **loud discrepancy** (host truth wins — and under this flow the host shows no PR at `done`);
|
|
94
|
+
- a **halt** is phrased from the host's `release_state`, named as a halt;
|
|
93
95
|
- **fork / irreversible / budget** relay verbatim, named.
|
|
94
96
|
|
|
95
97
|
The `--milestone` is derived per slice from its worktree branch (`forge/m-<id>`); it is what the fold recomputes against. Jarvis holds no status of its own — if a buzz would need a remembered fact, that is the drift class: recompute it or route out.
|
|
96
98
|
|
|
99
|
+
### The UAT gate (post-`done`) — no PR until the operator accepts
|
|
100
|
+
|
|
101
|
+
A `done` ping is the cue that the work is ready for the operator's **local UAT**, not that it shipped. There is no PR yet, and Jarvis opens one **only** after the operator's explicit in-session confirmation (the hard boundary in "What Jarvis is NOT"). On a relayed `done`, run this sequence **in order** — never skip ahead to a PR:
|
|
102
|
+
|
|
103
|
+
1. **Spin up the slice's local dev server** so the operator can actually try it. Read the project's dev-lane command from `project.yml`:
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
# jarvis.dev_lane_cmd — the stack-specific command that starts THIS slice's local dev server.
|
|
107
|
+
# Run it in the slice worktree (the work under test lives there), detached like the runner.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
If `jarvis.dev_lane_cmd` is **set**, run it in the slice worktree and tell the operator where it's up. If it is **absent**, do not fail — tell the operator to start their dev lane manually for this worktree (Forge owns no dev-server concept; the "how" is the project's, per FR-248). Either way, name the worktree so the operator knows what they're testing.
|
|
111
|
+
2. **Relay "ready for your UAT."** Buzz the operator: the work is built and the local server is up (or ask them to start it) — *"ready for your UAT on the local server."* This is a cue to the human, phrased as such.
|
|
112
|
+
3. **Wait for the operator's explicit confirmation.** Do nothing irreversible until the operator says, in session, that they've tested it and it's good (a plain "looks good" / "ship it" / "approved"). **Your own browser run, a passing e2e suite, or green CI never substitutes** — see the UAT boundary. No confirmation → the slice sits; you do not open a PR.
|
|
113
|
+
4. **On explicit confirmation only — open the PR and arm the merge.** This is a **trigger on the operator's word**, not an approval Jarvis grants (the "relays and triggers, never decides" boundary):
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
gh pr create --fill --head <slice-branch> # open the PR now that the human has accepted
|
|
117
|
+
gh pr merge <num> --auto --squash # arm auto-merge; CI + branch protection gate the actual merge
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Then, and only then, arm the come-try watch on that PR number (below). The order is load-bearing: dev lane → ready-for-UAT → **explicit confirmation** → PR-open + arm merge → come-try. A PR that exists before step 3 is the failure this gate refuses.
|
|
121
|
+
|
|
122
|
+
**On UAT failure — findings become an answer, and the slice re-dispatches.** If the operator says UAT failed, their findings are the fix instructions: land them as the runner's answer for the slice's `done` phase and re-dispatch, exactly like a parked-ambiguity answer (below) — no PR is opened, no new machinery:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
.forge/checks/forge-jarvis-answer.sh --work-dir <dir> --phase <N> --slice <worktree> --answer "<operator's UAT findings>"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The runner resumes the slice with the findings in hand and fixes them; the next `done` re-enters this same UAT gate. (`<N>` is the slice's final/`done` phase — the one the operator just tested.)
|
|
129
|
+
|
|
97
130
|
### The come-try tap and the answer round-trip
|
|
98
131
|
|
|
99
132
|
Two moments need a second source beyond the log line:
|
|
100
133
|
|
|
101
|
-
- **"Merged, on staging — come try."**
|
|
134
|
+
- **"Merged, on staging — come try."** After the operator has accepted the work and Jarvis has opened + armed the PR (the UAT gate, above), the step-2 auto-merge and the staging deploy land minutes later — that moment is never in the log. So **once the PR is open (post-UAT), never at `done`**, arm the bounded watch on that PR number:
|
|
102
135
|
|
|
103
136
|
```sh
|
|
104
137
|
.forge/checks/forge-jarvis-prwatch.sh --pr <num> [--staging-env <name>]
|
|
105
138
|
```
|
|
106
139
|
|
|
107
|
-
It polls `gh` (merge + staging-deploy) under a hard iteration/wall bound and self-terminates on merge+deploy (firing the come-try tap once, at-most-once by a PR-keyed marker), on a closed PR, or on the bound — never a standing daemon. It reads host truth only.
|
|
140
|
+
It polls `gh` (merge + staging-deploy) under a hard iteration/wall bound and self-terminates on merge+deploy (firing the come-try tap once, at-most-once by a PR-keyed marker), on a closed PR, or on the bound — never a standing daemon. It reads host truth only. The come-try moment therefore lands *after* the operator's own acceptance, so nothing reaches staging unverified.
|
|
108
141
|
|
|
109
|
-
- **Park → answer → resume.** When the operator answers a parked ambiguity (typed or from the phone), close the loop through the runner's own convention:
|
|
142
|
+
- **Park → answer → resume.** When the operator answers a parked ambiguity (typed or from the phone) — or supplies UAT-failure findings (the UAT gate, above) — close the loop through the runner's own convention:
|
|
110
143
|
|
|
111
144
|
```sh
|
|
112
145
|
.forge/checks/forge-jarvis-answer.sh --work-dir <dir> --phase <N> --slice <worktree> --answer "<reply>"
|
|
@@ -205,3 +238,5 @@ B3 delivered intake → spec → detached dispatch; B4 added the callback relay;
|
|
|
205
238
|
- **B6 — promotion voice** ✅ (this phase): on explicit `promote <sha>`, show what the SHA carries and trigger the step-2 seam — **trigger, never approve** (Promotion voice, above).
|
|
206
239
|
|
|
207
240
|
The front door is now whole: intake, spec, detached dispatch, the callback relay, awareness + instruments, and the promotion voice — every state claim host-recomputed, no owned state beyond the B4 relay markers.
|
|
241
|
+
|
|
242
|
+
**m-48 — UAT-gated dispatch** (later refinement, 0.74.0): the callback relay's back-half was re-sequenced so a `done` ping means "ready for the operator's local UAT" (no PR yet), Jarvis spins up the slice's local dev server (`jarvis.dev_lane_cmd`), waits for the operator's **explicit in-session UAT confirmation**, and only then triggers PR-open + arm merge — with the come-try PR watch re-armed *after* that operator-confirmed PR-open, and UAT failures routed back through the answer-file re-dispatch. The hard boundary — UAT is the human's act, no agent-attestation path to PR-open — lives in "What Jarvis is NOT". Nothing reaches staging unverified.
|
package/template/.forge/FORGE.md
CHANGED
|
@@ -188,7 +188,7 @@ Quick tier skips init.
|
|
|
188
188
|
|
|
189
189
|
State lives in `.forge/`. One line per artifact; protocol detail lives in the named ADRs and skills:
|
|
190
190
|
|
|
191
|
-
- `project.yml` — vision, stack, design system, verification, constraints (<5 KB)
|
|
191
|
+
- `project.yml` — vision, stack, design system, verification, constraints (<5 KB). Optional `jarvis.dev_lane_cmd` (m-48) is the stack-agnostic seam Jarvis runs to spin up a slice's local dev server for operator UAT before a PR opens; absent ⇒ manual lane start. See `docs/jarvis.md`.
|
|
192
192
|
- `constitution.md` — active architectural gates
|
|
193
193
|
- `design-system.md` — component mapping table
|
|
194
194
|
- `requirements/m{N}.yml` — per-milestone structured requirements with `[NEEDS CLARIFICATION]` markers. **FR/DEF/NFR ids are globally unique across all milestone files** — reserve via the ID Reservation Protocol before writing. M9 e2e gate fields (`e2e`, `observable_outcome`, `validated`, hash) lazy-migrate; absent ⇒ `false`.
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
2
|
# forge-jarvis-prwatch.sh — the bounded "merged, on staging — come try" watch
|
|
3
|
-
# (m-37, Brief-R2 step 4 B4(c); contract handoff-step4-jarvis.md REV2).
|
|
3
|
+
# (m-37, Brief-R2 step 4 B4(c); contract handoff-step4-jarvis.md REV2; re-sequenced m-48).
|
|
4
4
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
5
|
+
# Under UAT-gated dispatch (m-48) a PR is opened by Jarvis ONLY after the operator's explicit
|
|
6
|
+
# in-session UAT confirmation — never at the runner's `done` (which now means "ready for the
|
|
7
|
+
# operator's local UAT", no PR yet). This watch is armed on THAT post-UAT PR: step-2 auto-merge +
|
|
8
|
+
# the staging deploy land minutes LATER, so the flagship "come try it" moment never appears in the
|
|
9
|
+
# notify log. On the opened PR, poll `gh` for its merge + staging-deploy state with a HARD bound
|
|
10
|
+
# and, on merge+deploy, emit the come-try text once. Because it arms only after the operator has
|
|
11
|
+
# accepted the work, nothing reaches staging unverified.
|
|
9
12
|
#
|
|
10
13
|
# STRICTLY BOUNDED + self-terminating (NFR-036 / Fork 3): it stops on merge+deploy, on a closed
|
|
11
14
|
# PR, or when the iteration/wall bound is hit — it NEVER becomes a standing daemon and owns no
|
|
@@ -154,6 +154,12 @@ models:
|
|
|
154
154
|
# # no flag (platform default). TRUST WARNING: bypassPermissions means
|
|
155
155
|
# # phone-spawned sessions act without prompts — opt in only where the
|
|
156
156
|
# # phone lane carries the same trust as an attended terminal.
|
|
157
|
+
# dev_lane_cmd: "" # OPTIONAL. Shell command Jarvis runs (in the slice worktree) to spin up
|
|
158
|
+
# # the LOCAL dev server for the operator's UAT after a `done` ping — the
|
|
159
|
+
# # UAT-gated dispatch seam (m-48). Stack-specific: Forge owns no dev-server
|
|
160
|
+
# # concept, so the project supplies the "how" (e.g. its `dev:all` lane).
|
|
161
|
+
# # Absent → Jarvis tells the operator to start the lane manually (no failure).
|
|
162
|
+
# # The PR opens only AFTER the operator's explicit in-session UAT — never here.
|
|
157
163
|
|
|
158
164
|
# attribution: # OPT-IN Driven-by attribution (hold-waiver patch) — default OFF.
|
|
159
165
|
# driven_by: true # When true, the merge-floor check-quality lint
|