axstack 0.20.31 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +25 -23
  2. package/bin/axstack.js +17 -5
  3. package/docs/installation.md +104 -51
  4. package/docs/workflows.md +176 -131
  5. package/package.json +3 -3
  6. package/profiles/presets/claude-only.json +23 -23
  7. package/profiles/presets/codex-only.json +10 -10
  8. package/profiles/presets/mixed.json +24 -24
  9. package/skills/axstack/references/automations.md +136 -137
  10. package/skills/axstack/references/autopilot.md +30 -17
  11. package/skills/axstack/references/candidate-publication.md +13 -8
  12. package/skills/axstack/references/contracts.md +13 -12
  13. package/skills/axstack/references/design-lens.md +3 -3
  14. package/skills/axstack/references/diligence.md +3 -1
  15. package/skills/axstack/references/evidence-archive.md +38 -33
  16. package/skills/axstack/references/lifecycle.md +64 -50
  17. package/skills/axstack/references/review-manager-prompt.md +13 -11
  18. package/skills/axstack/references/role-roster.md +12 -2
  19. package/skills/axstack/references/routing.md +33 -25
  20. package/skills/axstack/references/run-record.md +35 -16
  21. package/skills/axstack/references/t3-runtime.md +237 -0
  22. package/skills/axstack/references/test-audit-weekly.md +62 -0
  23. package/skills/axstack/references/test-value.md +120 -0
  24. package/skills/axstack/references/ui-verification.md +5 -1
  25. package/skills/axstack/references/workspace-hygiene.md +102 -156
  26. package/skills/axstack/scripts/pr-digest.js +120 -0
  27. package/skills/axstack/scripts/resolve-models.js +102 -38
  28. package/skills/axstack-align/SKILL.md +19 -56
  29. package/skills/axstack-audit/SKILL.md +12 -3
  30. package/skills/axstack-audit/references/record.md +1 -1
  31. package/skills/axstack-brainstorm/SKILL.md +24 -0
  32. package/skills/axstack-brainstorm/references/arena.md +56 -0
  33. package/skills/axstack-cleanup/SKILL.md +69 -87
  34. package/skills/axstack-debug/SKILL.md +1 -1
  35. package/skills/axstack-explain/SKILL.md +1 -1
  36. package/skills/axstack-explain/references/visual-qa.md +2 -0
  37. package/skills/axstack-implement/SKILL.md +56 -20
  38. package/skills/axstack-improve/SKILL.md +24 -4
  39. package/skills/axstack-relay/SKILL.md +8 -6
  40. package/skills/axstack-research/SKILL.md +11 -4
  41. package/skills/axstack-review/SKILL.md +34 -30
  42. package/skills/axstack-spec/SKILL.md +18 -13
  43. package/skills/axstack-tickets/SKILL.md +7 -8
  44. package/skills/axstack-watch/SKILL.md +97 -27
  45. package/skills/axstack-watch/references/watch-runtime.md +51 -66
  46. package/src/capabilities.js +33 -69
  47. package/src/installer.js +1 -1
  48. package/src/instructions.js +9 -4
  49. package/skills/axstack/references/orca-runtime.md +0 -202
  50. package/skills/axstack/scripts/trust-path.js +0 -123
@@ -1,202 +0,0 @@
1
- # Orca runtime boundary
2
-
3
- Read this immediately before using Orca for a role dispatch, handoff, delivery,
4
- settlement, or recovery. Ordinary local reading and writing do not load it.
5
- Axstack owns policy, role selection, and evidence; Orca owns Run, Task,
6
- Dispatch, session, worktree, messaging, settlement, and scheduling state.
7
-
8
- ## Discover the runtime-owned guides
9
-
10
- Resolve one Orca executable for the session and reuse it. Prefer
11
- `ORCA_CLI_COMMAND` when set, then the checkout's `orca-dev` when
12
- `ORCA_DEV_REPO_ROOT` is set, the Linux-safe `orca-ide` outside managed
13
- terminals, and otherwise `orca`. If the selected executable fails, report that
14
- exact gap; never switch binaries silently.
15
-
16
- Load only the selected executable's version-matched guides needed by the
17
- operation through `skills get orchestration --json`,
18
- `skills get orca-cli --json`, and `skills get orca-linear --json`.
19
- `orchestration` owns Run, Task,
20
- Dispatch, messaging, supervision,
21
- settlement, and recovery. `orca-cli` owns worktrees, terminals, automations,
22
- handoffs, and artifact publication; load its named conditional reference at
23
- the matching action gate. `orca-linear` owns Linear issue reads and writes.
24
- Follow returned schemas and current command help rather than copying their
25
- procedures into Axstack. Guide discovery does not prove runtime support for a
26
- particular operation: preflight that operation and report an advertised gap.
27
- Missing discovery never authorizes legacy runtime use, a silent integration or
28
- store fallback, or an Axstack dispatcher, daemon, scheduler, database, or
29
- escalation engine.
30
-
31
- Orca artifacts publish public-by-link output. They are not private evidence
32
- storage and must never receive private evidence by default; sharing requires
33
- explicit publication authority and the `orca-cli` publishing reference.
34
-
35
- ## Bind the configured role
36
-
37
- Read `roles.json` from the installed shared root `skills/axstack/`. The installed
38
- shape is `{ "version": 1, "preset": "<name>", "roles": [...] }`. Bundled
39
- profiles are setup inputs shaped as
40
- `{ "version": 1, "roles": [...] }`. A new run records the selected preset and
41
- all 32 role rows once. For each role record class, resolved exact ID, source,
42
- and time. An active run keeps the exact snapshot; resume reuses it without
43
- re-resolution until the user explicitly changes it.
44
-
45
- Select the requested role by stable ID. A missing class and missing or null
46
- model holds only that role; never launch a provider default. Resolve Codex
47
- classes with `scripts/resolve-models.js`, passing the catalog path explicitly;
48
- missing or malformed catalogs hold. The first launch of each Claude class uses
49
- its alias. Read the exact ID from the first assistant turn's `message.model` in
50
- that worker's own session transcript at
51
- `~/.claude/projects/<worktree-path-slug>/*.jsonl`; the worktree path slug
52
- replaces each non-alphanumeric character with `-`. Identify the file by the
53
- worker's session ID, or use the newest file created after launch. Later launches
54
- of that class use the recorded exact ID. Before read-back record `alias,
55
- unresolved`; record an unknown read-back as unknown and hold
56
- provenance-dependent work. A worker self-report is a labeled last
57
- resort. Launch-by-agent-id routes for which Orca exposes no
58
- `--model` override (today: `grok`, `antigravity`) record `model: null` with an explicit note and are
59
- launchable; the run record snapshots the model the TUI reports. Validate provider, model, and effort
60
- against the guide and actual launch capability. Stored `modeId` and other
61
- permission fields are conservative intent, not proof of effective permission
62
- parity or a security boundary. Requested settings, input acceptance, effective
63
- settings, and completed work are separate evidence. An unsupported or
64
- unavailable value holds affected work for the user's decision except the narrow
65
- retry below.
66
- The single-provider preset's null adviser and round-2 seat are intentional installation data, not
67
- readiness failure; because Align and Spec require both adviser receipts, either
68
- null adviser still holds those phases. The current chat is the driver and has
69
- no role row in any preset.
70
-
71
- Only explicit model rejection before the first turn permits a Codex
72
- `--retry-of` with the next eligible ID in the same class, provider, and effort.
73
- Fence the rejected Dispatch and record tried ID, error, and fallback ID in the
74
- snapshot and reply. Timeout, quota, auth, and other failures hold; Claude
75
- rejection holds. Apply this to every role, including advisers and judges.
76
-
77
- ## Materialize checkouts as worktrees of the registered repo
78
-
79
- Every reviewer, release, or worker checkout is `ORCA worktree create --repo
80
- id:<repoId> ...` under the repo Orca already registers. `ORCA repo add` is a
81
- one-time import of a new repository; running it on a clone of a registered
82
- repo creates a second top-level repo record, so it never materializes a
83
- checkout. See [Candidate publication](candidate-publication.md) for the
84
- detached immutable review checkout.
85
-
86
- ## Supervise one authoritative attempt
87
-
88
- For supervised work, use the orchestration guide's native Run, Task, and
89
- Dispatch flow. Reconcile existing attempts first. Bind the approved spec or
90
- small-change intent, brief, authority, role snapshot, worktree, base, and
91
- candidate to the Task; preserve the returned
92
- Task, Dispatch, terminal, agent, and worktree identities. Exactly one Dispatch
93
- may write a candidate at a time.
94
- Put the [Safe deletion](workspace-hygiene.md#safe-deletion) rule in every
95
- worker brief.
96
-
97
- Create a worker worktree with `--parent-worktree` naming the candidate's
98
- worktree when both are in the same repository; see
99
- [Readable sidebar](workspace-hygiene.md#readable-sidebar) for naming, status,
100
- and parentage at dispatch. `--no-parent` is for unrelated work with no parent
101
- context. Where supported, correct wrong lineage in place with
102
- `worktree set --parent-worktree`. Lineage is presentation, never authority: it
103
- grants nothing and cannot replace Task, Dispatch, and receipt evidence.
104
- `--no-parent` is never used for a review or repair checkout.
105
-
106
- Every reviewer gets a separate Orca child worktree parented to the candidate.
107
- Keep that reviewer's probes and private evidence in its separate private
108
- per-Dispatch run folder under [Workspace hygiene](workspace-hygiene.md), with no
109
- first-pass cross-read. Untracked files never prove a worktree disposable.
110
-
111
- Before launching a Claude worker in a checkout, from the installed `axstack` skill directory
112
- run `bun scripts/trust-path.js --path <exact checkout path>` for that
113
- exact checkout path. It trusts only Orca-registered repository roots and their
114
- worktrees. A failed preflight holds launch; workers never answer trust or
115
- permission dialogs. A trust dialog that still appears is a hold.
116
-
117
- An `input_accepted` stage proves only that input reached the terminal. Require
118
- `turn_started` plus runtime/session inspection before treating the agent as
119
- started, and verify the requested role independently before trusting its work.
120
- If a worker asks to confirm its own dispatch brief, the dispatching owner
121
- confirms once by typed terminal input restating the brief's authority, then
122
- re-verifies `turn_started`. That confirmation never answers a trust or permission prompt;
123
- it answers only the agent's own model-turn question about its brief, never a
124
- harness or tool dialog, and adds no authority. A second ask is a hold.
125
- A workspace trust, hook review, permission, authentication, or model prompt is
126
- a visible hold. Never answer a trust or permission prompt on the worker's
127
- behalf. A permission prompt or provider safety refusal is a held, incomplete
128
- outcome, never consent or completion. Never bypass or retry it through another
129
- model. Preserve the attempt and its evidence, then use only
130
- the runtime guide's inspection and recovery procedure; reconcile before any
131
- authorized retry so no duplicate writer starts.
132
-
133
- ## Reviewer workspaces and evidence
134
-
135
- Give each reviewer a separate Orca-managed child worktree under the candidate's
136
- worktree, including report-only reviews and rechecks; never share the author's
137
- checkout or another reviewer's checkout. A later review gets a fresh Orca-managed
138
- child worktree after the prior settled review's evidence and cleanup are
139
- reconciled. Use the runtime-owned worktree guide,
140
- not a raw Git worktree or temporary clone. Before dispatch, verify a detached
141
- checkout of the exact candidate SHA and the pinned base in that child.
142
-
143
- Name the private `<run dir>/evidence/<dispatch>/` folder in the brief and
144
- completion receipt. Keep tracked candidate files read-only and peer folders
145
- isolated. Scope `TMPDIR` to that 0700 folder for owned commands where supported.
146
- Before use or temporary-file cleanup, validate that its real path equals or
147
- is inside the recorded run evidence folder, is not a symbolic link, and matches the recorded
148
- Dispatch owner. Worktree-local temporary paths use the same guards against
149
- their recorded worktree and owner. Remove only an exact validated owned
150
- path, with no glob or parent-root deletion; never wipe a general cache.
151
- Uncertain temporary paths are preserved for reconciliation.
152
- Before removing a reviewer worktree, read back its report and supporting
153
- evidence from the private run evidence folder and record their paths. Files
154
- already there need no archive step; the private evidence archive applies only
155
- to legacy in-worktree evidence. Incidental caches are not evidence.
156
- A settled reviewer Dispatch can be
157
- cleaned before PR merge through [axstack-cleanup](../../axstack-cleanup/SKILL.md)
158
- only after its classification, readback, and removal guards pass. Preserve
159
- active or unknown review evidence and unique evidence whose bytes must survive;
160
- uncertain ownership or evidence holds. Terminal release alone is not permission
161
- to discard evidence or remove the worktree.
162
-
163
- ## Consume, settle, and recover
164
-
165
- Process a whole delivery before acknowledgment. Accept `worker_done` only when
166
- its sender, Task, and Dispatch match the expected active attempt; then verify
167
- the candidate revision and evidence before advancing Axstack's derived record.
168
- A valid completion for an older Dispatch never completes a newer Dispatch.
169
- Duplicate messages are deduplicated by their runtime identity.
170
-
171
- On `consumer_fenced`, stop consuming under that identity. Reconcile the active
172
- coordinator and delivery through the runtime guide; never bypass the fence,
173
- forge a sender, borrow a terminal identity, or partially acknowledge the
174
- delivery. Settlement is also runtime-owned: reuse, retain, or release a settled
175
- terminal only through the guide. A genuine `user_takeover` result requires
176
- retention; do not close, release, reuse, or send commands to that terminal as
177
- cleanup. Apply only the recorded
178
- repair Dispatch ID exception in [Workspace hygiene](workspace-hygiene.md).
179
-
180
- Contact loss, silence, idle state, or an absent status never proves exit or
181
- transfers authority. Ordinary restart and resume reconcile the same owner,
182
- author, Task, Dispatch, worktree, revisions, and pending receipts. Authorized
183
- repairs return to the same author when its session and evidence remain usable;
184
- uncertainty holds replacement rather than creating a second writer.
185
-
186
- ## Transfer ownership explicitly
187
-
188
- Distinguish supervised workers from a full ownership handoff. Only the user's
189
- explicit transfer request enters this branch. Record the intended recipient,
190
- exact scope, revisions, authority, and pending request before following the
191
- runtime-owned `orca-cli` handoff procedure.
192
-
193
- Input acceptance or turn start is launch evidence, not ownership. Validate an
194
- explicit recipient acceptance against the intended request, session, scope,
195
- candidate/base, and authority before changing ownership. Until then the current
196
- owner remains accountable. After a valid acceptance, record it, transfer only
197
- the accepted authority, and have the prior owner stop. Ordinary resume keeps
198
- the current owner and never launches a handoff.
199
-
200
- The runtime step is complete only when its real receipts are recorded with
201
- their limitations. Those receipts grant no merge, release, publication, model
202
- substitution, host-configuration, or scope authority.
@@ -1,123 +0,0 @@
1
- #!/usr/bin/env bun
2
- import { chmod, lstat, readFile, rename, unlink, writeFile } from 'node:fs/promises';
3
-
4
- function fail(message) { throw new Error(message); }
5
-
6
- function args(argv) {
7
- const values = {};
8
- for (let i = 0; i < argv.length; i += 2) {
9
- const key = argv[i];
10
- if (!['--path', '--repo-list-file', '--worktree-list-file'].includes(key) || !argv[i + 1] || values[key]) {
11
- fail(`invalid argument: ${key ?? '(end)'}`);
12
- }
13
- values[key] = argv[i + 1];
14
- }
15
- const path = values['--path'];
16
- if (!path || !path.startsWith('/') || path.includes('\0') || path.split('/').some((part) => part === '.' || part === '..') ||
17
- (path !== '/' && (path.endsWith('/') || path.includes('//')))) fail('path must be an exact absolute path');
18
- if (Boolean(values['--repo-list-file']) !== Boolean(values['--worktree-list-file'])) {
19
- fail('both Orca inventory files are required together');
20
- }
21
- return values;
22
- }
23
-
24
- async function inventory(file, command, key) {
25
- let raw;
26
- if (file) raw = await readFile(file, 'utf8');
27
- else {
28
- const result = Bun.spawnSync(['orca', ...command, '--json'], { stdout: 'pipe', stderr: 'pipe' });
29
- if (result.exitCode !== 0) fail(`Orca ${command.join(' ')} failed: ${result.stderr.toString().trim()}`);
30
- raw = result.stdout.toString();
31
- }
32
- const response = JSON.parse(raw);
33
- if (response.ok !== true || !Array.isArray(response.result?.[key])) fail(`invalid Orca ${key} inventory`);
34
- if (response.result.truncated === true) fail(`truncated Orca ${key} inventory`);
35
- return response.result[key];
36
- }
37
-
38
- async function configStat(path) {
39
- const stat = await lstat(path).catch((err) => err?.code === 'ENOENT' ? null : Promise.reject(err));
40
- if (stat?.isSymbolicLink()) fail(`refusing symlinked Claude config: ${path}`);
41
- if (stat && !stat.isFile()) fail(`Claude config is not a regular file: ${path}`);
42
- return stat;
43
- }
44
-
45
- async function snapshot(path) {
46
- const stat = await configStat(path);
47
- return { stat, raw: stat ? await readFile(path, 'utf8') : null };
48
- }
49
-
50
- async function withLock(path, action) {
51
- // The lock serializes this helper's writers; byte checks also catch other writers.
52
- const lock = `${path}.axstack-lock`;
53
- for (let attempt = 0; attempt < 100; attempt += 1) {
54
- try {
55
- await writeFile(lock, `${process.pid}\n`, { flag: 'wx', mode: 0o600 });
56
- try { return await action(); }
57
- finally { await unlink(lock); }
58
- } catch (err) {
59
- if (err?.code !== 'EEXIST') throw err;
60
- await Bun.sleep(5 + Math.floor(Math.random() * 10));
61
- }
62
- }
63
- fail('Claude config is busy; trust preflight held');
64
- }
65
-
66
- async function trust(configPath, path) {
67
- for (let attempt = 0; attempt < 5; attempt += 1) {
68
- const { stat, raw } = await snapshot(configPath);
69
- const current = raw === null ? {} : JSON.parse(raw);
70
- if (!current || typeof current !== 'object' || Array.isArray(current) ||
71
- (current.projects !== undefined && (!current.projects || typeof current.projects !== 'object' || Array.isArray(current.projects)))) {
72
- fail('invalid Claude config shape');
73
- }
74
- if (current.projects?.[path]?.hasTrustDialogAccepted === true) {
75
- console.log(JSON.stringify({ status: 'already-trusted', path }));
76
- return;
77
- }
78
- current.projects ??= {};
79
- if (current.projects[path] !== undefined && (!current.projects[path] || typeof current.projects[path] !== 'object' || Array.isArray(current.projects[path]))) {
80
- fail('invalid Claude project entry');
81
- }
82
- current.projects[path] ??= {};
83
- current.projects[path].hasTrustDialogAccepted = true;
84
-
85
- const temp = `${configPath}.${crypto.randomUUID()}.tmp`;
86
- try {
87
- await writeFile(temp, `${JSON.stringify(current, null, 2)}\n`, { flag: 'wx', mode: stat ? stat.mode & 0o777 : 0o600 });
88
- if (stat) await chmod(temp, stat.mode & 0o777);
89
- if ((await snapshot(configPath)).raw !== raw) {
90
- await Bun.sleep(5 + Math.floor(Math.random() * 10));
91
- continue;
92
- }
93
- await rename(temp, configPath);
94
- const after = await snapshot(configPath);
95
- if (JSON.parse(after.raw).projects?.[path]?.hasTrustDialogAccepted === true) {
96
- console.log(JSON.stringify({ status: 'trusted', path }));
97
- return;
98
- }
99
- } finally {
100
- await unlink(temp).catch((err) => { if (err?.code !== 'ENOENT') throw err; });
101
- }
102
- await Bun.sleep(5 + Math.floor(Math.random() * 10));
103
- }
104
- fail('Claude config changed during trust preflight');
105
- }
106
-
107
- async function main() {
108
- const options = args(process.argv.slice(2));
109
- const path = options['--path'];
110
- const repos = await inventory(options['--repo-list-file'], ['repo', 'list'], 'repos');
111
- const worktrees = await inventory(options['--worktree-list-file'], ['worktree', 'list'], 'worktrees');
112
- const repoIds = new Set(repos.filter((repo) => repo.kind === 'git').map((repo) => repo.id));
113
- const registered = repos.some((repo) => repo.kind === 'git' && repo.path === path) ||
114
- worktrees.some((worktree) => repoIds.has(worktree.repoId) && worktree.hostId === 'local' && worktree.path === path);
115
- if (!registered) fail(`path is not an Orca-registered repository or worktree: ${path}`);
116
-
117
- const home = process.env.HOME;
118
- if (!home?.startsWith('/')) fail('HOME must be absolute');
119
- const configPath = `${home.replace(/\/$/, '')}/.claude.json`;
120
- await withLock(configPath, () => trust(configPath, path));
121
- }
122
-
123
- main().catch((err) => { console.error(err.message); process.exitCode = 1; });