axstack 0.34.2 → 0.34.4
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/docs/getting-started.md +4 -2
- package/docs/host-operations.md +3 -4
- package/docs/installation.md +2 -0
- package/docs/workflows.md +8 -3
- package/package.json +3 -3
- package/skills/axstack/references/automations.md +7 -4
- package/skills/axstack/references/autopilot.md +1 -1
- package/skills/axstack/references/run-record.md +2 -1
- package/skills/axstack/references/t3-runtime.md +18 -4
- package/skills/axstack/references/ui-verification.md +8 -12
- package/skills/axstack/references/workspace-hygiene.md +11 -0
- package/skills/axstack/scripts/dispatch-plan.js +25 -10
- package/skills/axstack/scripts/readiness.js +29 -2
- package/skills/axstack/scripts/test-repository.js +30 -0
- package/skills/axstack-diagram/SKILL.md +2 -1
- package/skills/axstack-explain/SKILL.md +3 -3
- package/skills/axstack-explain/references/inline-pages.md +1 -3
- package/skills/axstack-relay/SKILL.md +1 -0
- package/skills/axstack-review/SKILL.md +1 -0
- package/skills/axstack-watch/SKILL.md +6 -1
- package/skills/axstack-watch/references/watch-runtime.md +7 -6
package/docs/getting-started.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Getting started
|
|
2
2
|
|
|
3
|
+
Linux is the only supported host OS.
|
|
4
|
+
|
|
3
5
|
Install Axstack, check your host, then ask for one bounded task in T3 Code.
|
|
4
6
|
For the mental model, read [concepts](concepts.md); for other journeys, use
|
|
5
7
|
[guides](guides.md).
|
|
@@ -24,8 +26,8 @@ axstack check --harness codex
|
|
|
24
26
|
```
|
|
25
27
|
|
|
26
28
|
Installation writes owned skills and instructions, preserving unrelated content,
|
|
27
|
-
and fetches the pinned archify tool for explicit viewer requests. Reload the
|
|
28
|
-
installation. Use the [installation reference](installation.md) for other
|
|
29
|
+
and fetches the pinned archify tool for explicit viewer requests. Reload the
|
|
30
|
+
harness's skills in T3 after installation. Use the [installation reference](installation.md) for other
|
|
29
31
|
harnesses, source installs or conflicts.
|
|
30
32
|
|
|
31
33
|
A successful check exits 0. Its five capability rows mean:
|
package/docs/host-operations.md
CHANGED
|
@@ -134,10 +134,9 @@ messages under the accepted fleet risk.
|
|
|
134
134
|
|
|
135
135
|
## Chat-run watch activation
|
|
136
136
|
|
|
137
|
-
A bound T3 schedule
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
member, or failed re-arming restore five minutes. Human-only waits use 60 minutes
|
|
137
|
+
A bound T3 schedule wakes the driver thread on a normal 30-minute cadence.
|
|
138
|
+
Unavailable or unarmed native watches for any open member, failed re-arming,
|
|
139
|
+
or a resumed question run restore five minutes. Human-only waits use 60 minutes
|
|
141
140
|
under [Chat-run watch runtime](../skills/axstack-watch/references/watch-runtime.md#chat-run-watch).
|
|
142
141
|
A T3 "stopped watching" notice triggers a PR re-check and native re-arm in that same turn.
|
|
143
142
|
The run record holds the schedule ID and driver thread.
|
package/docs/installation.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Installation
|
|
2
2
|
|
|
3
|
+
Linux is the only supported host OS.
|
|
4
|
+
|
|
3
5
|
Axstack's Bun CLI installs owned chat skills plus one selected role snapshot and
|
|
4
6
|
checks host capabilities. T3 Code is the only supported active runtime. The CLI
|
|
5
7
|
does not dispatch agents, edit T3 settings, run a scheduler, or maintain a
|
package/docs/workflows.md
CHANGED
|
@@ -134,6 +134,7 @@ Antigravity and Grok routes.
|
|
|
134
134
|
The mixed `axstack-auditor` uses Haiku 5.5 xhigh, pinned to `claude-haiku-5-5`;
|
|
135
135
|
missing that ID or xhigh effort holds without substitution. The mixed
|
|
136
136
|
`axstack-explainer-review` uses Sol medium; `axstack-explainer` stays Sonnet high.
|
|
137
|
+
In `claude-only`, `axstack-auditor` uses the Claude Sonnet class at high effort.
|
|
137
138
|
The new `-sol` auditor, research-code, and explore-execution seats use Sol high
|
|
138
139
|
in `mixed` and `codex-only`; `claude-only` records each as intentionally absent.
|
|
139
140
|
Dispatch the base and Sol seats independently on the same brief, then reconcile
|
|
@@ -150,8 +151,7 @@ later installation changes without re-resolution.
|
|
|
150
151
|
|
|
151
152
|
Peer roles use the stable IDs `axstack-reviewer-primary` and
|
|
152
153
|
`axstack-reviewer-peer`; their provider/class mappings come only from the
|
|
153
|
-
selected preset. The mixed
|
|
154
|
-
Opus medium. The mixed peer coordinator and review-lane binding
|
|
154
|
+
selected preset and the ordered reviewer table above. The mixed peer coordinator and review-lane binding
|
|
155
155
|
`axstack-owner` uses Sol high and never reviews. `axstack-reviewer-secondary`
|
|
156
156
|
is used in the authored mapping and, alongside `axstack-reviewer-primary`,
|
|
157
157
|
in codebase findings mode.
|
|
@@ -259,7 +259,12 @@ for explicit ownership transfer.
|
|
|
259
259
|
archive the exact eligible thread, then remove its exact worktree without
|
|
260
260
|
force and delete only eligible local branches. T3 metadata actions do not
|
|
261
261
|
remove worktrees. Accepted writer or delegated completion settles thread
|
|
262
|
-
metadata only
|
|
262
|
+
metadata only after receipt acceptance, which is distinct from T3 sidebar
|
|
263
|
+
settlement. Every writer follow-up, including rebase, base update, conflict,
|
|
264
|
+
body and receipt changes, follows same-turn settlement and readback under
|
|
265
|
+
[Settlement](../skills/axstack/references/workspace-hygiene.md#settlement).
|
|
266
|
+
Fresh native run inventory gates zero-unsettled and cadence claims; incomplete
|
|
267
|
+
inventory is UNKNOWN. Author threads and worktrees remain retained and unarchived
|
|
263
268
|
until their PR merges or closes; the current pass, unsettled descendants,
|
|
264
269
|
and user-taken-over threads remain protected.
|
|
265
270
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "axstack",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.4",
|
|
4
4
|
"description": "Axstack installer and setup CLI: installs owned chat skills and role data, configures supported harness settings, and checks T3 Code capabilities.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"scripts": {
|
|
35
35
|
"lint": "biome lint . --error-on-warnings",
|
|
36
36
|
"typecheck": "bun node_modules/typescript/bin/tsc --noEmit --project jsconfig.json",
|
|
37
|
-
"test": "bun test",
|
|
38
|
-
"test:all": "bun test"
|
|
37
|
+
"test": "bun skills/axstack/scripts/test-repository.js",
|
|
38
|
+
"test:all": "bun skills/axstack/scripts/test-repository.js"
|
|
39
39
|
},
|
|
40
40
|
"license": "MIT",
|
|
41
41
|
"devDependencies": {
|
|
@@ -71,7 +71,7 @@ Missing ordering or ownership evidence holds admission and never guesses a winne
|
|
|
71
71
|
|
|
72
72
|
Once identified as a duplicate, the new pass does no PR work, makes no further
|
|
73
73
|
shared-record write and touches no PR-job thread or descendant owned by the
|
|
74
|
-
live manager.
|
|
74
|
+
live manager. Besides its private pass note and authorized notification, a duplicate's only shared mutation is pass-start settlement of eligible
|
|
75
75
|
terminal lane pass threads under [Finite-session teardown](#finite-session-teardown).
|
|
76
76
|
A duplicate pass admits nothing and runs read-only discovery
|
|
77
77
|
into its own pass note in its private evidence folder, recording new eligible
|
|
@@ -330,13 +330,16 @@ decision interpreter; the driver maps card replies in its prose checks.
|
|
|
330
330
|
|
|
331
331
|
## Finite-session teardown
|
|
332
332
|
|
|
333
|
+
Decisions outliving a finite manager pass retain their receipt and hold in durable continuity, with a GitHub user action route or explicit ownership transfer.
|
|
334
|
+
Use the T3 action route for such decisions; a reply to a closed pass never clears a hold, and a successor reissues a card only after reconciling the retained receipt and current authority.
|
|
335
|
+
|
|
333
336
|
After lane reconciliation at pass start, every pass, including a duplicate,
|
|
334
337
|
uses `t3_thread_organize` to settle finished predecessor and duplicate lane pass
|
|
335
338
|
threads as metadata only, before discovery or admission.
|
|
336
339
|
Settle another lane pass thread only with terminal run evidence, no unsettled
|
|
337
|
-
descendants,
|
|
340
|
+
descendants, zero open holds naming it, recorded or directly observed, no user takeover, and exclusion of
|
|
338
341
|
the live owner and current pass.
|
|
339
|
-
|
|
342
|
+
Keep held passes, wedged passes and stalled owners unsettled and visible.
|
|
340
343
|
Settlement is separate from owner-only worktree removal, branch deletion and
|
|
341
344
|
continuity writes.
|
|
342
345
|
|
|
@@ -352,7 +355,7 @@ Then run the driver-start orphan sweep under Workspace hygiene; the sweep is
|
|
|
352
355
|
silent when nothing was removed. Record sweep results and holds in continuity's
|
|
353
356
|
Open holds table.
|
|
354
357
|
The orphan sweep covers the run record's repositories plus registered repositories on this host.
|
|
355
|
-
Retirement settles remaining duplicate threads with `t3_thread_organize`
|
|
358
|
+
Retirement settles remaining predecessor, duplicate and failed-successor pass threads with `t3_thread_organize`
|
|
356
359
|
(settle/archive changes metadata only) before separate guarded Git worktree removal.
|
|
357
360
|
Unknown, active or user-taken-over threads,
|
|
358
361
|
ambiguous publication and failed salvage stay preserved.
|
|
@@ -89,7 +89,7 @@ Never require a manual `axstack-watch` invocation.
|
|
|
89
89
|
The driver remains the single owner and sole run-record writer.
|
|
90
90
|
Never create a per-PR session or an ownership hand-off.
|
|
91
91
|
Read the [T3 runtime boundary](t3-runtime.md) and use its bound
|
|
92
|
-
`schedule_task` wake (`everyMs:
|
|
92
|
+
`schedule_task` wake (`everyMs:1800000`), recording the scheduledTaskId.
|
|
93
93
|
Follow [Native PR links and watches](t3-runtime.md#native-pr-links-and-watches)
|
|
94
94
|
alongside that bound schedule.
|
|
95
95
|
Apply [Chat-run watch runtime](../../axstack-watch/references/watch-runtime.md#chat-run-watch)
|
|
@@ -136,7 +136,8 @@ Record the reason for each driver-elected repair in `Decisions`.
|
|
|
136
136
|
|
|
137
137
|
Record concise IDs, SHAs, URLs, status, timestamps, next actions, and evidence
|
|
138
138
|
references. Private records include the checkout, evidence and worktree paths
|
|
139
|
-
that the schema requires. Include no
|
|
139
|
+
that the schema requires. Include no other machine-specific paths in private records.
|
|
140
|
+
Include no tokens, transcripts, full worker output,
|
|
140
141
|
credentials or private prompts. Publication of a sanitized summary needs separate
|
|
141
142
|
authority.
|
|
142
143
|
|
|
@@ -238,10 +238,24 @@ the failed attempt's branch is kept until salvage. Unknown liveness holds
|
|
|
238
238
|
replacement; reconcile the old writer before admitting another.
|
|
239
239
|
|
|
240
240
|
With an unsettled launched thread, the driver turn must end only while a bound
|
|
241
|
-
`schedule_task` with `bindToCurrentThread:true
|
|
242
|
-
|
|
241
|
+
`schedule_task` with `bindToCurrentThread:true` is armed at the default
|
|
242
|
+
`everyMs:1800000` or for its 5-minute recovery cases in
|
|
243
|
+
[Chat-run watch runtime](../../axstack-watch/references/watch-runtime.md#chat-run-watch),
|
|
244
|
+
with its ID recorded. Each wake must reconcile all unsettled runs, including a
|
|
243
245
|
writer that died without sending; failed runs hold incomplete work. The watch
|
|
244
246
|
inherits the driver model/workspace and adds no runtime of Axstack's own.
|
|
247
|
+
T3 queues a scheduled wake even while the driver is busy, so copies pile up.
|
|
248
|
+
After a provider error, server restart or Stop, T3 holds the queue: held
|
|
249
|
+
messages do not start, and later queued messages are held too.
|
|
250
|
+
At the start of each run-watch wake, the driver lists every queued message with
|
|
251
|
+
`t3_queue_list` and treats it as stranded.
|
|
252
|
+
The driver must cancel every queued copy of its own run-watch prompt.
|
|
253
|
+
One wake reconciles all those copies.
|
|
254
|
+
For each stranded worker receipt or PR-watch update, the driver must read it
|
|
255
|
+
with `t3_queue_read`, act on it in that wake, then cancel it with `t3_queue_cancel`.
|
|
256
|
+
A queued user message is a pending local action, so the driver must keep every
|
|
257
|
+
queued user message and report it in its reply even on an otherwise unchanged
|
|
258
|
+
wake, because only the user resumes a held queue.
|
|
245
259
|
|
|
246
260
|
Once nothing remains unsettled the driver must `delete_scheduled_task` for the
|
|
247
261
|
run watch and use `list_scheduled_tasks` to read back its absence; an uncertain
|
|
@@ -286,10 +300,10 @@ If re-arming fails, restore the bound 5-minute schedule.
|
|
|
286
300
|
When the run waits only on a user decision or a human-only step, including a
|
|
287
301
|
user merge, with no unsettled worker and no PR needing watch events, change
|
|
288
302
|
the run watch cadence to 60 minutes at once.
|
|
289
|
-
When work restarts, restore the normal
|
|
303
|
+
When work restarts, restore the normal 30-minute cadence.
|
|
290
304
|
Keep native PR watches.
|
|
291
305
|
For chat-run cadence changes, follow [Chat-run watch runtime](../../axstack-watch/references/watch-runtime.md#chat-run-watch)
|
|
292
|
-
for 30-minute
|
|
306
|
+
for the normal 30-minute cadence, 5-minute recovery, and schedule update read-back.
|
|
293
307
|
The schedule still reconciles author and review tasks, readiness, and release.
|
|
294
308
|
When a PR merges or closes, or its watch is torn down, call `unwatch_pull_request`
|
|
295
309
|
and keep its link.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# UI verification
|
|
2
2
|
|
|
3
|
-
Every Playwright, browser, or rendered-UI check outside the three named
|
|
3
|
+
Every Playwright, browser, or rendered-UI check outside the three named browser
|
|
4
4
|
exceptions, including a "confirm it in the browser" step, goes through async
|
|
5
5
|
`delegate_task` to `axstack-ui-verifier` from the 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.
|
|
@@ -8,21 +8,16 @@ The PR writer remains the sole writer.
|
|
|
8
8
|
|
|
9
9
|
Before using a PR preview URL, the UI verifier must read [PR previews](preview.md).
|
|
10
10
|
|
|
11
|
-
The first named
|
|
11
|
+
The first named browser exception is archify `finalize` as a headless build gate.
|
|
12
12
|
Keep finalize outputs only in the private evidence folder.
|
|
13
13
|
Never replace the verifier's rendered pass with finalize.
|
|
14
14
|
|
|
15
|
-
The second named
|
|
15
|
+
The second named browser exception is the driver's two `html_preview`
|
|
16
16
|
runs at 728px dark and 360px light.
|
|
17
|
-
Scan the exact bytes of every page for remote src, srcset, and href on loaded
|
|
18
|
-
resources, `@import`, `url()`, `fetch`, XHR, WebSocket, EventSource, and meta refresh.
|
|
19
|
-
Reject scan matches except local url(#id) references such as SVG markers and gradients.
|
|
20
|
-
Require correct layout, theme, zero console errors, empty `missingImages`,
|
|
21
|
-
height, network, and word count.
|
|
22
17
|
Never replace the verifier's interaction pass with `html_preview`.
|
|
23
18
|
Follow [Inline pages](../../axstack-explain/references/inline-pages.md) for the page checks.
|
|
24
19
|
|
|
25
|
-
The third named
|
|
20
|
+
The third named browser exception permits dispatched roles to use
|
|
26
21
|
`html_preview` as a non-publishing self-check.
|
|
27
22
|
Dispatched-role self-checks never replace the driver's two previews or the `axstack-ui-verifier` pass.
|
|
28
23
|
Dispatched roles never call `html_render`.
|
|
@@ -36,8 +31,8 @@ Candidate browser and visual checks must run in the delegated `axstack-ui-verifi
|
|
|
36
31
|
For every interactive page, require a real-browser `axstack-ui-verifier` interaction pass.
|
|
37
32
|
Give the evidence path and SHA-256 of the exact bytes in the verifier brief.
|
|
38
33
|
The verifier serves the exact bytes on loopback.
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
The verifier opens the page with `preview_open` using `open:false`.
|
|
35
|
+
The verifier checks clicks, keyboard, focus order, screen-reader names, expanded states, and reduced motion.
|
|
41
36
|
Require that `performance.getEntriesByType('resource')` is empty.
|
|
42
37
|
The detached-checkout rule does not apply to a page without a candidate.
|
|
43
38
|
|
|
@@ -57,7 +52,8 @@ Keep browser recipes tool-neutral for the verifier.
|
|
|
57
52
|
|
|
58
53
|
## Proof standards
|
|
59
54
|
|
|
60
|
-
Apply these standards
|
|
55
|
+
Apply these standards wherever referenced, including the verifier's candidate checks
|
|
56
|
+
and inline-page interaction pass.
|
|
61
57
|
|
|
62
58
|
Drive the real user path.
|
|
63
59
|
Capture the action, the resulting state and its side effects.
|
|
@@ -44,6 +44,15 @@ On forge-confirmed merge or closure, follow [Native PR links and watches](t3-run
|
|
|
44
44
|
for same-turn author settlement and its required readback.
|
|
45
45
|
A repair turn automatically un-settles the thread, making it visible while working.
|
|
46
46
|
The driver settles the thread again after the next accepted repair completion.
|
|
47
|
+
Every writer follow-up, including rebase, base update, conflict, body and receipt changes, counts as repair for same-turn settlement and readback.
|
|
48
|
+
Immediately before settlement require native state proving the accepted run is current and the latest overall run.
|
|
49
|
+
Before settlement verify zero active, pending or queued work and zero unsettled descendants.
|
|
50
|
+
After settlement verify exact thread/run identity, current activity and protection state; a mismatch or missing readback holds only that dispatch's next advancement.
|
|
51
|
+
These checks are best effort, not atomic; never issue a compensating unsettle.
|
|
52
|
+
Successful receipt acceptance is distinct from T3 sidebar settlement metadata.
|
|
53
|
+
Cancellation disposition is separate from successful acceptance and requires native terminal cancellation, exact attempt identity, a driver reason and preservation pointers.
|
|
54
|
+
Cancellation disposition requires zero live or queued work, zero unsettled descendants, zero user takeover, zero unanswered questions, zero QUESTION or FAILED markers and zero serious-risk holds.
|
|
55
|
+
Never cancel solely to make a thread eligible for settlement.
|
|
47
56
|
Threads with unaccepted completion, FAILED or QUESTION markers, held, failed or interrupted runs, or anything needing the user stay unsettled and visible.
|
|
48
57
|
Retain a user-taken-over T3 thread and never send cleanup commands to it, including `t3_thread_organize` settle or archive.
|
|
49
58
|
Never remove the current driver, current pass, an active or unknown thread, an unsettled descendant, or a resource with ambiguous ownership.
|
|
@@ -52,6 +61,8 @@ At final settlement include run-owned worktrees in other repositories of the
|
|
|
52
61
|
same project and report each remaining resource as a hold with its reason. Recorded
|
|
53
62
|
projectId, threadId/runId, delegated taskId/childThreadId/childRunId, attempt key,
|
|
54
63
|
checkout path and revision decide ownership. Idle alone never proves exit.
|
|
64
|
+
Before any zero-unsettled claim, cadence relaxation, handback or Close-out, read a fresh fully paginated native inventory of run-owned writers, delegated children and known orphans, including already-settled threads with unconsumed results.
|
|
65
|
+
Incomplete inventory or unknown ownership records UNKNOWN and holds only the affected claim or transition.
|
|
55
66
|
|
|
56
67
|
Read back the durable receipt and evidence manifest before removing source copies or the worktree; missing or differing readback holds removal.
|
|
57
68
|
Evidence already outside the checkout needs no copy; read back its receipt and
|
|
@@ -12,14 +12,16 @@ Example: bun dispatch-plan.js --role axstack-author --roles roles.json --capabil
|
|
|
12
12
|
--capabilities Saved orchestrator_capabilities JSON; reuse the run's saved snapshot
|
|
13
13
|
--picker Saved picker JSON; uses chosenInstanceId
|
|
14
14
|
--kind task emits target; launch emits modelSelection
|
|
15
|
-
--verify Compare t3_thread_configuration JSON; print MATCH or each mismatch
|
|
16
|
-
--out
|
|
15
|
+
--verify Compare t3_thread_configuration JSON; print evidence then MATCH or each mismatch
|
|
16
|
+
--out Save the payload as full JSON here; stdout is an input/path/omitted-count summary
|
|
17
17
|
--help Show all flags and exit codes
|
|
18
18
|
|
|
19
19
|
Read-only inputs: reads supplied JSON, spawns adjacent resolve-models.js, writes stdout/stderr.
|
|
20
20
|
Writes only the caller's --out path when supplied; no retained state.
|
|
21
21
|
Results name input paths. Plan output over 4096 bytes requires --out.
|
|
22
22
|
Large verification retains its exit code, prints mismatches and advises --out on stderr.
|
|
23
|
+
An unwritable --out still prints verification mismatches and retains exit 2.
|
|
24
|
+
An omitted provider label is unknown; exact instance/model/options/mode checks still apply.
|
|
23
25
|
Never dispatches or changes snapshots. Reuse recorded exact model pins as given.
|
|
24
26
|
Exit codes: 0 ok, 1 error, 2 hold (including incomplete read-back).
|
|
25
27
|
`;
|
|
@@ -76,7 +78,10 @@ function verify(configuration, instanceId, provider, model, options) {
|
|
|
76
78
|
compare('options', options, selection?.options,
|
|
77
79
|
normalizedOptions(options) === normalizedOptions(selection?.options));
|
|
78
80
|
compare('runtimeMode', 'full-access', configuration?.runtimeMode);
|
|
79
|
-
return mismatches
|
|
81
|
+
return { mismatches, ...(selection?.provider == null ? {
|
|
82
|
+
providerEvidence: `provider: unknown; expected ${JSON.stringify(provider)}; observed missing; `
|
|
83
|
+
+ 'provider binding checked via instanceId and saved capabilities',
|
|
84
|
+
} : {}) };
|
|
80
85
|
}
|
|
81
86
|
|
|
82
87
|
function plan(argv, io) {
|
|
@@ -89,17 +94,24 @@ function plan(argv, io) {
|
|
|
89
94
|
const emit = (result) => {
|
|
90
95
|
const full = { inputs, ...result };
|
|
91
96
|
const inline = result.mismatches
|
|
92
|
-
? `${JSON.stringify({ inputs })
|
|
97
|
+
? `${[JSON.stringify({ inputs }), result.providerEvidence, result.mismatches.join('\n') || 'MATCH'].filter(Boolean).join('\n')}\n`
|
|
98
|
+
: `${JSON.stringify(full)}\n`;
|
|
93
99
|
if (!args['--out']) {
|
|
94
100
|
if (new TextEncoder().encode(inline).length > 4096) {
|
|
95
101
|
if (!result.mismatches) throw new Error('large output; pass --out <report.json> to save full JSON');
|
|
96
|
-
io.stderr('Large verification output; pass --out <path>.json for
|
|
102
|
+
io.stderr('Large verification output; pass --out <path>.json for a saved JSON copy\n');
|
|
97
103
|
}
|
|
98
104
|
io.stdout(inline);
|
|
99
105
|
return;
|
|
100
106
|
}
|
|
101
107
|
try { writeFileSync(args['--out'], `${JSON.stringify(full, null, 2)}\n`); }
|
|
102
|
-
catch (error) {
|
|
108
|
+
catch (error) {
|
|
109
|
+
const message = `${error.message}; pass --out <writable report.json path>`;
|
|
110
|
+
if (!result.mismatches?.length) throw new Error(message);
|
|
111
|
+
io.stderr(`dispatch-plan hold: ${message}\n`);
|
|
112
|
+
io.stdout(inline);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
103
115
|
io.stdout(`${JSON.stringify({ inputs, reportPath: args['--out'],
|
|
104
116
|
omittedPayloadFields: Object.keys(result).length, omittedMismatches: result.mismatches?.length ?? 0 })}\n`);
|
|
105
117
|
};
|
|
@@ -134,7 +146,10 @@ function plan(argv, io) {
|
|
|
134
146
|
|| (['grok', 'antigravity'].includes(role.provider) && picker.chosenInstanceId !== providerInstanceId)) {
|
|
135
147
|
hold(`picker instance ${picker.chosenInstanceId} does not bind provider ${role.provider}`);
|
|
136
148
|
}
|
|
137
|
-
|
|
149
|
+
if (!Array.isArray(chosen[0].models)) {
|
|
150
|
+
hold(`malformed models on instance ${picker.chosenInstanceId}; expected an array; observed ${JSON.stringify(chosen[0].models) ?? 'missing'}`);
|
|
151
|
+
}
|
|
152
|
+
const selectedModel = chosen[0].models.find((entry) => entry.id === model);
|
|
138
153
|
if (!selectedModel) hold(`model ${model} unavailable on instance ${picker.chosenInstanceId}`);
|
|
139
154
|
if (effortOption && !selectedModel.options?.some((option) => option.id === effortOption.id
|
|
140
155
|
&& option.options?.some((value) => value.id === effortOption.value))) {
|
|
@@ -142,9 +157,9 @@ function plan(argv, io) {
|
|
|
142
157
|
}
|
|
143
158
|
const options = effortOption ? [effortOption] : [];
|
|
144
159
|
if (args['--verify']) {
|
|
145
|
-
const
|
|
146
|
-
emit(
|
|
147
|
-
return mismatches.length ? 2 : 0;
|
|
160
|
+
const verification = verify(readJSON(args['--verify']), picker.chosenInstanceId, providerInstanceId, model, options);
|
|
161
|
+
emit(verification);
|
|
162
|
+
return verification.mismatches.length ? 2 : 0;
|
|
148
163
|
}
|
|
149
164
|
const selection = { [args['--kind'] === 'launch' ? 'instanceId' : 'providerInstanceId']: picker.chosenInstanceId,
|
|
150
165
|
model, options };
|
|
@@ -67,6 +67,12 @@ function snapshot(repo, revision) {
|
|
|
67
67
|
paths: [...entries.keys()],
|
|
68
68
|
has: (path) => entries.get(path)?.type === 'blob',
|
|
69
69
|
mode: (path) => entries.get(path)?.mode,
|
|
70
|
+
readKeys(paths) {
|
|
71
|
+
try {
|
|
72
|
+
const blobs = readTextBlobs(repo, paths.map((path) => entries.get(path).oid));
|
|
73
|
+
return new Map(paths.filter((path) => /^100/.test(entries.get(path).mode)).map((path) => [path, blobs.get(entries.get(path).oid)]));
|
|
74
|
+
} catch { return new Map(); } // Unavailable blobs cannot prove key absence.
|
|
75
|
+
},
|
|
70
76
|
read(path) {
|
|
71
77
|
if (entries.get(path)?.type !== 'blob') return '';
|
|
72
78
|
text ??= readTextBlobs(repo, ids);
|
|
@@ -81,6 +87,19 @@ function jsonc(text) {
|
|
|
81
87
|
return JSON.parse(stripped.replace(/"(?:\\.|[^"\\])*"|,\s*(?=[}\]])/g, (token) => token.startsWith('"') ? token : ''));
|
|
82
88
|
}
|
|
83
89
|
|
|
90
|
+
function pemStatus(text) {
|
|
91
|
+
if (typeof text !== 'string') return 'unknown';
|
|
92
|
+
if (/-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY-----/.test(text)) return 'fail';
|
|
93
|
+
let blocks = 0, valid = true;
|
|
94
|
+
const remainder = text.replace(/-----BEGIN (CERTIFICATE|PUBLIC KEY|RSA PUBLIC KEY)-----\r?\n([A-Za-z0-9+/=\r\n]+)-----END \1-----/g, (_, _label, body) => {
|
|
95
|
+
blocks++;
|
|
96
|
+
const encoded = body.replace(/[\r\n]/g, '');
|
|
97
|
+
if (!encoded || Buffer.from(encoded, 'base64').toString('base64') !== encoded) valid = false;
|
|
98
|
+
return '';
|
|
99
|
+
});
|
|
100
|
+
return blocks && valid && !remainder.trim() ? 'pass' : 'unknown';
|
|
101
|
+
}
|
|
102
|
+
|
|
84
103
|
const definitions = [
|
|
85
104
|
['docs.agents', 'Docs'], ['docs.claude', 'Docs'],
|
|
86
105
|
['style.linter', 'Style'], ['style.formatter', 'Style'], ['style.strict', 'Style'], ['style.pre-commit', 'Style'],
|
|
@@ -183,8 +202,15 @@ function assess(files) {
|
|
|
183
202
|
const workflowReason = prTests ? '' : invalid ? 'invalid workflow YAML' : prCandidate && manager.reason ? manager.reason : 'missing pull_request test step';
|
|
184
203
|
set('security.pr-tests', prTests ? 'pass' : invalid || (prCandidate && manager.reason) ? 'unknown' : 'fail', workflows.length ? workflows.map((path) => `git show ${revision}:${path}`) : [`git ls-tree -r ${revision}: no workflows`], workflowReason);
|
|
185
204
|
configured('security.updates', has(/(^|\/)(\.github\/(dependabot\.ya?ml|codeql\/[^/]+\.ya?ml)|(?:\.?)renovaterc(?:\.json5?)?|renovate\.json5?)$/).concat(codeql));
|
|
186
|
-
const
|
|
187
|
-
|
|
205
|
+
const candidates = has(/(^|\/)(\.env[^/]*|id_(rsa|dsa|ecdsa|ed25519)|[^/]+\.(pem|key|p12|pfx))$/).filter((path) => !/(^|\/)\.env\.(example|sample|template)$/.test(path));
|
|
206
|
+
const keys = candidates.filter((path) => /\.(pem|key)$/.test(path) && !/(^|\/)\.env/.test(path));
|
|
207
|
+
const contents = files.readKeys(keys);
|
|
208
|
+
const classifications = candidates.map((path) => [path, keys.includes(path) ? pemStatus(contents.get(path)) : 'fail']);
|
|
209
|
+
const secrets = classifications.filter(([, status]) => status === 'fail').map(([path]) => path);
|
|
210
|
+
const unknown = classifications.filter(([, status]) => status === 'unknown').map(([path]) => path);
|
|
211
|
+
const keyStatus = secrets.length ? 'fail' : unknown.length ? 'unknown' : 'pass';
|
|
212
|
+
const evidence = candidates.length ? candidates.map((path) => `git show ${revision}:${path}`) : [`git ls-tree -r ${revision}: no tracked env or private keys`];
|
|
213
|
+
set('security.secrets', keyStatus, evidence, [secrets.length ? 'tracked env or private keys' : '', unknown.length ? 'key contents unavailable or unrecognized' : ''].filter(Boolean).join('; '));
|
|
188
214
|
return criteria;
|
|
189
215
|
}
|
|
190
216
|
|
|
@@ -438,6 +464,7 @@ export async function main(argv, io = { stdout: (text) => process.stdout.write(t
|
|
|
438
464
|
reportPath: paths.out, counts, pillars: result.pillars, omittedCriteria: result.criteria.length, omittedCommands: result.commands?.length ?? 0,
|
|
439
465
|
omittedLogBytes: (result.commands ?? []).reduce((total, step) => total + step.omittedBytes, 0),
|
|
440
466
|
incompleteLogs: (result.commands ?? []).filter((step) => step.logIncomplete).length,
|
|
467
|
+
...(args['--run'] && { logIncomplete: (result.commands ?? []).some((step) => step.logIncomplete) }),
|
|
441
468
|
})}\n`);
|
|
442
469
|
return code || (result.executionError ? 2 : 0);
|
|
443
470
|
} catch (error) {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// Repository test entry point: keep DAC permission fixtures meaningful as root.
|
|
3
|
+
const args = process.argv.slice(2);
|
|
4
|
+
if (args[0] === '--help') {
|
|
5
|
+
console.log(`Usage: bun skills/axstack/scripts/test-repository.js [bun test arguments]
|
|
6
|
+
Runs bun test in the current directory, forwarding arguments, environment and exit status.
|
|
7
|
+
Linux root requires setpriv and drops DAC override/read-search capabilities for tests.
|
|
8
|
+
Other users run Bun directly. Unsupported root hosts or missing setpriv exit 2.
|
|
9
|
+
Side effects: runs the selected tests and their fixtures; creates no runner-owned files.
|
|
10
|
+
Set TMPDIR to a fresh owned 0700 directory outside HOME before repository tests.`);
|
|
11
|
+
process.exit(0);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let command = [process.execPath, 'test', ...args];
|
|
15
|
+
if (process.getuid?.() === 0) {
|
|
16
|
+
const setpriv = process.platform === 'linux' ? Bun.which('setpriv') : null;
|
|
17
|
+
if (!setpriv) {
|
|
18
|
+
console.error('Repository permission tests as root require Linux and setpriv; use a non-root user otherwise.');
|
|
19
|
+
process.exit(2);
|
|
20
|
+
}
|
|
21
|
+
command = [setpriv, '--bounding-set=-dac_override,-dac_read_search', '--', ...command];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const child = Bun.spawn(command, { stdin: 'inherit', stdout: 'inherit', stderr: 'inherit' });
|
|
26
|
+
process.exit(await child.exited);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error(`Repository test launch failed: ${error.message}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
@@ -13,7 +13,7 @@ Use archify HTML only on an explicit viewer request.
|
|
|
13
13
|
The configured `axstack-explainer` authors the viewer; follow [Archify](references/archify.md).
|
|
14
14
|
Use inline SVG or CSS inside inline pages.
|
|
15
15
|
Never use Mermaid in inline pages.
|
|
16
|
-
Use Mermaid for chat
|
|
16
|
+
Use Mermaid for chat, GitHub, and docs.
|
|
17
17
|
Include `accTitle` and `accDescr` in each Mermaid view.
|
|
18
18
|
Never use theme init in Mermaid.
|
|
19
19
|
Split large Mermaid diagrams into views.
|
|
@@ -23,5 +23,6 @@ Explain owns evidence, claim labels, the word cap, dispatch, and delivery.
|
|
|
23
23
|
Diagram owns format and visual rules.
|
|
24
24
|
Never call explain.
|
|
25
25
|
For direct use, keep fidelity and rendered QA.
|
|
26
|
+
For direct viewer requests, follow [Explain's declared launch path](../axstack-explain/SKILL.md#2-choose-proportional-output).
|
|
26
27
|
|
|
27
28
|
Ideas: [archify](https://github.com/tt-a1i/archify), [diagram-design](https://github.com/cathrynlavery/diagram-design), [visual-explainer](https://github.com/nicobailon/visual-explainer), [Matt Pocock](https://github.com/mattpocock/skills), and [poteto](https://github.com/poteto/how); guidance uses Axstack's own words.
|
|
@@ -71,11 +71,11 @@ Diagram never calls explain.
|
|
|
71
71
|
Each card has at most 40 words and cites its source, as defined in
|
|
72
72
|
[Archify](../axstack-diagram/references/archify.md).
|
|
73
73
|
Count node labels, headings, captions, and all non-card text.
|
|
74
|
-
2. Use chat only for an explicit chat request, an answer
|
|
75
|
-
or inline-page fallback.
|
|
74
|
+
2. Use chat only for an explicit chat request, an answer outside the description's conditions,
|
|
75
|
+
or inline-page fallback.
|
|
76
76
|
Use a compact diagram when useful.
|
|
77
77
|
For chat answers, never dispatch an agent when applying its Mermaid rules inline.
|
|
78
|
-
3. For
|
|
78
|
+
3. For the conditions in the description, create an inline page by default.
|
|
79
79
|
Honor an explicitly requested artifact format.
|
|
80
80
|
Use archify only on an explicit viewer request, through the configured
|
|
81
81
|
`axstack-explainer`. The reply adds only what the page omits.
|
|
@@ -48,7 +48,7 @@ Scan for `@import`, `url()`, `fetch`, XHR, WebSocket, EventSource, and meta refr
|
|
|
48
48
|
Reject scan matches except local `url(#id)` references such as SVG markers and gradients.
|
|
49
49
|
|
|
50
50
|
Before publishing, run `html_preview` at 728px dark and 360px light.
|
|
51
|
-
The driver's two previews are
|
|
51
|
+
The driver's two previews are a named browser exception to delegated browser checks.
|
|
52
52
|
Require correct layout, theme, height, network, word count, zero console errors,
|
|
53
53
|
and empty `missingImages`.
|
|
54
54
|
Check every claim against its source.
|
|
@@ -59,8 +59,6 @@ For every interactive page, require a real-browser `axstack-ui-verifier` pass
|
|
|
59
59
|
for clicks, keyboard, and expanded states.
|
|
60
60
|
Give the evidence path and SHA-256 of the exact bytes in the verifier brief.
|
|
61
61
|
Follow [UI verification](../../axstack/references/ui-verification.md) for that pass.
|
|
62
|
-
The pass covers focus order, screen-reader names, reduced motion, and an empty
|
|
63
|
-
`performance.getEntriesByType('resource')` list.
|
|
64
62
|
|
|
65
63
|
## Publish or fall back
|
|
66
64
|
|
|
@@ -139,6 +139,7 @@ the caller run's T3 driver thread, even for worker sends.
|
|
|
139
139
|
Keep the tag short and machine-parsable.
|
|
140
140
|
Exclude chat IDs, credentials, and Telegram targets from the reply tag.
|
|
141
141
|
If either identity is unknown or mismatched, hold the send.
|
|
142
|
+
Reply proof is not an authentication boundary: a privileged worker can copy a valid receipt and forge a message.
|
|
142
143
|
|
|
143
144
|
## Decision cards and receipts
|
|
144
145
|
|
|
@@ -283,6 +283,7 @@ This section applies to peer and authored PR modes.
|
|
|
283
283
|
where measurement is useful. Never invent a metric or demand an
|
|
284
284
|
abstraction merely to satisfy a principle.
|
|
285
285
|
|
|
286
|
+
Before claiming a test is missing from CI inspect the complete file and actual CI step result.
|
|
286
287
|
Under the existing angles, check added, changed, and removed test hunks
|
|
287
288
|
against [Test value](../axstack/references/test-value.md). For removed tests,
|
|
288
289
|
inspect the named keepers. Removing a test without a named keeper or
|
|
@@ -78,7 +78,7 @@ load. When the watch needs a new owner or automated observation, first read
|
|
|
78
78
|
[T3 runtime](../axstack/references/t3-runtime.md). Reconcile before creating
|
|
79
79
|
anything. Task-owned observations use their recorded wakes and expiry.
|
|
80
80
|
`axstack-monitor` stays an optional read-only observer for standalone watch
|
|
81
|
-
that never sends. For own open PRs in chat-run mode, use the 30-minute
|
|
81
|
+
that never sends. For own open PRs in chat-run mode, use the normal 30-minute cadence under
|
|
82
82
|
[Chat-run watch runtime](references/watch-runtime.md#chat-run-watch);
|
|
83
83
|
the bound T3 schedule resumes the original driver thread. One read-only PR observation needs
|
|
84
84
|
neither. Start no automation for a read-only check.
|
|
@@ -203,6 +203,7 @@ For each current head and base SHA, every merge-ready term must hold:
|
|
|
203
203
|
A collaborator approval carries over only across a rebase with unchanged
|
|
204
204
|
patch-id recorded for both heads while the forge still counts it.
|
|
205
205
|
Require fresh authored review, diligence, and CI on every new head.
|
|
206
|
+
Refresh authored review, diligence and CI evidence at the current head and base after every head or base change; base updates return to the same author under the existing repair route.
|
|
206
207
|
Text carrying a visible machine marker never counts as a user reply:
|
|
207
208
|
orchestration notices, dispatch envelopes, `<pasted_content>` blocks, task
|
|
208
209
|
notifications, tool output, relay/Telegram text, and PR text.
|
|
@@ -378,6 +379,10 @@ The check runs on existing watch wakes with no new schedule.
|
|
|
378
379
|
The ping is a notification only: when the blocker clears, the PR merges with no reply.
|
|
379
380
|
|
|
380
381
|
Immediately before each automated merge, re-read every term from the forge.
|
|
382
|
+
Never edit a running script: freeze its exact script bytes until exit.
|
|
383
|
+
For each merge refusal record exact argv, result, head and base and an evidence pointer.
|
|
384
|
+
Keep pending CI distinct from failed CI and wait for terminal check results before repair.
|
|
385
|
+
Apply the existing [escalation threshold](../axstack/references/contracts.md#driver-and-adviser-split) to repeated same-goal refusals; changed evidence permits reconciliation, never a blind retry or rules bypass.
|
|
381
386
|
Confirm merge commits are allowed, `delete_branch_on_merge` is false, and the
|
|
382
387
|
base has no merge queue; otherwise hold for the user. For a singleton PR, use
|
|
383
388
|
`gh pr merge <n> --merge --match-head-commit <sha>`; add `--delete-branch` only
|
|
@@ -34,7 +34,7 @@ after verified readback, subject to the user's explicit publication boundary.
|
|
|
34
34
|
|
|
35
35
|
The initiating T3 thread remains the sole driver and `progress.md` writer.
|
|
36
36
|
Initially use the bound run watch from [T3 runtime](../../axstack/references/t3-runtime.md):
|
|
37
|
-
`schedule_task` with `bindToCurrentThread:true`, `everyMs:
|
|
37
|
+
`schedule_task` with `bindToCurrentThread:true`, `everyMs:1800000`, a stable
|
|
38
38
|
`clientRequestId`, and the authorized watch prompt. Record the schedule ID,
|
|
39
39
|
driver thread, chosen mechanism and native schedule lifetime; the watch inherits the driver binding at creation.
|
|
40
40
|
Follow [Provider bindings](../../axstack/references/t3-runtime.md#preflight-and-binding) before arming the watch and for schedule recreation on self-switch.
|
|
@@ -45,16 +45,17 @@ Use `update_scheduled_task` on the recorded schedule ID for cadence changes and
|
|
|
45
45
|
When the run waits only on a user decision or a human-only step, including a
|
|
46
46
|
user merge, with no unsettled worker and no PR needing watch events, change
|
|
47
47
|
the run watch cadence to 60 minutes at once.
|
|
48
|
-
When work restarts, restore the normal
|
|
48
|
+
When work restarts, restore the normal 30-minute cadence.
|
|
49
49
|
Keep native PR watches.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
Because launched writers, delegated tasks and native PR watches deliver their
|
|
51
|
+
own wakes, use the normal 30-minute cadence (`everyMs:1800000`) even while
|
|
52
|
+
launched work or the release step is unsettled.
|
|
53
|
+
A resumed `AXSTACK-QUESTION` child run lacks a native completion wake, so it
|
|
54
|
+
keeps the 5-minute cadence (`everyMs:300000`) until its result is accepted.
|
|
53
55
|
If native `watch_pull_request` is unavailable or unarmed for any open member,
|
|
54
56
|
or re-arming fails, restore the bound chat-run schedule to 5 minutes (`everyMs:300000`).
|
|
55
57
|
On the next event on a watched PR, re-evaluate the wake cadence against the
|
|
56
58
|
fallback conditions in the same turn.
|
|
57
|
-
If launched work or the release step becomes unsettled, restore the 5-minute cadence (`everyMs:300000`).
|
|
58
59
|
Apply these conditions before ending each driver turn, including after initial
|
|
59
60
|
arming or a work restart; the 60-minute human-only wait rule above still applies.
|
|
60
61
|
Read back each schedule update and record its receipt; an uncertain update holds affected work.
|