axstack 0.24.1 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +48 -9
  2. package/docs/installation.md +9 -6
  3. package/docs/workflows.md +142 -27
  4. package/package.json +1 -1
  5. package/profiles/presets/claude-only.json +10 -1
  6. package/profiles/presets/codex-only.json +10 -1
  7. package/profiles/presets/mixed.json +16 -7
  8. package/skills/axstack/references/automations.md +41 -3
  9. package/skills/axstack/references/autopilot.md +37 -21
  10. package/skills/axstack/references/candidate-publication.md +10 -0
  11. package/skills/axstack/references/contracts.md +20 -17
  12. package/skills/axstack/references/diligence.md +6 -1
  13. package/skills/axstack/references/lifecycle.md +4 -4
  14. package/skills/axstack/references/pr-shape.md +5 -0
  15. package/skills/axstack/references/pr-triage-nightly.md +22 -0
  16. package/skills/axstack/references/preview.md +53 -0
  17. package/skills/axstack/references/review-manager-prompt.md +6 -3
  18. package/skills/axstack/references/role-roster.md +5 -1
  19. package/skills/axstack/references/routing.md +7 -2
  20. package/skills/axstack/references/run-record.md +4 -1
  21. package/skills/axstack/references/t3-runtime.md +68 -3
  22. package/skills/axstack/references/test-audit-weekly.md +4 -1
  23. package/skills/axstack/references/ui-verification.md +2 -0
  24. package/skills/axstack/scripts/pick-instance.js +110 -0
  25. package/skills/axstack-audit/SKILL.md +5 -3
  26. package/skills/axstack-implement/SKILL.md +25 -10
  27. package/skills/axstack-relay/SKILL.md +37 -11
  28. package/skills/axstack-review/SKILL.md +42 -11
  29. package/skills/axstack-watch/SKILL.md +125 -42
  30. package/skills/axstack-watch/references/repair-publication.md +3 -0
  31. package/skills/axstack-watch/references/watch-runtime.md +34 -12
@@ -45,6 +45,16 @@ remote confirmation. Reviewers inspect a detached immutable checkout of the
45
45
  confirmed candidate SHA and pinned base, never only the movable branch name.
46
46
  Any author repair creates a new revision and repeats this boundary.
47
47
 
48
+ ## Revert line
49
+
50
+ Every own PR description must contain exactly one `Revert` line:
51
+ `Revert: clean` | `Revert: steps: <manual steps>` | `Revert: irreversible: <why>`.
52
+ Use `clean` only when a single `git revert` of the merge commit restores the
53
+ previous behaviour with CI green.
54
+ A `clean` revert leaves no data, schema, config, external, or published effect behind.
55
+ Otherwise use `steps` or `irreversible`.
56
+ Classify every release PR as `irreversible`.
57
+
48
58
  ## Immutable checkout shape
49
59
 
50
60
  The driver creates the immutable review checkout with `git worktree add --detach <run>/checkouts/<key> <sha>` at the confirmed candidate SHA and pinned base.
@@ -40,9 +40,14 @@ the revised scope and plan.
40
40
 
41
41
  Validate the configured provider and model at actual launch. If it is
42
42
  unavailable or exhausted, pause affected work, record the gap, and ask the
43
- user. Never infer a route from quota state or subscription entitlement. Every
43
+ user. Only same-provider, same-model account selection among instances of one
44
+ driver may use headroom under [Provider bindings](t3-runtime.md#preflight-and-binding).
45
+ An exhausted account with no eligible sibling still holds; dispatched roles never fail over mid-thread.
46
+ Follow [Provider bindings](t3-runtime.md#preflight-and-binding) for driver account re-selection at turn boundaries.
47
+ Never infer any other route from quota state or subscription entitlement. Every
44
48
  substitution requires the user's decision: configured alternatives are not
45
49
  defaults. Rejection, timeout, quota and auth failures hold affected work.
50
+ Substitution here means changing provider or model, excluding that account selection.
46
51
  Read the [T3 runtime boundary](t3-runtime.md) before dispatch, receipt consumption
47
52
  or recovery; resolve models from the saved capabilities snapshot and verify
48
53
  requested and effective settings separately.
@@ -103,19 +108,17 @@ gate.
103
108
 
104
109
  ## Authority
105
110
 
106
- - The driver owns run scope, cross-PR coordination, integration, and every
107
- selected external-tracker mutation. The checker reports discrepancies only.
108
- - One T3 host/server owns a run. There is no fixed active-PR count;
109
- fanout is dependency- and capacity-driven within configured host resource and
110
- spending limits. The driver reduces fanout when the run record shows rework,
111
- review backlog, or resource pressure, queues conflicting or dependent work,
112
- and uses `gh stack` for dependent PRs. Routine shape, split, fanout, and
113
- exception choices are autonomous driver decisions within the approved scope;
114
- size alone never requires user approval.
115
- - Exactly one writer per candidate acts at a time, with one persistent owner
116
- accountable for each PR. Each PR carries one theme and a measured size under
117
- [PR shape](pr-shape.md). Unknown capacity metrics are reported as unknown,
118
- never as a telemetry prerequisite or blocker. Parent changes invalidate
119
- affected child evidence, which must be refreshed against the new parent.
120
- - The human merges by default, bottom-up for a stack. Review approval and
121
- reviewer votes never grant mutation or merge authority.
111
+ - The driver owns scope, cross-PR coordination, integration, and every selected
112
+ external-tracker mutation. Checker reports discrepancies only.
113
+ - One T3 host/server owns a run. No fixed active-PR count; fanout is dependency-
114
+ and capacity-driven within host resource and spending limits. Reduce fanout for
115
+ recorded rework, review backlog, or resource pressure. Queue conflicts and
116
+ dependencies; use `gh stack` for dependent PRs. Routine shape, split, fanout, and
117
+ exception choices within approved scope are autonomous driver decisions; size alone never
118
+ requires user approval.
119
+ - Exactly one writer per candidate; one persistent accountable PR owner. Each PR has one theme and measured size under [PR shape](pr-shape.md). Report unknown capacity
120
+ metrics; never a telemetry prerequisite or blocker. Parent changes invalidate
121
+ affected child evidence; refresh it against the new parent.
122
+ - Own PRs default to automatic merge under [watch §5](../../axstack-watch/SKILL.md).
123
+ Review approval and reviewer votes alone never grant mutation or merge authority.
124
+ User merges are bottom-up for a stack.
@@ -7,6 +7,11 @@ It is read-only, never authors or edits, and returns `PASS`, `FINDINGS`, or `UNK
7
7
  with locations, observed evidence, and limits. A stale or missing receipt is
8
8
  not a pass. Keep its first pass independent of other reviewers and workers.
9
9
 
10
+ Load [Finding severity](../../axstack-review/SKILL.md#finding-severity) for the shared rubric.
11
+ Diligence returns `FINDINGS` for any `medium` or `high` mismatch.
12
+ Diligence returns `PASS` with the low items listed when only low mismatches remain.
13
+ Keep diligence `UNKNOWN` unchanged.
14
+
10
15
  For a PR, compare every changed line with the accepted intent and exclusions:
11
16
  is it intended and in scope? Check that no contract, rule, or obligation was
12
17
  silently weakened or dropped by rewording. Compare the PR body, commit messages,
@@ -30,5 +35,5 @@ Report an attributed failure with its retained output normally.
30
35
  An observed full-suite failure still fails the suite, including when attributed or reported `UNKNOWN`.
31
36
  No reruns are required.
32
37
 
33
- `FINDINGS` identifies a mismatch for the driver to resolve at the owning phase;
38
+ `FINDINGS` identifies a medium or high mismatch for the driver to resolve at the owning phase;
34
39
  it does not edit the artifact or create another review round by itself.
@@ -9,9 +9,9 @@ binding state and receipts to exact revisions.
9
9
 
10
10
  - Driver: current chat; owns scope, decisions, cross-PR dependencies,
11
11
  external-tracker mutations, integration.
12
- - Owner: driver owns loop PRs; `axstack-owner` only for standalone watch/review
13
- without live driver. It may perform PR-scoped publication within user authority. Human
14
- merge is default.
12
+ - Owner: driver for loop PRs; `axstack-owner` for standalone watch/review without
13
+ a live driver. PR-scoped publication is within user authority.
14
+ Own PRs default to automatic merge under watch §5's predicate.
15
15
  - Author: exactly one writer per candidate; accepted fixes return there.
16
16
  Workers launch no recursive teams.
17
17
  - Reviewers: peer = two configured roles with the same brief and isolated first
@@ -121,7 +121,7 @@ The default 24-hour deadline covers standalone task-owned timers. Stop them at
121
121
  deadline and preserve remaining work; the review automation has no task-owned
122
122
  deadline. Merge-ready requires applicable review receipt(s) and current diligence
123
123
  `PASS` at the exact head; CI/tests alone are insufficient. Merge-ready
124
- differs from merged; human merges.
124
+ differs from merged.
125
125
 
126
126
  ## Review automation health
127
127
 
@@ -24,6 +24,11 @@ migrations that must change together to stay green and reviewable.
24
24
  This is not a folder restriction. Unrelated themes split even under the target.
25
25
  Smaller cohesive PRs are encouraged; no padding.
26
26
 
27
+ ## PR body
28
+
29
+ Every own PR description must contain exactly one `Revert` line.
30
+ Follow [Revert line](candidate-publication.md#revert-line) for its format and classification.
31
+
27
32
  ## Exception band
28
33
  The driver attempts a reasonable split first. If each tried split materially
29
34
  compromises atomicity, green state, or independent reviewability, or inseparable
@@ -0,0 +1,22 @@
1
+ # Nightly PR-triage prompt
2
+
3
+ You are a fresh read-only nightly PR-triage pass in your own T3 thread.
4
+ Read-only applies to the forge, and own schedule replacement follows [Provider bindings](t3-runtime.md#preflight-and-binding).
5
+ At pass start, follow [Provider bindings](t3-runtime.md#preflight-and-binding) for your own account and schedule binding.
6
+ Use [Nightly PR-triage setup](automations.md#nightly-pr-triage-setup) for activation.
7
+ Read the durable activation record for the repository set.
8
+ Resolve the user with `gh api user --jq .login`.
9
+ Read all open PRs authored by the user in every repository in the recorded set,
10
+ including all pages.
11
+
12
+ Report each PR's CI, reviews, mergeable state, and unresolved threads in your
13
+ own T3 thread.
14
+ For each unavailable, failed, or incomplete forge field, report `UNKNOWN`.
15
+ Report incomplete repository or pagination coverage explicitly.
16
+ Flag stale PRs after 7 days of inactivity.
17
+ Report the top three PRs to act on with reasons drawn from the observed state.
18
+ If fewer than three PRs exist, report those available.
19
+ Never declare a PR merge-ready.
20
+
21
+ Never merge, post comments, change labels, push, send relay messages, dispatch
22
+ work, or launch threads.
@@ -0,0 +1,53 @@
1
+ # PR previews
2
+
3
+ Only the PR owner runs this procedure for private previews over the tailnet.
4
+ The tailnet is the user's private Tailscale network.
5
+ Preview authority covers only the preview unit and its `tailscale serve` route on the VPS.
6
+ This procedure grants no release, npm publish, or host install authority.
7
+ A later release run under `AGENTS.md` needs its own recorded authority.
8
+
9
+ ## Decide
10
+
11
+ Start a preview only when the run's T3 host is the VPS.
12
+ On any other host, record "no preview: run host is not the VPS" and continue.
13
+ For each own PR, the owner decides whether a preview makes sense.
14
+ Require both a runnable dev-server command documented in the base branch's `AGENTS.md` or README and a user-visible change in the PR.
15
+ Read the command only from the base.
16
+ Never read the command from the PR head.
17
+ If either requirement is missing, record "no preview".
18
+
19
+ Report missing systemd user lingering or Tailscale operator rights as "no preview".
20
+ Never change systemd user lingering or Tailscale operator rights.
21
+ Never change unrelated host services or configuration.
22
+ Run at most two previews per host.
23
+ A third preview waits until a slot frees.
24
+
25
+ ## Start and record
26
+
27
+ The owner starts the preview from an isolated checkout of the PR head as a systemd user unit.
28
+ Set `RuntimeMaxSec=4h`, `MemoryMax=2G`, and `CPUQuota=200%`.
29
+ Use only repository-documented dev or test environment sources.
30
+ Never use production secrets for a preview in any repository.
31
+ After start, confirm the process listens only on loopback.
32
+ After start, confirm the `tailscale serve` target is `127.0.0.1:<port>`.
33
+ If either loopback check fails, tear down and record "no preview: not loopback-only".
34
+ Never use Tailscale Funnel.
35
+
36
+ Record `Preview: <url> @ <served-sha>` in the run record and the driver thread.
37
+ Label it as the served revision, distinct from the PR head SHA.
38
+ Put the Preview line and any "preview queued" note in the PR description only for private repositories.
39
+ After each restart or teardown, update or remove the Preview line and any "preview queued" note in the private PR description.
40
+ Update or remove the run-record and driver-thread preview records after each restart or teardown.
41
+
42
+ The `axstack-ui-verifier` can use the preview URL.
43
+ A preview never replaces UI verification.
44
+ Follow [UI verification](ui-verification.md) for the independent rendered pass.
45
+
46
+ ## Restart and teardown
47
+
48
+ When the PR head changes, restart the preview on the new head.
49
+ Run teardown when the PR merges or closes, the watch ends, or the time limit stops the unit.
50
+ Use `ExecStopPost` to remove the route when the time limit stops the unit.
51
+ At teardown, remove both the unit and its `tailscale serve` route.
52
+ Read back the absence of both the unit and its `tailscale serve` route.
53
+ If teardown fails, hold and record a receipt.
@@ -1,12 +1,15 @@
1
1
  # Review manager prompt
2
2
 
3
+ At pass start, follow [Provider bindings](t3-runtime.md#preflight-and-binding) for own account selection.
4
+
3
5
  You are a fresh finite T3 review-manager pass in project `axstack-review-lane`
4
6
  on the VPS's existing `axatbhardwaj/axstack` clone. Fetch first; this unbound
5
7
  pass worktree starts from `origin/main`. Enter through installed `axstack-review`,
6
8
  which loads `../axstack/references/automations.md` relatively. Read that contract
7
- and [T3 runtime](t3-runtime.md). Verify your configuration against the recorded
8
- `axstack-owner` binding before admission. Reconcile the whole lane, discover
9
- all eligible peer-review events and admit within measured host capacity.
9
+ and [T3 runtime](t3-runtime.md). Reconcile lane ownership and duplicate status,
10
+ then follow [Provider bindings](t3-runtime.md#preflight-and-binding) for shared schedule
11
+ recreation and recorded instance update before verifying the recorded `axstack-owner`
12
+ binding before admission. Discover all eligible peer-review events and admit within measured host capacity.
10
13
  Use host-clone detached per-PR checkouts; preserve exact ownership and receipts.
11
14
  Retire settled predecessors, report retained worktree count, and disable the
12
15
  schedule and hold past its authorized limit. Save and read back continuity at
@@ -2,7 +2,11 @@
2
2
 
3
3
  - Chat drives (no role ID); `axstack-owner` owns one PR and
4
4
  `axstack-author` its sole writer.
5
- - `axstack-reviewer-primary` and `axstack-reviewer-secondary` are the ordered
5
+ For own PRs, automatic merge is the default under the
6
+ [watch predicate](../../axstack-watch/SKILL.md#5-state-readiness-precisely).
7
+ Only the recorded owning watch thread merges, including `axstack-owner`
8
+ for authorized standalone maintenance. Other roles never acquire merge authority.
9
+ - `axstack-reviewer-primary` and `axstack-reviewer-peer` are the ordered
6
10
  peer pair. Peer review uses both; authored review uses this table:
7
11
 
8
12
  | Preset | Author class | Reviewer (class/effort) |
@@ -10,6 +10,9 @@ Presets: `mixed`, `codex-only`, `claude-only`. For new runs, use
10
10
  skills root, or an explicit user selection in the run record. Missing or contradictory sources are
11
11
  a setup gap: hold. Never infer from live profiles, harness,
12
12
  tools, credentials, quota, subscription, or default to `mixed`.
13
+ Only same-provider, same-model account selection among instances of one driver
14
+ may use headroom under [Provider bindings](t3-runtime.md#preflight-and-binding);
15
+ provider/model substitution still requires the user's decision.
13
16
 
14
17
  At start, snapshot all role IDs from installed `skills/axstack/roles.json`,
15
18
  including provider/modelClass/model/mode/effort and intentional absences.
@@ -35,6 +38,8 @@ An unavailable provider, model, role, mode or effort holds that role with no sub
35
38
  Preset changes apply to new runs only; an active run keeps its snapshot.
36
39
  Replacing a session needs an explicit user decision and revalidation.
37
40
  Timeout, quota, auth and rejection hold affected work.
41
+ An exhausted account with no eligible sibling still holds; dispatched roles never fail over mid-thread.
42
+ Follow [Provider bindings](t3-runtime.md#preflight-and-binding) for driver account re-selection at turn boundaries.
38
43
  [Model discipline](contracts.md#model-discipline) governs optional seats,
39
44
  auditor preflight, and required holds; [Role roster](role-roster.md) governs
40
45
  single-provider absence and mixed Codex+Claude fan-out.
@@ -102,8 +107,8 @@ reason in the run record, or in the brief for tiny direct work.
102
107
  issue plus explicit acceptance checks and exclusions, snapshots it once, and
103
108
  proceeds. No prior snapshot, spec, tickets, or second approval is required; do not route
104
109
  to `axstack-align` solely because the snapshot is not yet written. Strict TDD,
105
- mode-specific review, model, risk, and human-merge
106
- contracts still apply.
110
+ mode-specific review, model, risk, and merge-authority contracts still apply.
111
+ Own PRs default to automatic merge under watch §5 predicate.
107
112
  - **Unclear:** clarify via `axstack-align` or a bounded question, then
108
113
  classify small or substantial; it does not force substantial-work paperwork.
109
114
  [Design lens](design-lens.md) Rung 1 is Unclear; use `axstack-align`.
@@ -97,7 +97,9 @@ send, or watch can be looked up before any retry.
97
97
  Resume from compact pointers to commands or evidence, not copied transcripts.
98
98
  For chat-run watch, record the bound T3 schedule and scheduledTaskId,
99
99
  member PR publication/adoption receipts, exact driver threadId/runId, observation/report
100
- IDs, disposition, wake and stop receipts in this same record. The driver alone writes it; a later same-Run publication joins the membership only after remote readback. Reconcile named threads/runs, revisions, PR state, watches, and deliveries before
100
+ IDs, disposition, wake and stop receipts in this same record.
101
+ Record the chat-run watch cadence, last PR event, native schedule lifetime, and re-arm receipts.
102
+ The driver alone writes it; a later same-Run publication joins the membership only after remote readback. Reconcile named threads/runs, revisions, PR state, watches, and deliveries before
101
103
  creating or redelivering anything. Outside the bounded driver-start orphan
102
104
  sweep, touch only this run; no unscoped global sweep, runtime database, or
103
105
  scheduler follows from the record.
@@ -185,6 +187,7 @@ Source base: <exact revision or source identity>
185
187
  IDs: <projectId + driver threadId/runId + dispatch identity receipt pointers>
186
188
  Runtime: <host + T3 version + installed Axstack SHA + capabilities JSON path>
187
189
  Schedules: <scheduledTaskIds of every watch and manager schedule>
190
+ Watch: <member publication/adoption receipts + cadence + last PR event + native lifetime + update/re-arm/stop receipts>
188
191
  Worktrees in other repositories: <per-run repository and worktree IDs or none>
189
192
  Evidence: <check/review/submission/audit receipt pointers>
190
193
  Pending: <launch/acceptance/external receipts + scheduledTaskIds + runIds + deadline>
@@ -16,8 +16,66 @@ preset and stable role IDs, requested provider/model/class/mode/effort, resolved
16
16
  ID, source and time once. Resume preserves that snapshot with no re-resolution;
17
17
  changes require the user's explicit decision. Bundled presets are setup inputs.
18
18
 
19
- Provider bindings must map codex→`codex`, claude→`claudeAgent`, grok→`grok`,
20
- antigravity→`antigravity`. Map `modeId` to `runtimeMode:full-access` and effort
19
+ Provider bindings must map grok→`grok` and antigravity→`antigravity`, with
20
+ canonical error-exit fallbacks codex→`codex` and claude→`claudeAgent`.
21
+ At each dispatch or launch, claude and codex must bind to the instanceId printed
22
+ by `scripts/pick-instance.js --provider <provider>`.
23
+ For dispatched roles, only error exit 1 permits fallback to the canonical instance after validating availability.
24
+ Exit 2 (no eligible provider instances) must hold the work without fallback.
25
+ Record the chosen instanceId and a pointer to saved `--json` output in the dispatch record.
26
+ Only same-provider, same-model account selection among instances of one driver
27
+ is permitted, with provider, model, class and effort rules required to remain unchanged.
28
+ An exhausted account with no eligible sibling must hold.
29
+ Dispatched roles never fail over mid-thread.
30
+
31
+ When the driver starts or resumes a run and at the start of every run-watch wake,
32
+ it runs `scripts/pick-instance.js --provider <its own provider> --json`.
33
+ Read its current binding with `t3_thread_configuration` and save picker JSON in private run evidence.
34
+ If the driver's own current instance is `excluded` for a usage limit and an eligible
35
+ same-provider sibling exists, it must switch itself via `t3_thread_configure` to the
36
+ chosen sibling instance, keeping the same provider, model and effort/options, then continue.
37
+ The driver must record from/to instance, a pointer to saved picker JSON and UTC time in `progress.md`.
38
+ If the driver's own current instance is eligible, it must stay despite headroom differences.
39
+ On exit 2 (no eligible sibling), the driver must hold under the existing rule.
40
+ On error exit 1, the driver must keep its current instance.
41
+ Driver account re-selection must configure only the calling thread and only at a turn boundary.
42
+ A turn already paused by a usage limit cannot self-recover.
43
+ The next wake or user message runs this check.
44
+
45
+ Driver self-switching is required from v0.25.1.
46
+ T3 scheduled tasks retain the creation-time instanceId for wakes and fresh-thread
47
+ passes regardless of the calling thread's current binding.
48
+ The driver must arm a run watch only after picking its account: `pick-instance.js` before `schedule_task`.
49
+ On a driver self-switch, delete and recreate its armed bound run watch with the
50
+ same prompt, cadence and binding on the new instance.
51
+
52
+ Every scheduled automation pass runs `scripts/pick-instance.js --provider <its own provider> --json`
53
+ at pass start, including fresh-thread review-manager passes.
54
+ Scheduled passes follow the driver's eligibility and stay rules: an eligible own instance stays,
55
+ exit 1 keeps the current instance and exit 2 holds.
56
+ If a scheduled pass's own current instance is `excluded` and an eligible same-provider sibling exists,
57
+ it must switch itself via `t3_thread_configure` to the chosen sibling instance,
58
+ keeping the same provider, model and effort/options.
59
+ On a scheduled pass self-switch in a review-manager lane, only the owner-of-record, after lane reconciliation
60
+ and the duplicate check, must delete and recreate its own schedule with the same
61
+ prompt, cadence and binding on the chosen instance.
62
+ On any other scheduled pass self-switch, delete and recreate its own schedule with
63
+ the same prompt, cadence and binding on the chosen instance only after `list_scheduled_tasks`
64
+ confirms no replacement for that schedule on the chosen instance already exists.
65
+ If a replacement for that schedule on the chosen instance already exists, any other scheduled pass must skip recreation.
66
+ For a review-manager self-switch, only the owner-of-record must update the recorded
67
+ `axstack-owner` binding's instanceId to the chosen instance after verifying unchanged
68
+ provider/model/effort/options with `t3_thread_configuration` and attaching the picker
69
+ switch receipt, before the admission binding comparison.
70
+ For each schedule replacement, read back old absence and new presence using `list_scheduled_tasks`.
71
+ For each schedule replacement, record old/new scheduledTaskId, from/to instance,
72
+ picker JSON pointer and UTC time in the `progress.md` or durable activation/continuity record.
73
+ Retain the recorded schedule's title and enabled state and use a fresh stable creation `clientRequestId`.
74
+ An uncertain replacement holds affected work: preserve its native receipts for reconciliation.
75
+ A scheduled pass already running on an exhausted account cannot recover.
76
+ Account switches must happen before exhaustion at the picker's near-limit cutoff.
77
+
78
+ Map `modeId` to `runtimeMode:full-access` and effort
21
79
  to `options:[{id,value}]`. Stored permission intent is neither effective parity
22
80
  nor a security boundary.
23
81
 
@@ -27,6 +85,7 @@ A preset model must be used as given.
27
85
  codex `gpt-<N>-<class>`, claude `claude-<class>-<N>-<N>`. Use
28
86
  `scripts/resolve-models.js --provider` with the saved capabilities JSON path;
29
87
  a missing or malformed catalog holds resolution.
88
+ Model catalog resolution retains the canonical instance IDs above.
30
89
 
31
90
  A `model:null` role lacking a class must use the first model listed for its
32
91
  provider in saved capabilities only for grok and antigravity (launch-by-agent-id
@@ -40,6 +99,8 @@ absence and must hold; never use a provider default for that role.
40
99
 
41
100
  An unavailable provider, model, role, mode or effort must hold that role with
42
101
  no substitution. Auth, quota, timeout and rejection do not select an alternative.
102
+ Here alternative means a provider or model substitution, excluding the bounded
103
+ same-provider, same-model account selection above.
43
104
  Intentional absent seats remain recorded absences; availability is runtime proof.
44
105
 
45
106
  Codex effort must use option ID `reasoningEffort`.
@@ -234,4 +295,8 @@ The boundary must provide no Axstack daemon, DB, lock or scheduler. Native T3
234
295
  schedules supply wakes; Axstack maintains prose records, not a runtime state
235
296
  engine. Private evidence requires explicit publication authority before sharing;
236
297
  receipts confer no merge, release, publication, model-substitution, host-mutation
237
- or expanded scope authority. Human merges by default.
298
+ or expanded scope authority.
299
+ For own PRs, automatic merge is the default under the
300
+ [watch predicate](../../axstack-watch/SKILL.md#5-state-readiness-precisely).
301
+ The recorded owning watch thread merges; a missing or idle owner requires
302
+ lifecycle reconciliation and explicit transfer first.
@@ -1,5 +1,7 @@
1
1
  # Weekly test-audit prompt
2
2
 
3
+ At pass start, follow [Provider bindings](t3-runtime.md#preflight-and-binding) for account selection and schedule recreation.
4
+
3
5
  You are a fresh finite weekly test-audit session in this repository's dedicated
4
6
  T3 project worktree. Before admission, read the activation record: repository,
5
7
  test-path allowlist, finite budget, and standing edit and PR-open authority.
@@ -54,7 +56,8 @@ Keep one writer and private revision-bound receipts; workers never push.
54
56
  Obtain independent review using Implement's configured authored-review roles and
55
57
  verify the exact candidate's checks before publication. The driver uses
56
58
  `gh stack` and opens at most one test-audit PR per week after independent review;
57
- the human merges.
59
+ for own PRs, automatic merge is the default under the
60
+ [watch predicate](../../axstack-watch/SKILL.md#5-state-readiness-precisely).
58
61
 
59
62
  Notify only under the run's Notification policy: a decision park, merge-ready
60
63
  (within the run's milestone cap), or serious-risk hold; never progress or
@@ -6,6 +6,8 @@ run's role snapshot. Give it the exact build, URL, or artifact and the private
6
6
  dispatch's evidence folder. The verifier is read-only: it never edits source.
7
7
  The PR writer remains the sole writer.
8
8
 
9
+ Before using a PR preview URL, the UI verifier must read [PR previews](preview.md).
10
+
9
11
  The sole author browser exception is archify `finalize` as a headless build gate.
10
12
  Keep finalize outputs only in the private evidence folder.
11
13
  Never replace the verifier's rendered pass with finalize.
@@ -0,0 +1,110 @@
1
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+
3
+ const weights = {
4
+ claude: { default_claude_max_20x: 4, default_claude_max_5x: 1 }, codex: { pro: 4, prolite: 1 },
5
+ };
6
+ const drivers = { claude: 'claudeAgent', codex: 'codex' };
7
+ const home = process.env.HOME;
8
+ const expandHome = (path) => path === '~' ? home : path.startsWith('~/') ? `${home}/${path.slice(2)}` : path;
9
+ const readJson = (path) => JSON.parse(readFileSync(path, 'utf8'));
10
+ const cacheDir = `${process.env.XDG_CACHE_HOME || `${home}/.cache`}/axstack`;
11
+ const cachePath = `${cacheDir}/usage.json`;
12
+ let cache;
13
+ try { cache = readJson(cachePath); } catch { cache = {}; }
14
+ if (!cache || typeof cache !== 'object' || Array.isArray(cache)) cache = {};
15
+
16
+ function argumentsFrom(args) {
17
+ const options = {};
18
+ for (let i = 0; i < args.length; i++) {
19
+ const flag = args[i];
20
+ if (flag === '--json' && !options.json) { options.json = true; continue; }
21
+ if (!['--provider', '--settings'].includes(flag) || flag.slice(2) in options) {
22
+ throw new Error('expected --provider claude|codex [--settings path] [--json]');
23
+ }
24
+ const value = args[++i];
25
+ if (!value || value.startsWith('--')) throw new Error('missing argument value');
26
+ options[flag.slice(2)] = value;
27
+ }
28
+ if (!Object.hasOwn(drivers, options.provider)) throw new Error('expected --provider claude|codex');
29
+ return options;
30
+ }
31
+
32
+ async function account(instanceId, instance, provider) {
33
+ const config = instance.config ?? {};
34
+ const dir = expandHome((provider === 'claude' ? config.homePath : config.shadowHomePath || config.homePath)
35
+ || `${home}/.${provider}`);
36
+ let credentials;
37
+ try {
38
+ credentials = readJson(`${dir}/${provider === 'claude' ? '.credentials.json' : 'auth.json'}`);
39
+ const valid = provider === 'claude' ? credentials.claudeAiOauth?.accessToken
40
+ : credentials.tokens?.access_token && credentials.tokens?.account_id;
41
+ if (!valid) throw new Error();
42
+ } catch {
43
+ return { instanceId, score: null, state: 'skipped', reason: 'missing credentials' };
44
+ }
45
+ const headers = provider === 'claude'
46
+ ? { authorization: `Bearer ${credentials.claudeAiOauth.accessToken}`,
47
+ 'anthropic-beta': 'oauth-2025-04-20', 'user-agent': 'claude-cli/2.1.0 (external, cli)' }
48
+ : { authorization: `Bearer ${credentials.tokens.access_token}`,
49
+ 'chatgpt-account-id': credentials.tokens.account_id };
50
+ const url = provider === 'claude'
51
+ ? process.env.AXSTACK_CLAUDE_USAGE_URL || 'https://api.anthropic.com/api/oauth/usage'
52
+ : process.env.AXSTACK_CODEX_USAGE_URL || 'https://chatgpt.com/backend-api/wham/usage';
53
+ const key = JSON.stringify([provider, dir]);
54
+ let value = cache[key];
55
+ if (!Number.isFinite(value?.updatedAt) || !(value.utilization === null || Number.isFinite(value.utilization))
56
+ || typeof value.limitReached !== 'boolean') value = undefined;
57
+ let state = 'cached';
58
+ if (!value || Date.now() - value.updatedAt >= 5 * 60 * 1000) {
59
+ try {
60
+ const response = await fetch(url, { headers, signal: AbortSignal.timeout(5000) });
61
+ if (!response.ok) throw new Error();
62
+ const usage = await response.json();
63
+ const windows = provider === 'claude'
64
+ ? [usage.five_hour?.utilization, usage.seven_day?.utilization]
65
+ : [usage.rate_limit?.primary_window?.used_percent, usage.rate_limit?.secondary_window?.used_percent];
66
+ const known = windows.filter((value) => typeof value === 'number' && Number.isFinite(value));
67
+ value = { updatedAt: Date.now(),
68
+ tier: provider === 'claude' ? credentials.claudeAiOauth.rateLimitTier : usage.plan_type,
69
+ utilization: known.length ? Math.max(...known) : null, limitReached: usage.rate_limit?.limit_reached === true };
70
+ cache[key] = value;
71
+ state = 'fresh';
72
+ try {
73
+ mkdirSync(cacheDir, { recursive: true, mode: 0o700 });
74
+ writeFileSync(cachePath, JSON.stringify(cache), { mode: 0o600 });
75
+ } catch { /* Cache availability must not prevent account selection. */ }
76
+ } catch {
77
+ state = value ? 'stale' : 'unknown';
78
+ value ??= { tier: credentials.claudeAiOauth?.rateLimitTier, utilization: null };
79
+ }
80
+ }
81
+ const stale = state === 'stale';
82
+ if (value.utilization >= 95 || value.limitReached) {
83
+ return { instanceId, score: null, state: 'excluded', stale, reason: 'usage limit' };
84
+ }
85
+ const weight = Object.hasOwn(weights[provider], value.tier) ? weights[provider][value.tier] : 1;
86
+ return { instanceId, score: value.utilization === null ? weight : (100 - value.utilization) * weight,
87
+ state: value.utilization === null ? 'unknown' : state, stale };
88
+ }
89
+
90
+ try {
91
+ const options = argumentsFrom(process.argv.slice(2));
92
+ const settings = readJson(expandHome(options.settings || `${home}/.t3/userdata/settings.json`));
93
+ if (!settings?.providerInstances || typeof settings.providerInstances !== 'object'
94
+ || Array.isArray(settings.providerInstances)) throw new Error();
95
+ const instances = [];
96
+ for (const [instanceId, instance] of Object.entries(settings.providerInstances).filter(([, instance]) =>
97
+ instance.enabled && instance.driver === drivers[options.provider])) {
98
+ instances.push(await account(instanceId, instance, options.provider));
99
+ }
100
+ const chosen = instances.filter((instance) => instance.score !== null).sort((a, b) => b.score - a.score)[0];
101
+ if (!chosen) {
102
+ console.error('account selection hold: no eligible provider instances');
103
+ process.exitCode = 2;
104
+ } else {
105
+ console.log(options.json ? JSON.stringify({ chosenInstanceId: chosen.instanceId, instances }) : chosen.instanceId);
106
+ }
107
+ } catch {
108
+ console.error('account selection failed: invalid input/settings or unexpected error');
109
+ process.exitCode = 1;
110
+ }
@@ -42,8 +42,10 @@ If the base auditor is unlaunchable (preflight rejection, no Dispatch started),
42
42
  record `auditor: UNKNOWN (unlaunchable)` with the attempted route and error as
43
43
  the archive receipt; archive the run. A launched auditor Dispatch must settle
44
44
  normally. There is no substitution for the base auditor.
45
- The user-chosen improvement mode is a tested, independently reviewed PR that a
46
- human merges.
45
+ The user-chosen improvement mode is a tested, independently reviewed PR.
46
+ For own PRs, automatic merge is the default under the
47
+ [watch predicate](../axstack-watch/SKILL.md#5-state-readiness-precisely).
48
+ The auditor never merges.
47
49
 
48
50
  Act as a non-author, read-only reader of the run. The assigned audit artifact is
49
51
  `audit.md`, the only writable output. Make no edits to product, skills,
@@ -151,7 +153,7 @@ Each proposal names:
151
153
  4. a regression scenario first, followed by an unchanged holdout evaluation;
152
154
  5. a cost and quality comparison when those values were measured; and
153
155
  6. the authorized delivery path: the auditor suggests, the driver arranges an
154
- author and independent review, a reviewed PR is proposed, and a human merges.
156
+ author and independent review, a reviewed PR is proposed, and the owning watch thread applies watch §5, including its user-merge exclusions.
155
157
 
156
158
  Keep evaluation data, candidate changes, and validation separate. This is an
157
159
  original Axstack workflow with no outside dependency or extra framework to
@@ -189,6 +189,10 @@ The author stops at that receipt and does not push. The driver reconciles it,
189
189
  uses `gh stack` to publish, confirms remote readback, and continues the loop
190
190
  without editing the candidate. No step grants merge authority.
191
191
 
192
+ Every own PR description must contain exactly one `Revert` line.
193
+ Follow [Revert line](../axstack/references/candidate-publication.md#revert-line)
194
+ for its format and classification.
195
+
192
196
  ## 6. Loop until merge-ready
193
197
 
194
198
  Inputs are one snapshotted small-change intent or an approved spec and ticket
@@ -202,6 +206,8 @@ For each PR:
202
206
 
203
207
  1. Dispatch `axstack-author` under §§3-5 and consume its strict-TDD receipt.
204
208
  2. Publish through candidate-publication and read back the exact SHA.
209
+ For each own PR, the owner must follow [PR previews](../axstack/references/preview.md)
210
+ to decide whether a preview makes sense.
205
211
  3. Dispatch and consume the authored-mode `axstack-review` selected from actual
206
212
  author provenance. State the author's actual provider and model from the
207
213
  T3 launch receipt in the review dispatch brief; a `Claude-Session`
@@ -239,9 +245,10 @@ For each PR:
239
245
  `repairs` once and counts once toward the third-round hold.
240
246
 
241
247
  The T3 run watch reconciles every unsettled dispatch attempt; the bounded
242
- forge check wait is the only other implementation wait. The eligible run arms
243
- one maintain-mode chat-run watch at its first published PR; that watch owns its
244
- bound 10-minute T3 schedule wake.
248
+ forge check wait is the only other implementation wait.
249
+ After verified readback of every own PR publication, the driver arms or joins
250
+ its maintain-mode chat-run watch under [Autopilot](../axstack/references/autopilot.md).
251
+ That watch owns the bound T3 schedule wake; its runtime sets the cadence.
245
252
  A turn with unsettled launched threads must end only under the bound-watch rule in the T3 runtime contract.
246
253
  With settled threads, end a turn only when every required PR is `merge-ready` or `held`. Under the recorded Notification policy,
247
254
  `axstack-relay` sends only a serious risk immediately, a genuine blocked
@@ -253,13 +260,21 @@ Only the bounded categories—user-decision holds (including spec approval),
253
260
  serious-risk holds, and at most two merge-ready/merged milestones per run—may
254
261
  be relayed under the recorded Notification policy.
255
262
 
256
- Merge-ready opens the merge boundary. Only the chat-run driver holding the
257
- approved ticket map is the merge actor for own PRs inside the approved ticket
258
- map (run-created or explicitly adopted into it) when they target an
259
- `integration` base. Apply `axstack-watch` §5's merge card and
260
- full predicate; an approval alone never grants merge authority. A peer PR or
261
- `deploying` base waits for the user to merge, in either approval mode. A
262
- manager, worker, reviewer, automation, or standalone watch must never merge.
263
+ Merge-ready opens the merge boundary.
264
+ For own PRs, automatic merge is the default under the
265
+ [watch predicate](../axstack-watch/SKILL.md#5-state-readiness-precisely).
266
+ The merge actor is the recorded owning watch thread (`axstack-owner` for
267
+ standalone authorized maintenance), including small and adopted work.
268
+ Missing or idle ownership follows lifecycle reconciliation and explicit transfer first.
269
+ Apply `axstack-watch` §5's merge card and full predicate; an approval alone
270
+ never grants merge authority.
271
+ A peer PR or `deploying` base waits for the user to merge, in either approval mode.
272
+ User merges are bottom-up for a stack.
273
+ A manager, worker, reviewer, monitor, or nightly triage must never merge.
274
+ Observation-only and peer watches never merge.
275
+ Watch §5 owns provider provenance, approval carryover, eligible bases, every
276
+ planned stack member's publication, exclusions, and card-reply exceptions.
277
+ This policy grants no release, npm publish, or host install authority.
263
278
  Re-read every predicate term under watch §5 before merging. Confirm merge
264
279
  commits are allowed, `delete_branch_on_merge` is false, and the base has no
265
280
  merge queue; otherwise hold for the user. For a singleton, use