axstack 0.9.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/LICENSE +21 -0
- package/README.md +132 -0
- package/bin/axstack.js +396 -0
- package/docs/installation.md +239 -0
- package/docs/workflows.md +220 -0
- package/package.json +40 -0
- package/profiles/presets/claude-only.json +194 -0
- package/profiles/presets/codex-only.json +194 -0
- package/profiles/presets/mixed.json +194 -0
- package/skills/axstack/SKILL.md +81 -0
- package/skills/axstack/references/automations.md +368 -0
- package/skills/axstack/references/candidate-publication.md +45 -0
- package/skills/axstack/references/contracts.md +102 -0
- package/skills/axstack/references/lifecycle.md +137 -0
- package/skills/axstack/references/orca-runtime.md +109 -0
- package/skills/axstack/references/pr-shape.md +39 -0
- package/skills/axstack/references/routing.md +129 -0
- package/skills/axstack/references/run-record.md +109 -0
- package/skills/axstack-align/SKILL.md +121 -0
- package/skills/axstack-audit/SKILL.md +137 -0
- package/skills/axstack-audit/references/record.md +28 -0
- package/skills/axstack-debug/SKILL.md +157 -0
- package/skills/axstack-debug/references/packet.md +80 -0
- package/skills/axstack-explain/SKILL.md +66 -0
- package/skills/axstack-explain/references/visual-qa.md +15 -0
- package/skills/axstack-implement/SKILL.md +164 -0
- package/skills/axstack-improve/SKILL.md +69 -0
- package/skills/axstack-relay/SKILL.md +102 -0
- package/skills/axstack-research/SKILL.md +57 -0
- package/skills/axstack-research/references/checklist.md +25 -0
- package/skills/axstack-review/SKILL.md +343 -0
- package/skills/axstack-spec/SKILL.md +67 -0
- package/skills/axstack-tickets/SKILL.md +86 -0
- package/skills/axstack-watch/SKILL.md +160 -0
- package/skills/axstack-watch/references/repair-publication.md +69 -0
- package/skills/axstack-watch/references/watch-runtime.md +60 -0
- package/src/capabilities.js +138 -0
- package/src/claude-settings.js +230 -0
- package/src/installer.js +980 -0
- package/src/instructions.js +100 -0
- package/src/locations.js +43 -0
- package/src/manifest.js +251 -0
- package/src/posixpath.js +108 -0
- package/src/roles.js +142 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: axstack
|
|
3
|
+
description: When routing an engineering run through Axstack, use axstack to select the applicable phase and scope identity.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Axstack entry
|
|
7
|
+
|
|
8
|
+
Route the current request to one Axstack phase with the right scope identity.
|
|
9
|
+
The current chat remains the driver; Orca owns runtime orchestration.
|
|
10
|
+
|
|
11
|
+
For an explicit relay message or transport test, use
|
|
12
|
+
[axstack-relay](../axstack-relay/SKILL.md) directly. No engineering scope
|
|
13
|
+
identity or decision workflow is needed for that send. The same skill handles
|
|
14
|
+
urgent or blocking notifications under an explicit standing instruction.
|
|
15
|
+
|
|
16
|
+
## Route the request
|
|
17
|
+
|
|
18
|
+
1. Classify the request with [Shared routing](references/routing.md). Direct
|
|
19
|
+
research, explanation, improvement discovery, peer-review, adopted-watch,
|
|
20
|
+
and handoff routes need no spec
|
|
21
|
+
ceremony. Only an explicit user-requested ownership transfer can use the
|
|
22
|
+
capability-gated native route in
|
|
23
|
+
[Lifecycle and receipts](references/lifecycle.md#native-handoff-and-resume),
|
|
24
|
+
not an Axstack handoff phase. Preparation completion, watch expiry, and
|
|
25
|
+
ordinary resume update or reconcile the run record without launching it.
|
|
26
|
+
2. For new engineering work, validate scope identity before invoking any phase.
|
|
27
|
+
Record `small`, `substantial`, or `unclear` plus a brief reason, then apply the
|
|
28
|
+
[proportional scope identity](references/routing.md#proportional-scope-identity).
|
|
29
|
+
A small clear change proceeds from its snapshotted small-change intent.
|
|
30
|
+
Substantial work proceeds only from an approved spec and matching ticket
|
|
31
|
+
map. Clarify unclear size before dispatch.
|
|
32
|
+
3. Only after validation passes, invoke exactly the selected phase. A directly
|
|
33
|
+
invoked later phase starts there and must pass its own identity check. When
|
|
34
|
+
substantial work lacks an approved spec or matching ticket map, return that
|
|
35
|
+
exact gap, name `axstack-align` as the next route, and stop the current
|
|
36
|
+
invocation; do not invoke align, spec, or tickets. Apply the same stop to a
|
|
37
|
+
mismatched or invalidated identity. Never admit work that a deeper phase
|
|
38
|
+
would reject.
|
|
39
|
+
|
|
40
|
+
The route is settled when one applicable phase is named with its valid scope
|
|
41
|
+
identity, or the exact preparation/setup gap is reported with affected work
|
|
42
|
+
held.
|
|
43
|
+
|
|
44
|
+
## Load at the action boundary
|
|
45
|
+
|
|
46
|
+
- Every independently called phase loads [Standing contracts](references/contracts.md),
|
|
47
|
+
which requires lifecycle and audit loading before action.
|
|
48
|
+
- Before an actual Axstack role dispatch, delivery, settlement, or handoff, load
|
|
49
|
+
[Orca runtime](references/orca-runtime.md). Ordinary reading, writing, and
|
|
50
|
+
local checks do not require launch discovery.
|
|
51
|
+
- Substantive delegated or resumable work uses the
|
|
52
|
+
[Local run record](references/run-record.md).
|
|
53
|
+
- When the current session is an Orca PR automation (driver or watchdog), load
|
|
54
|
+
[Automation sessions](references/automations.md) before any discovery,
|
|
55
|
+
review, gate, or mutation.
|
|
56
|
+
- When review escalation or watch notification is eligible and the brief has a
|
|
57
|
+
`Notification policy`, use the optional
|
|
58
|
+
[axstack-relay](../axstack-relay/SKILL.md); otherwise keep notification in
|
|
59
|
+
the current Orca conversation.
|
|
60
|
+
|
|
61
|
+
## Lifecycle
|
|
62
|
+
|
|
63
|
+
This is a phase map, not an automatic dispatch sequence.
|
|
64
|
+
|
|
65
|
+
1. `axstack-align` settles substantial scope and decisions.
|
|
66
|
+
2. `axstack-spec` creates the single user-approved execution baseline.
|
|
67
|
+
3. `axstack-tickets` maps capabilities, tasks, and dependencies, then
|
|
68
|
+
preparation stops with a resumable handoff.
|
|
69
|
+
4. `axstack-implement` produces owned candidates with strict TDD.
|
|
70
|
+
5. `axstack-review` gives peer PRs the two configured independent same-brief
|
|
71
|
+
reviewer roles; authored PRs get one complete eligible non-author/non-owner
|
|
72
|
+
review based on actual author provenance and the routing snapshot.
|
|
73
|
+
6. `axstack-watch` monitors within the shared deadline and hands off remaining
|
|
74
|
+
work.
|
|
75
|
+
7. The human merges by default, bottom-up for a stack. Review approval never
|
|
76
|
+
grants merge authority.
|
|
77
|
+
|
|
78
|
+
Autonomous progress, model holds, serious-risk handling, mutation authority,
|
|
79
|
+
and the one-host ownership contract live in
|
|
80
|
+
[Standing contracts](references/contracts.md). Load only the selected phase
|
|
81
|
+
and the references its action requires.
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# Automation sessions
|
|
2
|
+
|
|
3
|
+
Read this when the current session is an Orca automation running a PR driver or
|
|
4
|
+
a watchdog.
|
|
5
|
+
|
|
6
|
+
## Pair identity
|
|
7
|
+
|
|
8
|
+
There are two independent automation pairs. Before acting, resolve which pair
|
|
9
|
+
this session belongs to from its own run id and the verbatim allowlist in its
|
|
10
|
+
own prompt; never assume.
|
|
11
|
+
|
|
12
|
+
- **Pair A/B** — driver Automation A (`*/30`) and watchdog Automation B, run id
|
|
13
|
+
`20260916-pr-automations`, allowlist `axatbhardwaj/axstack`.
|
|
14
|
+
- **Pair C/D** — driver Automation C (hourly) and watchdog Automation D, run id
|
|
15
|
+
`20260916-defi-automations`, allowlist
|
|
16
|
+
`defi-com/monorepo, defi-com/mobile, defi-com/azure-next-hybrid`.
|
|
17
|
+
|
|
18
|
+
The two pairs share no state: each has its own run id, run directory,
|
|
19
|
+
`progress.md` and sidecars, and no sidecar is shared between them. A clause
|
|
20
|
+
below that names a pair applies only to that pair; every other clause applies to
|
|
21
|
+
both. Where this reference says "the driver" it means the driver of the current
|
|
22
|
+
pair. It restates the operational contract of the approved
|
|
23
|
+
`docs/specs/orca-automations.md`; that spec is authoritative, and nothing here
|
|
24
|
+
widens it. Orca owns scheduling, sessions, retries, and run history. Axstack
|
|
25
|
+
owns policy, the run record, and evidence.
|
|
26
|
+
|
|
27
|
+
## Identity and scope
|
|
28
|
+
|
|
29
|
+
- **Self** is `gh api user --jq .login`, resolved at the start of every run and
|
|
30
|
+
never hardcoded.
|
|
31
|
+
- **Own PR:** an open PR authored by self. Authority equals the user at the
|
|
32
|
+
keyboard: repair, test, commit, and fast-forward push to the PR branch
|
|
33
|
+
(`git push`, no lease or force). `gh stack` sync or restack is out of scope.
|
|
34
|
+
- **Peer PR:** an open PR where self is officially review-requested, or where a
|
|
35
|
+
PR comment @-mentions self asking for a response. Unsolicited reviews never
|
|
36
|
+
happen. Peer code is read-only. A mention counts as a peer request only when
|
|
37
|
+
the driver reads the comment and it explicitly asks self to review or
|
|
38
|
+
respond. An incidental mention is discovery data and never review authority.
|
|
39
|
+
- **Discovery** covers every repository the account can see:
|
|
40
|
+
`gh search prs --state open --limit 100` with `--author @me`,
|
|
41
|
+
`--review-requested @me`, and `--mentions @me`. A result count equal to the
|
|
42
|
+
limit is a detectable truncation and is logged as `error`. Results are
|
|
43
|
+
deduplicated canonically by PR URL across the three searches with own-PR
|
|
44
|
+
precedence.
|
|
45
|
+
- **Mutation allowlist:** stated verbatim in the automation prompt, per
|
|
46
|
+
automation rather than as one global list. One allowlist gates both own-PR
|
|
47
|
+
repair and peer review for its own automation; there is no separate
|
|
48
|
+
review-only list. Outside the
|
|
49
|
+
allowlist the automation discovers and records only. The precheck writes the
|
|
50
|
+
full discovery list to `pending.json`; no review, watch, gate, or other model
|
|
51
|
+
work is launched for an external PR. External changes do not enter the wake
|
|
52
|
+
fingerprint, so external churn never wakes the session. External PR contents
|
|
53
|
+
never produce an escalation. This is a deliberate coverage reduction, not an
|
|
54
|
+
implied clean review; discovery errors themselves remain automation-health
|
|
55
|
+
findings.
|
|
56
|
+
- **Prohibited everywhere:** force-push, rebase, merge, close, `APPROVE`,
|
|
57
|
+
`REQUEST_CHANGES`. A need for any of these becomes a recorded hold.
|
|
58
|
+
|
|
59
|
+
## Roles per mode
|
|
60
|
+
|
|
61
|
+
The automation session is the driver and the owner for every PR it handles;
|
|
62
|
+
the driver is the automation session itself, with no `axstack-monitor` or
|
|
63
|
+
`axstack-owner` role row materialized, and the standalone-owner branches
|
|
64
|
+
of `axstack-watch` and `axstack-review` do not fire. `axstack-monitor` stays
|
|
65
|
+
an optional read-only observer that never sends.
|
|
66
|
+
|
|
67
|
+
- Peer PR → peer mode of [axstack-review](../../axstack-review/SKILL.md):
|
|
68
|
+
`axstack-reviewer-primary` and `axstack-reviewer-secondary`, isolated.
|
|
69
|
+
- Own-PR repair → authored mode: the repair author is the automation session
|
|
70
|
+
(provider `claude`), so the one cross-family reviewer comes from actual
|
|
71
|
+
provenance (`axstack-reviewer-primary`, Sol, in `mixed`). A repair delegated
|
|
72
|
+
to `axstack-author` (Sol) takes `axstack-reviewer-secondary`.
|
|
73
|
+
- "Every mode-required reviewer" means both reviewers in peer mode and the one
|
|
74
|
+
selected reviewer in authored mode.
|
|
75
|
+
- Gate → `axstack-auditor`.
|
|
76
|
+
- Watchdog → `axstack-watchdog`, which never mutates GitHub and performs
|
|
77
|
+
exactly one kind of send, a gate-authorized automation-health escalation
|
|
78
|
+
recorded in `watchdog.json`.
|
|
79
|
+
|
|
80
|
+
## Reviewer brief and criteria
|
|
81
|
+
|
|
82
|
+
Every reviewer brief ends with a required field, exactly:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
Escalate to user: yes | no — <criterion> — <reason>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Criteria, exactly four: a security concern; a permanent on-chain state change;
|
|
89
|
+
an architectural change in approach; and automation health (a
|
|
90
|
+
model-substitution, session, precheck, discovery, or relay-delivery hold). The
|
|
91
|
+
automation health criterion is usable only by the watchdog and the safety-hold
|
|
92
|
+
path, never by a reviewer.
|
|
93
|
+
|
|
94
|
+
## Stack-aware repair sequencing (pair C/D)
|
|
95
|
+
|
|
96
|
+
These three sections govern pair C/D only. Pair A/B's behaviour is unchanged by
|
|
97
|
+
revision 4 except for the named cadence correction, so A does not apply stack
|
|
98
|
+
sequencing, bot-triggered repair, the caps, or the deployment push hold.
|
|
99
|
+
|
|
100
|
+
Own-PR repair covers every own PR in the allowlisted repositories; stacking
|
|
101
|
+
changes the order of repair, never the scope. Within one stack the driver
|
|
102
|
+
repairs only the lowest open failing PR of that stack. Every open descendant of
|
|
103
|
+
a repaired PR records exactly one `pending restack` hold naming the repaired
|
|
104
|
+
parent and its new head SHA, and receives no independent repair of the same
|
|
105
|
+
finding while that hold stands. A descendant carrying a different finding from
|
|
106
|
+
the repaired parent's is repaired on its own merits, subject to the budgets
|
|
107
|
+
below; the hold suppresses duplicate application of the same finding, not all
|
|
108
|
+
work on the descendant.
|
|
109
|
+
|
|
110
|
+
The hold names the user as owner. It is cleared by the user's own restack, or by
|
|
111
|
+
a later tick observing the descendant no longer failing; that is the single
|
|
112
|
+
clearing rule. It is exempt from the watchdog's hold with no owner threshold,
|
|
113
|
+
because its owner is the user by construction. The per-tick budget counts one
|
|
114
|
+
unit per stack, not one per PR.
|
|
115
|
+
|
|
116
|
+
The reason is duplication, not politeness: the same finding recurs across a
|
|
117
|
+
stack, so independent per-PR repair would apply the identical fix at several
|
|
118
|
+
levels and the user's next cascade rebase would then conflict on the duplicate.
|
|
119
|
+
A parent fast-forward also does not change a descendant's PR diff, so a
|
|
120
|
+
descendant's CI and reviewers never see the parent fix; the hold states that
|
|
121
|
+
honestly instead of implying the descendant was repaired.
|
|
122
|
+
|
|
123
|
+
`gh stack` sync, restack, rebase, merge, link and submit remain out of scope for
|
|
124
|
+
every automation, and force-push and rebase stay prohibited everywhere. A
|
|
125
|
+
descendant is held, never rewritten.
|
|
126
|
+
|
|
127
|
+
## Bot review feedback (pair C/D)
|
|
128
|
+
|
|
129
|
+
A review authored by a bot account may be actionable and may trigger a repair,
|
|
130
|
+
bounded as follows.
|
|
131
|
+
|
|
132
|
+
Dedup is by processed review ID and by a digest of the review body. A repair
|
|
133
|
+
fires only on a review whose review ID was never processed and whose body
|
|
134
|
+
digest is not already recorded against that PR at that head SHA. Review-ID dedup alone is
|
|
135
|
+
insufficient: a bot that re-posts the identical finding under a new review ID
|
|
136
|
+
would otherwise re-trigger a repair on every tick.
|
|
137
|
+
|
|
138
|
+
Caps: at most one repair per PR per 24 hours, counted regardless of trigger; and
|
|
139
|
+
a per-tick push budget across all allowlisted repositories combined, configured
|
|
140
|
+
per pair and six for pair C/D. Reaching either cap records a hold naming the cap
|
|
141
|
+
and the value reached, rather than silently dropping the work. A budget hold
|
|
142
|
+
names the budget as its owner and is exempt from the hold with no owner
|
|
143
|
+
threshold. When a per-PR cap has expired the precheck wakes the driver even
|
|
144
|
+
if the forge is unchanged, so capped work is never stranded; the precheck
|
|
145
|
+
section below carries that trigger in its due-work list.
|
|
146
|
+
|
|
147
|
+
A bot review never satisfies the peer-PR trigger, which still requires self to
|
|
148
|
+
be officially review-requested or a comment that explicitly asks self to review
|
|
149
|
+
or respond.
|
|
150
|
+
|
|
151
|
+
## Watch window
|
|
152
|
+
|
|
153
|
+
Pair A/B keeps its 24 hours per own PR from first observation, ending early on
|
|
154
|
+
merge or close, with the deadline in `cursor.json`, the `expired` marking, and
|
|
155
|
+
the user re-arming an expired PR in the automation session.
|
|
156
|
+
|
|
157
|
+
Pair C/D uses a rolling window instead: a PR is in scope while it is open and
|
|
158
|
+
eligible, and leaves scope on merge or close. There is no expiry and no
|
|
159
|
+
re-arming, C/D's `cursor.json` stores no deadlines, and `expired` is not a state
|
|
160
|
+
a C/D PR can reach.
|
|
161
|
+
|
|
162
|
+
The difference is deliberate, not drift. A serves one low-volume repository
|
|
163
|
+
where expiry is cheap, while C would otherwise start twenty or more simultaneous
|
|
164
|
+
clocks on first observation and go dark a day later. Because that window
|
|
165
|
+
removes expiry as a cost brake, the per-PR and per-tick budgets and the watchdog
|
|
166
|
+
are the only brakes left on C, and D's thresholds are retuned for a fingerprint
|
|
167
|
+
that legitimately changes on nearly every tick.
|
|
168
|
+
|
|
169
|
+
## PR eligibility for repair (pair C/D)
|
|
170
|
+
|
|
171
|
+
A draft PR is discovered and recorded but never repaired; it becomes eligible
|
|
172
|
+
when it is marked ready for review, which the ordinary event state observes as
|
|
173
|
+
new work. A PR that already has a human reviewer requested is eligible for
|
|
174
|
+
repair and is not excluded, deliberately: most own PRs in these repositories
|
|
175
|
+
carry a requested human reviewer, and excluding them would empty the coverage.
|
|
176
|
+
`defi-com/mobile` has no workflows and therefore no check signal, so a repair
|
|
177
|
+
there is triggered only by actionable review feedback; if CI is later added the
|
|
178
|
+
ordinary check-rollup trigger applies with no contract change.
|
|
179
|
+
|
|
180
|
+
## Deployment safety (pair C/D)
|
|
181
|
+
|
|
182
|
+
A repair never pushes to a PR whose head branch is in that repository's
|
|
183
|
+
deploy-on-push set, and an attempt to do so is a recorded hold. The rule is
|
|
184
|
+
branch-name-agnostic: the set is enumerated per repository from that
|
|
185
|
+
repository's workflow files, recorded, and re-verified before enabling and on
|
|
186
|
+
any later allowlist change. It is never hardcoded to one branch name, because a
|
|
187
|
+
repository may deploy from more than one branch and may add another at any time.
|
|
188
|
+
|
|
189
|
+
## Escalation gate
|
|
190
|
+
|
|
191
|
+
After every mode-required reviewer settles, the driver spawns `axstack-auditor`
|
|
192
|
+
with the verdicts and the candidate revision, instructing it to act as the
|
|
193
|
+
escalation gate. It returns exactly one literal token, `escalate` or `proceed`.
|
|
194
|
+
|
|
195
|
+
- The gate decides only whether the user is notified. Reviewer "yes" is input,
|
|
196
|
+
not a veto.
|
|
197
|
+
- `escalate` → records the hold, then one `hermes send` through
|
|
198
|
+
[axstack-relay](../../axstack-relay/SKILL.md) naming the PR, the criterion,
|
|
199
|
+
every reviewer's reason, where the user acts (Orca conversation, worktree, or
|
|
200
|
+
PR), and the hold; it publishes nothing.
|
|
201
|
+
- `proceed` → no notification; a push or `COMMENT` publication then
|
|
202
|
+
additionally requires no unresolved validated blocking finding, because
|
|
203
|
+
`proceed` never overrides a validated blocking finding. A reviewer security
|
|
204
|
+
"yes" that the gate does not escalate is recorded as rejected-with-evidence
|
|
205
|
+
or returned to the author before any mutation.
|
|
206
|
+
- Only `proceed` plus no unresolved validated blocking finding permits a push
|
|
207
|
+
or publication; a push before the gate settles is forbidden.
|
|
208
|
+
- Precedence: credible serious risk found by a reviewer still produces the
|
|
209
|
+
standing internal prompt and dependent-action hold immediately, and the gate
|
|
210
|
+
governs only external notification. That hold is the serious-risk rule of
|
|
211
|
+
[contracts](contracts.md#serious-risk). The internal prompt lands in the run
|
|
212
|
+
record and the automation's Orca conversation; no `hermes send` occurs
|
|
213
|
+
without `escalate`.
|
|
214
|
+
- The health gate takes a watchdog finding and its evidence, not reviewer
|
|
215
|
+
verdicts or a candidate; the same two tokens apply.
|
|
216
|
+
- An unavailable gate or required reviewer records a hold, pauses mutation for
|
|
217
|
+
that PR, and is treated as a watchdog health finding. An unavailable gate
|
|
218
|
+
cannot be escalated through itself: the hold stays, the gap is visible in
|
|
219
|
+
Orca run history and the sidecar, and no substitute or unauthorized send
|
|
220
|
+
occurs.
|
|
221
|
+
|
|
222
|
+
## Precheck (bounded shell, no model)
|
|
223
|
+
|
|
224
|
+
Resolve self; run the three searches with `--json url,number,repository,updatedAt`;
|
|
225
|
+
write the full discovery list to `pending.json`. For each allowlisted,
|
|
226
|
+
non-expired own PR add head SHA, base SHA, and the check rollup of that head via
|
|
227
|
+
`gh pr view --json headRefOid,baseRefOid,statusCheckRollup`; check state is
|
|
228
|
+
data, and only authentication, command, and network errors are `error`. For pair
|
|
229
|
+
C/D only, that call also requests `isDraft` and the precheck adds draft status
|
|
230
|
+
to the hashed fingerprint, so a draft becoming ready wakes the driver on its
|
|
231
|
+
own; pair A/B's queried fields and fingerprint are unchanged. Hash
|
|
232
|
+
only allowlisted PRs. Read `cursor.json` for the last processed fingerprint and
|
|
233
|
+
for due control work: a watch deadline at or before now (pair A/B only, since
|
|
234
|
+
pair C/D stores no deadlines), a pending failed-relay retry, or a per-PR repair
|
|
235
|
+
cap that has expired (pair C/D only, since pair A/B has no caps). Exit 0 when the hash differs or control work is due;
|
|
236
|
+
otherwise exit non-zero. Exit non-zero without running when the previous driver
|
|
237
|
+
run is still active, or on `error`. Append one line
|
|
238
|
+
`<ts> <changed|due|unchanged|error|busy>` to `precheck.log`.
|
|
239
|
+
|
|
240
|
+
Terminal hygiene runs before the searches and covers driver terminals only.
|
|
241
|
+
Ownership is the driver automation's own recorded `terminalPtyId` from its Orca
|
|
242
|
+
run history, never a terminal title: Orca rewrites a Claude terminal's title to
|
|
243
|
+
the agent's current task summary, so a driver's title drifts and an unrelated
|
|
244
|
+
session can acquire one that reads like a driver. The precheck closes the
|
|
245
|
+
previous ticks' idle driver terminals with `--tab` — without it the pane closes
|
|
246
|
+
but the session stays listed and is never reclaimed, which also makes an
|
|
247
|
+
over-match destructive — and a driver terminal that is still working makes the
|
|
248
|
+
tick `busy`. It never closes a watchdog terminal or any terminal outside this
|
|
249
|
+
automation; an unreadable ownership source is `error`, never a silent empty
|
|
250
|
+
sweep. No two of the four automations may share a dispatch minute: A, B, C and D each
|
|
251
|
+
take a distinct minute, so a driver and its watchdog never collide and neither
|
|
252
|
+
pair can disturb the other's terminal hygiene.
|
|
253
|
+
|
|
254
|
+
The observed fingerprint is written to `pending.json`. After the processed
|
|
255
|
+
tick the driver promotes exactly that value to `cursor.json`, never a
|
|
256
|
+
recomputed one, so an event landing during a run is processed on the following
|
|
257
|
+
tick.
|
|
258
|
+
|
|
259
|
+
## Driver tick
|
|
260
|
+
|
|
261
|
+
Before any repair or publication the driver validates its effective session
|
|
262
|
+
identity through Orca runtime inspection and records it; a self-written label
|
|
263
|
+
is not evidence. Expected model: Opus. A mismatch or unknown identity holds
|
|
264
|
+
repair and publication for that run and is a health finding.
|
|
265
|
+
|
|
266
|
+
For each changed PR:
|
|
267
|
+
|
|
268
|
+
- Own PR → [axstack-watch](../../axstack-watch/SKILL.md) on the exact head
|
|
269
|
+
SHA in a per-PR child worktree; the driver worktree never checks out a PR
|
|
270
|
+
branch. Follow its repair-publication reference: candidate committed locally,
|
|
271
|
+
authored review at the local SHA, gate, then fast-forward push with the
|
|
272
|
+
publication readback immediately before it.
|
|
273
|
+
- Peer PR → two isolated `axstack-review` passes on the exact head SHA, then
|
|
274
|
+
the gate, then one owner-synthesized `COMMENT` review under the review skill's
|
|
275
|
+
COMMENT branch. `INCOMPLETE` or an unavailable required reviewer records a
|
|
276
|
+
hold and publishes nothing.
|
|
277
|
+
|
|
278
|
+
Watch window, pair A/B only: 24 hours per own PR from first observation, ending
|
|
279
|
+
early on merge or close. The deadline is stored in `cursor.json`; a due deadline
|
|
280
|
+
wakes the driver through the precheck even when GitHub is unchanged, and the
|
|
281
|
+
driver rechecks the deadline immediately before any publication. Expiry marks
|
|
282
|
+
the PR `expired` in the record and sidecar, records a resumable handoff, and
|
|
283
|
+
stops silently. The driver skips an expired PR until the user re-arms it in the
|
|
284
|
+
automation session, and the precheck ignores it; an expired PR is never silently
|
|
285
|
+
re-adopted. Pair C/D does not use this window at all; see "Watch window" above
|
|
286
|
+
for its rolling replacement, and it stores no deadline and reaches no `expired`
|
|
287
|
+
state.
|
|
288
|
+
|
|
289
|
+
Per-PR event state: head SHA, base SHA, check rollup, and processed request and
|
|
290
|
+
comment IDs. A review receipt is reused only when head, base, and scope are
|
|
291
|
+
unchanged. A new failing check, base change, review request, or qualifying
|
|
292
|
+
comment at an unchanged head is new work. Pair C/D additionally carries draft
|
|
293
|
+
status in that state, and a draft status that has changed from true to false is
|
|
294
|
+
new work for C/D, which is how a draft becoming ready for review reaches its
|
|
295
|
+
driver.
|
|
296
|
+
|
|
297
|
+
## Watchdog tick
|
|
298
|
+
|
|
299
|
+
Before its gate dispatch the watchdog validates its own effective session
|
|
300
|
+
identity through Orca runtime inspection; unknown identity holds the dispatch
|
|
301
|
+
and is itself recorded in `watchdog.json`.
|
|
302
|
+
|
|
303
|
+
Read Orca run history for the driver, `precheck.log`, and the run record.
|
|
304
|
+
Thresholds: three consecutive `error` lines in `precheck.log`; three
|
|
305
|
+
consecutive failed driver runs; no successful driver run within two hours while
|
|
306
|
+
the precheck logged `changed` or `due`; any unrequested fresh-session fallback
|
|
307
|
+
or non-Opus effective identity recorded by the driver; any `failed` relay
|
|
308
|
+
receipt older than one tick or any `uncertain` receipt; a hold with no owner.
|
|
309
|
+
A quiet precheck history with no due work is healthy.
|
|
310
|
+
|
|
311
|
+
The two-hour stall threshold above is pair A/B's. Pair D uses a stall window
|
|
312
|
+
re-derived before enabling as `max(2h, 3 x the 95th-percentile observed C tick
|
|
313
|
+
duration over at least 10 ticks)`, recorded with its sample, because C's
|
|
314
|
+
fingerprint legitimately changes on nearly every tick and a literal two hours
|
|
315
|
+
would fire on the first slow tick. Every other threshold is identical for both
|
|
316
|
+
pairs.
|
|
317
|
+
|
|
318
|
+
Each health finding gets an occurrence id `(type, first-observed UTC
|
|
319
|
+
timestamp)`; it stays deduplicated while unresolved, and a later recurrence is
|
|
320
|
+
a new occurrence. Pass a finding to the gate under the automation-health
|
|
321
|
+
criterion. On `escalate` the watchdog itself performs that one gate-authorized
|
|
322
|
+
`hermes send` and records the receipt in `watchdog.json`; it never mutates
|
|
323
|
+
GitHub and never writes `progress.md` or `cursor.json`. Failed or uncertain
|
|
324
|
+
delivery stays visibly held in `watchdog.json` and Orca run history.
|
|
325
|
+
|
|
326
|
+
## Run record and sidecar
|
|
327
|
+
|
|
328
|
+
One run id per pair for the lifetime of that pair — `20260916-pr-automations`
|
|
329
|
+
for A/B and `20260916-defi-automations` for C/D — each in the
|
|
330
|
+
[run record](run-record.md) shape with that pair's driver as sole writer of its
|
|
331
|
+
own `progress.md`. C/D's run directory lives under the same axstack
|
|
332
|
+
`git-common-dir` as A/B's, in its own `axstack/runs/<run id>/` folder; no
|
|
333
|
+
sidecar, record, or cursor is shared between the pairs. Per PR it stores processed event IDs, exact head and base SHAs, review receipts
|
|
334
|
+
per SHA, gate decisions, `hermes send` receipts with `message_id` and state, and
|
|
335
|
+
holds. The watch deadline and `expired` fields are pair A/B only, since pair C/D
|
|
336
|
+
stores no deadline and cannot reach `expired`; draft status is pair C/D only,
|
|
337
|
+
since only C/D treats a draft transition as new work. Its
|
|
338
|
+
`Notification policy:` line reads, verbatim:
|
|
339
|
+
|
|
340
|
+
```text
|
|
341
|
+
hermes send, target telegram (home), host VPS, gate-authorized escalations only
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Machine-readable sidecars in the same directory: `pending.json` (observed
|
|
345
|
+
fingerprint plus full discovery list, written by the precheck), `cursor.json`
|
|
346
|
+
(last processed fingerprint promoted verbatim from `pending.json`, expired PR
|
|
347
|
+
list and per-PR watch deadlines for pair A/B only, pending failed-relay
|
|
348
|
+
retries; written by the driver after each processed tick), `precheck.log` (precheck only), and
|
|
349
|
+
`watchdog.json` (watchdog only). Orca run history remains the authoritative
|
|
350
|
+
log; the record is derived progress, never authority.
|
|
351
|
+
|
|
352
|
+
Dedup: a processed event ID is never processed twice; a review receipt is
|
|
353
|
+
reused only for an unchanged head, base, and scope. PR notifications dedup on
|
|
354
|
+
(PR, criterion, head SHA); health notifications dedup on the occurrence id. A
|
|
355
|
+
`failed` relay receipt may be retried once, on the next tick, as due control
|
|
356
|
+
work; an `uncertain` one is never auto-resent.
|
|
357
|
+
|
|
358
|
+
## Safety holds
|
|
359
|
+
|
|
360
|
+
- The driver records its effective identity on every tick. An unrequested
|
|
361
|
+
fresh-session fallback, or a recorded identity different from the expected
|
|
362
|
+
one, pauses mutation for that run, is recorded, and goes to the watchdog
|
|
363
|
+
path. A user-run `--fresh-session` reconciles from the run record and is not
|
|
364
|
+
a hold.
|
|
365
|
+
- GitHub API errors leave the PR state unknown; nothing is pushed or published
|
|
366
|
+
on unknown state.
|
|
367
|
+
- A hold is cleared only by a later run observing the condition resolved, or by
|
|
368
|
+
the user in the Orca conversation. Silence never clears a hold.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Candidate publication
|
|
2
|
+
|
|
3
|
+
This is the author-to-review boundary for an owned candidate. The author stops
|
|
4
|
+
after returning its revision-bound implementation receipt and does not push.
|
|
5
|
+
Within recorded PR-scoped publication authority, the owner reconciles that
|
|
6
|
+
receipt against the actual local candidate SHA and base. The owner does not edit
|
|
7
|
+
the author's candidate; required code changes return to the author.
|
|
8
|
+
|
|
9
|
+
Publish the existing commits through `gh stack`. Prefer a fast-forward push.
|
|
10
|
+
Before a history rewrite, confirm the expected-old remote SHA and use lease
|
|
11
|
+
protection; a mismatch holds publication. If the push outcome is ambiguous,
|
|
12
|
+
inspect remote state before retrying.
|
|
13
|
+
|
|
14
|
+
Before reviewer dispatch, read the remote ref back and confirm that it resolves
|
|
15
|
+
to the candidate SHA; also pin the current base. Record:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
Candidate: <sha>
|
|
19
|
+
Base: <sha>
|
|
20
|
+
Remote ref: <branch>
|
|
21
|
+
Expected-old remote SHA: <sha | absent>
|
|
22
|
+
Confirmed remote SHA: <sha>
|
|
23
|
+
PR: <url>
|
|
24
|
+
CI: <run ID or URL and triggered/pending/completed status>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Local green is not CI green: immediately after publication CI is pending until
|
|
28
|
+
its required checks complete. Review may run in parallel with CI only after the
|
|
29
|
+
remote confirmation. Reviewers inspect a detached immutable checkout of the
|
|
30
|
+
confirmed candidate SHA and pinned base, never only the movable branch name.
|
|
31
|
+
Any author repair creates a new revision and repeats this boundary.
|
|
32
|
+
|
|
33
|
+
## Automation repair exception
|
|
34
|
+
|
|
35
|
+
For an automation repair under
|
|
36
|
+
[Automation sessions](automations.md), the candidate is a local immutable
|
|
37
|
+
commit SHA in the per-PR child worktree, not a published remote ref. The
|
|
38
|
+
reviewer confirms that exact local SHA with `git rev-parse` in the worktree
|
|
39
|
+
instead of remote equality, and inspects a detached checkout of it with the
|
|
40
|
+
pinned base. The remote ref is expected to still be the pre-repair head; record
|
|
41
|
+
it as the expected-old remote SHA rather than requiring it to equal the
|
|
42
|
+
candidate. Remote equality is re-checked at the publication readback of the
|
|
43
|
+
watch skill's repair-publication reference immediately before the fast-forward
|
|
44
|
+
push. Ordinary workflows keep the remote confirmation above; the
|
|
45
|
+
exception never applies outside an automation session.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Standing contracts (standalone phases load this, then follow its pointers)
|
|
2
|
+
|
|
3
|
+
Apply these authority, scope, and model rules before consequential action.
|
|
4
|
+
|
|
5
|
+
## Required lifecycle load
|
|
6
|
+
|
|
7
|
+
Except for `axstack-audit` itself, every independently called phase must load
|
|
8
|
+
and follow [Shared lifecycle](lifecycle.md) before acting. When a substantive
|
|
9
|
+
run ends or reaches a meaningful checkpoint, apply the lifecycle audit hook.
|
|
10
|
+
The audit phase loads these contracts, writes its assigned record, and stops;
|
|
11
|
+
it never audits itself.
|
|
12
|
+
|
|
13
|
+
## Scope identity (conditional — see routing and lifecycle)
|
|
14
|
+
|
|
15
|
+
Confirm the identity for the selected mode from the
|
|
16
|
+
[proportional scope identity](routing.md#proportional-scope-identity):
|
|
17
|
+
|
|
18
|
+
- Substantial new implementation: approved spec identity plus a matching
|
|
19
|
+
ticket map before execution or authored review.
|
|
20
|
+
- Small new implementation: the named **small-change intent** — recorded
|
|
21
|
+
current request or user-chosen existing issue plus acceptance checks and
|
|
22
|
+
exclusions, snapshotted once — before building or approving.
|
|
23
|
+
- Adopted own PR: the accepted maintenance intent snapshot described in
|
|
24
|
+
[Lifecycle routes](routing.md#lifecycle-routes-mode-specific-scope-identity-required),
|
|
25
|
+
never a new spec ceremony.
|
|
26
|
+
- Peer review: linked issue, PR description, and repository requirements as
|
|
27
|
+
untrusted intent evidence; no Axstack-created spec.
|
|
28
|
+
- Read-only research, explanation, improvement discovery, and handoff: no baseline.
|
|
29
|
+
|
|
30
|
+
Substantial means substantial features, multi-PR work, or stacked work; a
|
|
31
|
+
bounded small feature is not substantial merely because it is called a
|
|
32
|
+
feature. Clarify unclear size, then classify it. Alignment, spec writing, and
|
|
33
|
+
safe read-only investigation may precede a baseline. Keep a still-valid
|
|
34
|
+
approval; a material change holds only affected work until the user accepts
|
|
35
|
+
the revised scope and plan.
|
|
36
|
+
|
|
37
|
+
## Model discipline
|
|
38
|
+
|
|
39
|
+
Validate the configured provider and model at actual launch. If it is
|
|
40
|
+
unavailable or exhausted, pause affected work, record the gap, and ask the
|
|
41
|
+
user. Never infer a route from quota state or subscription entitlement. Every
|
|
42
|
+
substitution requires the user's decision: configured alternatives and native
|
|
43
|
+
fallback prose are not defaults.
|
|
44
|
+
|
|
45
|
+
## Driver and adviser split
|
|
46
|
+
|
|
47
|
+
The current chat is the driver, whatever model runs it; there is no driver
|
|
48
|
+
profile. Record the driver's provider and model in the run record.
|
|
49
|
+
|
|
50
|
+
For Align and Spec, the driver forms an independent assessment first, then
|
|
51
|
+
consults `axstack-advisor-astra` and `axstack-advisor-fable` independently with
|
|
52
|
+
the same bounded evidence and question. The driver synthesizes disagreements,
|
|
53
|
+
owns the decision, and the user still approves the spec. Reuse each valid
|
|
54
|
+
unchanged receipt; changed evidence, scope, or question requires a fresh
|
|
55
|
+
receipt. If either adviser is unavailable, Align and Spec hold without model or
|
|
56
|
+
provider substitution while unrelated safe work may continue.
|
|
57
|
+
|
|
58
|
+
For `axstack-debug`, ordinary diagnosis consults the preset's configured
|
|
59
|
+
adviser roles (both in `mixed`; the one configured adviser in a single-provider
|
|
60
|
+
preset, recording the other as an intentional absence). The high-stakes and
|
|
61
|
+
serious-risk contracts override that rule whenever their conditions arise. A
|
|
62
|
+
configured but unavailable adviser holds debug L1 and L2 without substitution.
|
|
63
|
+
Reuse a debug receipt while its evidence packet is unchanged.
|
|
64
|
+
|
|
65
|
+
High-stakes decisions require both advisers' plain AGREE and the driver's
|
|
66
|
+
accepted assessment. Resolve disagreement with bounded checks; silence and an
|
|
67
|
+
unavailable model do not authorize fallback. Ordinary work uses the configured
|
|
68
|
+
author and reviewer roles selected by review mode and the routing snapshot. The
|
|
69
|
+
existing mixed high-stakes route keeps its Opus high author and Sol high
|
|
70
|
+
checkpoint reviewer. An eligible current non-author, non-owner Sol high
|
|
71
|
+
checkpoint can satisfy the authored final review after revalidation; preserve
|
|
72
|
+
its effort and do not add a redundant reviewer. No single-provider high-stakes
|
|
73
|
+
mapping is defined: pause for an explicit user decision rather than borrowing
|
|
74
|
+
another preset or inventing a route. There is no silent fallback.
|
|
75
|
+
|
|
76
|
+
## Serious risk
|
|
77
|
+
|
|
78
|
+
Raise credible serious security, downtime, data-loss, or major-design risk
|
|
79
|
+
immediately through a prompt. Hold approval, merge-ready declarations, and
|
|
80
|
+
dependent dangerous actions while safe independent work continues. Present
|
|
81
|
+
the evidence, likely impact, options, and needed user decision. Disagreement
|
|
82
|
+
or silence is not permission. This remains a prompt contract, not a runtime
|
|
83
|
+
gate.
|
|
84
|
+
|
|
85
|
+
## Authority
|
|
86
|
+
|
|
87
|
+
- The driver owns run scope, cross-PR coordination, integration, and every
|
|
88
|
+
Linear mutation. The checker reports discrepancies only.
|
|
89
|
+
- One Orca execution host owns a run. There is no fixed active-PR count;
|
|
90
|
+
fanout is dependency- and capacity-driven within configured host resource and
|
|
91
|
+
spending limits. The driver reduces fanout when the run record shows rework,
|
|
92
|
+
review backlog, or resource pressure, queues conflicting or dependent work,
|
|
93
|
+
and uses `gh stack` for dependent PRs. Routine shape, split, fanout, and
|
|
94
|
+
exception choices are autonomous driver decisions within the approved scope;
|
|
95
|
+
size alone never requires user approval.
|
|
96
|
+
- Exactly one writer per candidate acts at a time, with one persistent owner
|
|
97
|
+
accountable for each PR. Each PR carries one theme and a measured size under
|
|
98
|
+
[PR shape](pr-shape.md). Unknown capacity metrics are reported as unknown,
|
|
99
|
+
never as a telemetry prerequisite or blocker. Parent changes invalidate
|
|
100
|
+
affected child evidence, which must be refreshed against the new parent.
|
|
101
|
+
- The human merges by default, bottom-up for a stack. Review approval and
|
|
102
|
+
reviewer votes never grant mutation or merge authority.
|