@1aboveio/skills 1.0.15 → 1.0.17

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 (97) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/.codex-plugin/resources.json +156 -152
  3. package/package.json +4 -4
  4. package/skills/app-dev/airflow/SKILL.md +1 -1
  5. package/skills/app-dev/android-development/SKILL.md +30 -1
  6. package/skills/app-dev/android-development/references/diagnosis.md +50 -0
  7. package/skills/app-dev/android-development/references/feature-work.md +3 -2
  8. package/skills/app-dev/android-development/references/gotchas.md +13 -0
  9. package/skills/app-dev/android-development/references/init.md +31 -2
  10. package/skills/app-dev/android-development/references/setup.md +16 -7
  11. package/skills/app-dev/android-development/references/ui-journeys.md +130 -0
  12. package/skills/app-dev/android-development/scripts/device-run.sh +93 -2
  13. package/skills/app-dev/android-development/scripts/failure_capture.py +331 -0
  14. package/skills/app-dev/android-development/scripts/init.mjs +129 -9
  15. package/skills/app-dev/android-development/scripts/maestro_failure.py +401 -0
  16. package/skills/app-dev/android-development/scripts/test_failure_capture.py +378 -0
  17. package/skills/app-dev/android-development/scripts/test_maestro_failure.py +462 -0
  18. package/skills/app-dev/app-debug/SKILL.md +1 -1
  19. package/skills/app-dev/better-auth/SKILL.md +1 -1
  20. package/skills/app-dev/data-catalog/SKILL.md +1 -1
  21. package/skills/app-dev/data-quality/SKILL.md +1 -1
  22. package/skills/app-dev/ios-foundation/SKILL.md +1 -1
  23. package/skills/app-dev/monorepo/SKILL.md +1 -1
  24. package/skills/app-dev/nextjs-fullstack/SKILL.md +1 -1
  25. package/skills/app-dev/prisma-setup/SKILL.md +1 -1
  26. package/skills/app-dev/pyspark/SKILL.md +1 -1
  27. package/skills/app-dev/python-backend/SKILL.md +1 -1
  28. package/skills/app-dev/shadcn/SKILL.md +1 -1
  29. package/skills/app-dev/zod-v4/SKILL.md +1 -1
  30. package/skills/cicd/cloud-build/SKILL.md +1 -1
  31. package/skills/cicd/cloud-debug/SKILL.md +1 -1
  32. package/skills/cicd/cloud-deploy/SKILL.md +1 -1
  33. package/skills/cicd/docker/SKILL.md +1 -1
  34. package/skills/cicd/github-actions/SKILL.md +1 -1
  35. package/skills/cicd/github-flow/SKILL.md +1 -1
  36. package/skills/cicd/google-cloud/SKILL.md +1 -1
  37. package/skills/cicd/mergify/SKILL.md +1 -1
  38. package/skills/cicd/podman/SKILL.md +1 -1
  39. package/skills/content/article-review/SKILL.md +1 -1
  40. package/skills/content/article-to-image/SKILL.md +1 -1
  41. package/skills/content/flowchart-svg/SKILL.md +1 -1
  42. package/skills/content/image-gen/SKILL.md +1 -1
  43. package/skills/content/mermaid/SKILL.md +1 -1
  44. package/skills/content/wechat-article-writer/SKILL.md +1 -1
  45. package/skills/content/wechat-publisher/SKILL.md +1 -1
  46. package/skills/content/wechat-search/SKILL.md +1 -1
  47. package/skills/content/xai-search/SKILL.md +1 -1
  48. package/skills/core/distill-writing/SKILL.md +1 -1
  49. package/skills/core/doc-to-md/SKILL.md +1 -1
  50. package/skills/core/editorial-review/SKILL.md +1 -1
  51. package/skills/core/house-style/SKILL.md +1 -1
  52. package/skills/core/plain-language/SKILL.md +1 -1
  53. package/skills/core/polish-cn/SKILL.md +1 -1
  54. package/skills/core/reg-parser/SKILL.md +1 -1
  55. package/skills/core/terminology/SKILL.md +1 -1
  56. package/skills/core/write-doc/SKILL.md +1 -1
  57. package/skills/core/write-report/SKILL.md +1 -1
  58. package/skills/engineering/better-review/SKILL.md +1 -1
  59. package/skills/engineering/e2e-test/SKILL.md +1 -1
  60. package/skills/engineering/engineering/SKILL.md +1 -1
  61. package/skills/engineering/engineering-runtime/SKILL.md +1 -1
  62. package/skills/engineering/engineering-runtime/coherence/workflow.json +13 -13
  63. package/skills/engineering/ensure-coverage/SKILL.md +1 -1
  64. package/skills/engineering/golden-path/SKILL.md +1 -1
  65. package/skills/engineering/harness-runtime/SKILL.md +4 -3
  66. package/skills/engineering/harness-runtime/agent-catalog.mjs +929 -0
  67. package/skills/engineering/harness-runtime/contracts.md +2 -0
  68. package/skills/engineering/harness-runtime/references/model-catalog.md +7 -1
  69. package/skills/engineering/resolve-issues/SKILL.md +18 -13
  70. package/skills/engineering/resolve-issues/references/delivery-progress.md +2 -0
  71. package/skills/engineering/resolve-issues/references/expire.md +6 -3
  72. package/skills/engineering/resolve-issues/references/exploration.md +60 -18
  73. package/skills/engineering/resolve-issues/references/implementation.md +7 -2
  74. package/skills/engineering/resolve-issues/references/preflight.md +65 -31
  75. package/skills/engineering/resolve-issues/references/review.md +22 -9
  76. package/skills/engineering/resolve-issues/references/shared-modules.md +142 -20
  77. package/skills/engineering/resolve-issues/references/task-plan.md +62 -8
  78. package/skills/engineering/resolve-issues/scripts/findings-reuse.mjs +1 -1
  79. package/skills/engineering/resolve-issues/scripts/next-actions.mjs +7 -7
  80. package/skills/engineering/resolve-issues/scripts/plan-sync.mjs +1 -1
  81. package/skills/engineering/resolve-issues/scripts/preflight-models.mjs +382 -592
  82. package/skills/engineering/resolve-issues/scripts/size-check.mjs +6 -5
  83. package/skills/engineering/resolve-release/SKILL.md +1 -1
  84. package/skills/engineering/rush-issues/SKILL.md +4 -4
  85. package/skills/engineering/rush-release/SKILL.md +1 -1
  86. package/skills/engineering/test-quality/SKILL.md +1 -1
  87. package/skills/risk-compliance/compliance-audit/SKILL.md +1 -1
  88. package/skills/risk-compliance/contract-compare/SKILL.md +1 -1
  89. package/skills/risk-compliance/contract-review/SKILL.md +1 -1
  90. package/skills/risk-compliance/doc-authenticity/SKILL.md +1 -1
  91. package/skills/risk-compliance/fraud-detection/SKILL.md +1 -1
  92. package/skills/risk-compliance/payment-analysis/SKILL.md +1 -1
  93. package/skills/risk-compliance/portfolio-payment-analysis/SKILL.md +1 -1
  94. package/skills/risk-compliance/similar-domain/SKILL.md +1 -1
  95. package/skills/risk-compliance/tld-detection/SKILL.md +1 -1
  96. package/skills/engineering/resolve-issues/scripts/discover-models.mjs +0 -9
  97. package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +0 -9
@@ -31,33 +31,155 @@ bundle invocations do not install global hooks. Scripted recovery alone is not
31
31
  proof that a Codex surface triggers it; native host compaction/resume certification
32
32
  must pass before that surface is advertised as supported.
33
33
 
34
- ## Model catalog
34
+ ## Model slots
35
35
 
36
- Owner: [`harness-runtime`](../../harness-runtime/) (catalog doctrine and seed
37
- under `references/`, `model-catalog.mjs`, `discover-models.mjs`). Before
38
- reading the doctrine, run the fast path:
36
+ Owner: the harness agent catalog. The workflow names four **roles** — implementer,
37
+ explorer, diagnoser (escalation), reviewer — and the harness decides which model
38
+ fills each one and how that role is launched on this host. The shared bridge is
39
+ [`harness-runtime/agent-catalog.mjs`](../../harness-runtime/agent-catalog.mjs);
40
+ this skill owns no ladder, no tier ranking, and no model list.
41
+
42
+ ### Native Pi preflight
43
+
44
+ When Pi advertises `agents_catalog` and role-based spawning, use the live catalog
45
+ for a run with no task model/effort override or separately declared authoritative
46
+ host preference. Check those inputs before selecting this path: an unpinned task
47
+ can still have `hostPreferences`. The native catalog resolves roles against this
48
+ session's model registry and effort support; a second, caller-built inventory is
49
+ unnecessary.
50
+
51
+ 1. Call `agents_catalog` with `action: "list"`, then `action: "inspect"` for
52
+ `developer`, `explorer`, and `reviewer`. Inspect all three even when the explorer
53
+ will not run. The diagnoser uses the same developer role.
54
+ 2. Require each inspection's live `launchable: yes` and `availability: available`,
55
+ with its actual resolved model and effort. `definitionValid` and
56
+ `catalogLaunchable` alone establish only definition validity, not runtime
57
+ availability. A missing or blocked live decision stops preflight with that
58
+ diagnostic; saved defaults do not replace it.
59
+ 3. Record the catalog revision and each role's **actual** model and effort as run
60
+ metadata. A tier fallback can differ from the displayed default. Use the
61
+ developer result for implementer and diagnoser. Require the reviewer's actual
62
+ model id to differ from the implementer's, regardless of effort; otherwise
63
+ stop and report the conflict without choosing a replacement.
64
+ Save each fill in `selections` as `source: "native-catalog"`, `role`, `id`
65
+ (actual model), `key` (`id@effort` when effort is present), `effort` (actual
66
+ effort), `launch: { role }`, `instructions`
67
+ from the inspection, and the observed `catalogRevision`. Retain the native
68
+ inspection as `selection` evidence, including requested/actual values and
69
+ availability. This is native provenance, not a fabricated portable
70
+ `selection` object or `catalogDigest`.
71
+ 4. Record the later launch by role (`{ role: "developer" }`, `{ role: "explorer" }`, or
72
+ `{ role: "reviewer" }`), adding the task brief and authorized workspace/tool
73
+ controls. The native catalog applies its live instructions and defaults again
74
+ at admission. Record actual launch provenance if it differs from preflight.
75
+
76
+ This completes model preflight; continue to the provisional target without
77
+ running `preflight-models.mjs` or manufacturing `available[]`. Worker capacity is
78
+ a separate scheduling input, not model evidence. An explicit task model or effort
79
+ override or authoritative host model/effort preference still needs validation for
80
+ that exact request: use the portable path below when the native inspection cannot
81
+ validate it and preserve its structured launch fields. Keep the request; an
82
+ unresolved request does not authorize a default launch.
83
+
84
+ ### Portable preflight
85
+
86
+ For a host without native role resolution, or a task override or authoritative
87
+ host preference requiring portable validation, write observed host capabilities
88
+ to a temporary JSON file (any writable path; the run directory does not exist yet
89
+ at step 1):
90
+
91
+ ```json
92
+ { "available": [{ "model": "provider/model", "nativeModel": "host-id", "supportedEfforts": ["medium", "high"] }],
93
+ "foregroundModel": "provider/model",
94
+ "launchCapabilities": { "model": true, "effort": true, "instructions": true },
95
+ "hostPreferences": { "developer": { "model": "provider/model" } },
96
+ "fallbackToForeground": false }
97
+ ```
98
+
99
+ Every field is evidence the host reports, never something to fill in from memory;
100
+ a field you cannot observe is left out, and the bridge never completes one.
101
+
102
+ | Field | Meaning |
103
+ |---|---|
104
+ | `available[]` | This turn's models. Each entry needs verified `supportedEfforts`; IDs alone from configuration or `discover-models.mjs` do not supply effort support. `nativeModel` is required for a harness whose slots are launched by a bare host id (Codex); pass the advertised mapping unchanged. |
105
+ | `launchCapabilities` | The launch controls this host exposes: `model`, `effort`, `instructions`, each a boolean. All three must be stated; omission is not "probably true". A native id and an effort say what the catalog chose, never that the adapter can set it. |
106
+ | `hostPreferences` | This host's own role preferences, keyed by **role** (`developer`, `explorer`, `reviewer`), each `{ model?, effort? }`. Below a task override and above the role default: it is how a host says "this machine runs the developer role on this model". |
107
+ | `fallbackToForeground` | Set `true` only when this host may use the foreground model as a fallback. Pi always may; another harness must opt in. Absent, no foreground fallback happens for it. |
108
+ | `tiers` | `{ tiers: { name: { members: [], candidates: [] } } }` — tier membership plus the ordered candidates that may replace an unavailable preferred model. `members` and `candidates` are `provider/model` ids; a candidate may be `{ model, crossProvider: true }` to allow another provider. An empty `candidates` list means no substitution. |
109
+ | `overrides` | The task's own pins, keyed by **slot** (`implementer`, `explorer`, `diagnoser`, `reviewer`). Highest precedence. |
110
+
111
+ `hostPreferences` is how a machine states its own choice instead of leaving it to the
112
+ saved role default. Example: this host's personal developer role points at a small
113
+ local model, but this machine runs the developer role on a stronger
114
+ `provider/model`. Declaring `"hostPreferences": { "developer": { "model":
115
+ "provider/model", "effort": "high" } }` outranks the role default; the catalog
116
+ reports it as an explicit request and the Pi launch keeps it instead of stripping
117
+ it back to `{ role }`. Omit the effort and only the model is pinned.
118
+
119
+ Then run:
39
120
 
40
121
  ```bash
41
122
  node <skill-base-dir>/scripts/preflight-models.mjs \
42
- --harness <pi|codex|claude-code> --risk <routine|high> \
43
- --available <comma-separated-current-turn-model-ids> --ask-only
123
+ --harness <pi|codex|claude-code> --capabilities /tmp/resolve-issues-capabilities.json
44
124
  ```
45
125
 
46
- Record its fills without asking. Use its `options` (up to four, recommended
47
- first) for the implementer question at the approval; accept an `alternate`
48
- or any discovered model the human names. Never run scripts under
49
- `archive/resolve-issues/`.
126
+ Record its fills by exact id and effort as run metadata, and show them on the
127
+ board. No role is a question: this workflow never asks which model should
128
+ implement, and the script emits no option list. The resolver is
129
+ `pi-agent-catalog` on PATH, or the JSON argv in `PI_AGENT_CATALOG_COMMAND` when
130
+ a host wraps it. Never run scripts under `archive/resolve-issues/`.
50
131
 
51
- | Slot | Selection |
52
- |---|---|
53
- | Implementer, routine | `gpt-6.1-sol@high`, `gpt-6-luna@high`, `grok-4.6@high`, `mimo-v2.6-pro@high` |
54
- | Implementer, high risk | `gpt-6.1-sol@high`, `gpt-6-astra@high`, `gpt-5.6-sol@high`, `grok-4.7@high` |
55
- | Explorer | `gpt-6.1-sol@medium`, then the routine ladder without `gpt-6.1-sol@high` |
56
- | Escalation (test-first workers, and fix workers after a cycle without progress; `preflight-models.mjs` key `diagnoser`) | The high-risk ladder, at any risk |
57
- | Reviewer | `gpt-6-astra@medium`; `gpt-5.6-sol@medium` when Astra implements; otherwise the payload's distinct-model ranking |
58
-
59
- Use only discovered or named models. Sync the catalog only after the
60
- approval. Require each spawn's read-back to match its slot.
132
+ | Role | Payload | Spawn with |
133
+ |---|---|---|
134
+ | Implementer | `implementer` | its own `launch` + `instructions` |
135
+ | Explorer | `explorer` | its own `launch` + `instructions` |
136
+ | Escalation (test-first workers, and fix workers after a cycle without progress) | `diagnoser` (developer role) | its own `launch` + `instructions` |
137
+ | Reviewer | `reviewer` | its own `launch` + `instructions` |
138
+
139
+ Each fill carries `{ id, key, effort, role, launch, instructions, selection }`,
140
+ and the payload carries the `catalogDigest` they were resolved under.
141
+
142
+ **Launch the fill, not the model.** On Pi a `launch` is `{ role }` plus a `model`
143
+ and `thinking` only when something explicitly asked for them: the human's task
144
+ override, or the host's own preference, which the catalog reports as an explicit
145
+ selection. A resolved role default is never copied in — the live Pi catalog keeps
146
+ supplying that. On Codex the `launch` is `{ model, effort, instructions }` with the
147
+ adapter's native id, and the run is blocked unless the host advertised every
148
+ control that launch needs: a slot whose harness cannot express the selection is a
149
+ blocked run (`launch-unsupported`), never a launch that claims a model it did not
150
+ set; never describe a model choice in the brief and call it selection.
151
+
152
+ Use the implementer fill for the run and show it as resolved. A model the human
153
+ names is an explicit override: rerun the fast path with `--implementer
154
+ <id[@effort]>` and use that result. A pinned implementer that the catalog
155
+ declines is `ok: false` with `code: pinned-implementer-unavailable`; end the run
156
+ and substitute nothing.
157
+
158
+ **A blocked result ends the run.** `ok: false` — no resolver, no capabilities,
159
+ a declined request, an unadvertised launch control, a missing native selection —
160
+ means report its `code` and `reason` and start nothing. Never reuse an earlier
161
+ pick, never fall back to the skill-owned catalog, and never let the reviewer share
162
+ the implementer's model id: the catalog enforces independence, and re-picking a
163
+ replacement here would silently break it.
164
+
165
+ `capabilities-missing` describes incomplete resolver input, not proof that the
166
+ host cannot launch workers. Check the supplied file and this turn's native
167
+ capability source before declaring a harness limitation. Repair an omitted field
168
+ from verified evidence and retry preflight; if that evidence is unavailable,
169
+ report the exact missing input. Never derive effort ranges from a selected role
170
+ default or use free worker slots as a model inventory.
171
+
172
+ **No fallback is invented.** The catalog substitutes only an available model from
173
+ the same tier's configured `candidates`, and never for an explicit request: an
174
+ unavailable pin or host preference blocks rather than sliding to a neighbour, and
175
+ a non-Pi host does not inherit the foreground model unless it set
176
+ `fallbackToForeground: true`. Nothing here upgrades, downgrades, or keeps a
177
+ previous run's pick to avoid a block.
178
+
179
+ The `harness-runtime` package's legacy `model-catalog.mjs` and `discover-models.mjs`
180
+ modules remain for other consumers that still import them; this workflow imports
181
+ only `detectHarness` from `discover-models.mjs` and never uses either to select a
182
+ model slot. The skill's own compatibility wrappers for those commands are gone.
61
183
 
62
184
  ## Leaf skills
63
185
 
@@ -1,6 +1,6 @@
1
1
  # Task plan
2
2
 
3
- Draft the plan in preflight, before exploration, and update it on every
3
+ Draft the plan in preflight, before the assessment, and update it on every
4
4
  worker and stage transition.
5
5
 
6
6
  ## Initialize the run
@@ -92,7 +92,7 @@ Fleet `status`: `pending`, `in-flight`, `succeeded`, `failed`,
92
92
  | `attempt`, `retries`, `escalations` | Attempt number; cycle counts; escalation-model attempts |
93
93
  | `worker`, `workerSince`, `clock` | Slot identifier of any worker running for the unit (implementer, reviewer, fix), `null` when none; when that worker started (ISO time, for [stuck-worker checks](expire.md#waits)); attempt and cumulative wall time |
94
94
  | `workerKind` | `implement`, `fix`, or `review`, set with `worker`; the [live-capacity scheduler](implementation.md#live-capacity) (`next-actions.mjs`) prints `worker-kind` for any other kind or none. An infrastructure diagnosis or a test-first worker is a `fix` worker. The explorer is the `explore` fleet row's worker, never a unit's; a merge-queue watcher is not a worker |
95
- | `estimatedLines` | Explorer estimate |
95
+ | `estimatedLines` | Preflight assessment estimate |
96
96
  | `sizeCheck` | Measures, `verdict` (the size check's per-unit verdict; `stop` means held), scope and proof verdicts, split or verification path; `runWhole: true` once a recommendation to run a held unit whole is accepted |
97
97
  | `note` | SHA, expiry reason code, failure and response, or blocker; for active debugging, the immediate acceptance checkpoint, baseline/result link and next distinguishing test ([delivery progress](../SKILL.md#delivery-progress)) |
98
98
  | `pr`, `headSha`, `reviewedHead` | PR URL, current HEAD (recorded from the implementer's first pushed commit on, so the draft PR opens early), last HEAD whose verdict was `pass` (reviewed or carried) |
@@ -117,15 +117,27 @@ Run fields: optional `installation` holds the explicit native installation descr
117
117
  pinned external root mappings). Capture from the selected bundle and preserve it
118
118
  through workers and recovery; never replace it with a newer cache or shared copy.
119
119
  Other run fields: `skill` (`resolve-issues` or `rush-issues`; the scheduler and
120
- rehydrate read it, and `next-actions.mjs` exits 2 without it), `planRevision`, models and efforts, `targetBranch`,
120
+ rehydrate read it, and `next-actions.mjs` exits 2 without it), `planRevision`, `selections`, `targetBranch`,
121
121
  `workspaceLifecycle: 1` and `repoRoot` ([workspaces.md](workspaces.md)),
122
122
  `deliveryMode` and its check, `mergeMode`, run directory, `specLocator`
123
123
  (`owner/name#N` or an issue URL; any other name turns off the issue-tree sync),
124
124
  exploration path, `decisions`, `standingOrders`, `schedulerMode` (`full`, `narrow`, or `off`), timestamps, and `excluded` (issues in the
125
125
  tree that are deliberately not units, each `{issue, reason}`: release or
126
- approval gates, and rollups the explorer found empty). A run resumed from an
126
+ approval gates, and rollups the assessment found empty). A run resumed from an
127
127
  older wave run keeps `merged` (unit ids merged by earlier runs).
128
128
 
129
+ `selections` records each slot's fill from the selected
130
+ [model-preflight path](shared-modules.md#model-slots). A native Pi fill records
131
+ `source: "native-catalog"`, `role`, actual `id`, `key` and `effort`, `launch: { role }`,
132
+ inspected `instructions`, `catalogRevision` and the retained native inspection
133
+ as `selection`. A portable fill is what `preflight-models.mjs` returned —
134
+ `id`, `key`, `effort`, `role`, `launch`, `instructions`, `selection`, and the
135
+ `catalogDigest` it was resolved under — beside the explicit task or host override
136
+ that produced it, when one did
137
+ ([shared-modules.md](shared-modules.md#model-slots)). Its `id` and `effort` are
138
+ recorded evidence of what the catalog resolved, not a pin to replay. The fill is
139
+ what a later launch of the slot repeats; a pair of model ids is not.
140
+
129
141
  `reviewFindings` entry: id, `severity` P0-P2 (P3 is skipped, never recorded), summary, locator, `status`
130
142
  (`open`, `resolved`, `deferred`), `resolvedHead`, `dropboxId` or `followUpUrl`. Copy them
131
143
  from `review-verdict.mjs`: on `fix` its `fix` list as `open`; on `pass` its
@@ -139,6 +151,41 @@ question it settles (`results/<unit>-<label>.json`, or
139
151
  agent's recommendation adds `source: agent-recommendation` and the
140
152
  recommendation's reason; its human's words are the invocation.
141
153
 
154
+ ### Worker selection on resume
155
+
156
+ **A launch repeats the saved fill, never a reconstruction of it.** On Pi the
157
+ launch authority stays the live role resolver ([shared-modules.md](shared-modules.md#model-slots)):
158
+ its `launch` is `{ role }` unless an explicit task override or this host's own
159
+ preference asked for a model or effort, and a resolved role default is never
160
+ written out as an explicit pin. On a non-Pi host the recorded `launch` is the
161
+ payload, and it names only the controls that host advertised. What a worker
162
+ actually launched with, its model and effort included, and its result are that
163
+ worker's run evidence: record them, keep them immutable, and never re-apply them
164
+ to another launch or rewrite them.
165
+
166
+ A plan saved before `selections` holds model ids and efforts and nothing saying
167
+ who chose them. Read such a value as evidence of what ran, never as a pin: do
168
+ not pass it as an explicit Pi model or effort. Before launching new workers,
169
+ repeat this host's model-preflight path ([preflight.md](preflight.md#1-model-slots))
170
+ with only the overrides the run can evidence — a `standingOrders` line, a
171
+ human-authored decision, or an explicit override in the invocation, never an
172
+ agent recommendation or stored metadata alone — and record its resolved fills
173
+ as `selections`. When an override's provenance, or a launch control the current
174
+ host must advertise, cannot be established, block the new launch and name what
175
+ is missing: report the code and reason and start nothing, rather than guessing a
176
+ pin. Workers already running or finished keep their configuration and history.
177
+ A resume asks no model question; a human who changes one does so as a separate
178
+ task input, recorded as a decision and resolved the same way.
179
+
180
+ For `source: "native-catalog"`, recheck current task overrides and authoritative
181
+ host preferences on resume. With neither, repeat live native inspection rather
182
+ than demanding a portable `catalogDigest` or running the portable script. A newly
183
+ declared preference or override returns through the exact-request validation path;
184
+ do not replay role-only defaults in its place. Keep
185
+ the old inspection as historical evidence; refresh preflight selection metadata
186
+ without rewriting any worker's actual launch history. A native inspection is not
187
+ an override, and its saved model and effort never become launch arguments.
188
+
142
189
  ### Standing orders
143
190
 
144
191
  **`standingOrders` are the run's only constraints.** A numbered list, one
@@ -178,14 +225,20 @@ Example: someone files #61 under epic #12 mid-run; the next resume prints
178
225
  - A failed fetch keeps the saved tree; a partial one never drops a unit or
179
226
  changes dependencies. A failed fetch before finishing never finishes:
180
227
  `next-actions.mjs` with [live capacity](implementation.md#live-capacity) prints `sync` until a fetch reads the tree.
181
- - `set-deps` only adds; a dependency the explorer recorded stays.
228
+ - At start and resume, fetch current spec and existing unit issue bodies from
229
+ their source and compare their criteria with the saved requirements, decisions,
230
+ contracts and relevant guidance. The tree fetch updates membership and links,
231
+ not issue bodies; unchanged sync output does not establish unchanged criteria.
232
+ Reassess affected units under [assessment reuse](exploration.md#reuse-first),
233
+ or reassess when the prior inputs cannot be established, before scheduling them.
234
+ - `set-deps` only adds; a dependency recorded in findings stays.
182
235
  - `cycle`: units depend on, or are chained on, each other, so none can move.
183
236
  Remove the link that is not a real dependency (on GitHub and in the plan);
184
237
  for a `stacksOn` loop, restack the unit it names onto the target.
185
238
  - `blocked-outside`: put the blocker into the tree (as a sibling of the
186
239
  waiting issue) or remove the link; never leave a unit waiting on an issue
187
240
  the run cannot see.
188
- - A rollup the explorer finds empty goes to `excluded` with "nothing left:
241
+ - A rollup the assessment finds empty goes to `excluded` with "nothing left:
189
242
  close it", and into the handback.
190
243
  - A unit that depends on an `excluded` issue waits for a human: it stays
191
244
  `pending` (not started), `next-actions.mjs` with [live capacity](implementation.md#live-capacity) gives it no action, and
@@ -196,7 +249,7 @@ Example: someone files #61 under epic #12 mid-run; the next resume prints
196
249
  ## Scope changes
197
250
 
198
251
  Record a new requirement as a decision, update the affected criteria,
199
- continue the explorer on affected and new units, rerun the size check, and
252
+ reassess affected and new units using [owner routing](exploration.md#choose-the-owner), rerun the size check, and
200
253
  show the board. Put the change in in-flight units' next brief; never copy
201
254
  files into a running workspace. Add new units as rows and schedule them
202
255
  normally.
@@ -279,7 +332,8 @@ text board. Keep the board and file in agreement. Never show an unsaved transiti
279
332
 
280
333
  ## Board
281
334
 
282
- Show the first board before the explorer spawn, as a record.
335
+ Show the first board before the preflight assessment, as a record. The fleet
336
+ `explore` row tracks that assessment, with a worker only when one is delegated.
283
337
 
284
338
  ```text
285
339
  resolve-issues rev 12 workers 2 elapsed 18m delivery stack
@@ -66,7 +66,7 @@ export function findingsReuse({ prior, units, head = 'HEAD' }) {
66
66
  let baseKnown = typeof prior?.base === 'string' && prior.base.trim() !== ''
67
67
  let changed = []
68
68
  if (baseKnown) {
69
- try { changed = git(['diff', '--name-only', prior.base, headSha]).split('\n').filter(Boolean) } catch { baseKnown = false }
69
+ try { changed = git(['diff', '--name-only', '--no-renames', prior.base, headSha]).split('\n').filter(Boolean) } catch { baseKnown = false }
70
70
  }
71
71
  const ids = units?.length ? units : Object.keys(prior?.units ?? {})
72
72
  return { base: prior?.base ?? null, head: headSha, ...decideReuse(prior, ids, changed, baseKnown) }
@@ -16,8 +16,8 @@
16
16
  // GitHub call. Sync after the run files an issue
17
17
  // unblock a unit marked blocked without a reason from BLOCK_REASONS
18
18
  // (`blockedReason`), or human-decision without `humanItem` (1-5) and
19
- // `humanNeed`: reopen it now; and on --resume, every blocked unit:
20
- // reopen it with fresh limits; its next step follows. A note never keeps a
19
+ // `humanNeed`: reopen it now; on --resume, reopen prior blocks with fresh
20
+ // limits except a current size stop without accepted runWhole. A note never keeps a
21
21
  // unit blocked. A complete review at the unit's HEAD that holds a P0/P1 but
22
22
  // wrote no fix brief and awaits no GitHub reviewer (a handback) gets a
23
23
  // fresh full round, so review-verdict hands it back again only if its
@@ -122,7 +122,7 @@ import { BLOCKING } from './review-verdict.mjs'
122
122
  export const WORKER_KINDS = Object.freeze(['implement', 'fix', 'review'])
123
123
  export const SKILL_PATH = join(dirname(dirname(fileURLToPath(import.meta.url))), 'SKILL.md')
124
124
  // Printed after every text call, and by rehydrate.mjs after a compaction.
125
- export const RULES = 'Per unit, run only implement, fix, and review workers, recorded as workerKind: no planning, architecture, product, or setup workers. Exploration continues the run\'s one explorer, on the fleet explore row. You coordinate: never edit product code. In full mode take every step from next-actions.mjs; in every mode the run ends only when it reports done. A HEAD after a passing review is carried; any other new HEAD takes the tier rereview-scope.mjs picks, never yours. Decide before you defer: a question a worker or review raises is answered and recorded, then the unit continues; retrying or deferring never answers it. Never block on the human: take the automatic answer and keep going. Fix the root cause, never only its symptom. Before each scheduling pass, refresh subagent_settings and pass its snapshot with --capacity-json; do not reuse a run-start budget or subtract workflow workers again.'
125
+ export const RULES = 'Per unit, run only implement, fix, and review workers, recorded as workerKind: no planning, architecture, product, or setup workers. You own preflight findings; use an optional explorer on the fleet explore row only for concrete planning unknowns (exploration.md). You coordinate: never edit product code. In full mode take every step from next-actions.mjs; in every mode the run ends only when it reports done. A HEAD after a passing review is carried; any other new HEAD takes the tier rereview-scope.mjs picks, never yours. Decide before you defer: a question a worker or review raises is answered and recorded, then the unit continues; retrying or deferring never answers it. Never block on the human: take the automatic answer and keep going. Fix the root cause, never only its symptom. Before each scheduling pass, refresh subagent_settings and pass its snapshot with --capacity-json; do not reuse a run-start budget or subtract workflow workers again.'
126
126
  export const DEFAULT_QUIET_MINUTES = 45
127
127
  // The reasons a unit may stay blocked (expire.md#reason-codes). Waiting on another unit, an
128
128
  // infrastructure or external blocker (a tree issue the unit waits on), and a size hold in a rush
@@ -205,15 +205,15 @@ export function nextActions(plan, reviews = {}, capacity, { resume = false, now,
205
205
  if (!Array.isArray(saved) || saved.length === 0) throw new NextActionsError('task plan has no units')
206
206
  const excluded = excludedIds(plan)
207
207
  const gates = (u) => (u.dependsOn ?? []).map(String).filter((d) => excluded.has(d))
208
- // In a rush run, a size-held unit is split, never deferred: it gets `split` until the sync
209
- // drops it (split into sub-issues) or a rerun size check clears it.
208
+ // A current size stop survives resume. Rush splits it; a normal run may hand it back.
210
209
  const shortcut = plan.skill === 'rush-issues'
211
- const sizeHeld = (u) => shortcut && (u.sizeCheck?.verdict ?? u.sizeCheck?.scope) === 'stop' && u.sizeCheck?.runWhole !== true && !codeDone(u)
210
+ const heldForSize = (u) => (u.sizeCheck?.verdict ?? u.sizeCheck?.scope) === 'stop' && u.sizeCheck?.runWhole !== true && !codeDone(u)
212
211
  && !hasWorker(u) && u.status !== 'succeeded' && u.status !== 'cancelled' && gates(u).length === 0
213
212
  && !excluded.has(String(u.id))
213
+ const sizeHeld = (u) => shortcut && heldForSize(u)
214
214
  const reasonOk = (u) => BLOCK_REASONS.includes(u.blockedReason) && !(shortcut && u.blockedReason === 'size-hold')
215
215
  && (u.blockedReason !== 'human-decision' || namesHumanItem(u))
216
- const reopen = (u) => (resume || !reasonOk(u)) && u.status === 'blocked' && !hasWorker(u) && gates(u).length === 0 && !sizeHeld(u)
216
+ const reopen = (u) => (resume || !reasonOk(u)) && u.status === 'blocked' && !hasWorker(u) && gates(u).length === 0 && !heldForSize(u)
217
217
  // `stack` and `chain` both open a child's PR once its parents' PRs are open; only the PR base differs.
218
218
  if (plan.deliveryMode !== undefined && !['stack', 'chain', 'wait'].includes(plan.deliveryMode)) throw new NextActionsError(`deliveryMode must be stack, chain, or wait: ${JSON.stringify(plan.deliveryMode)}`)
219
219
  const chain = plan.deliveryMode === 'chain'
@@ -139,7 +139,7 @@ export function planSync(plan, tree) {
139
139
  const { deps } = wants(key)
140
140
  const id = idFor(key, repo)
141
141
  const rollup = (node.children ?? []).length > 0
142
- add('add-unit', id, `add unit ${id} for ${key} "${node.title}"${deps.length ? ` with dependsOn [${deps.join(', ')}]` : ''}: fetch its issue into the run, continue the explorer for it, rerun the size check${rollup ? '; every sub-issue is closed, so the explorer records what is left or that nothing is (then hand back "close it")' : ''}`, { issue: key, dependsOn: deps })
142
+ add('add-unit', id, `add unit ${id} for ${key} "${node.title}"${deps.length ? ` with dependsOn [${deps.join(', ')}]` : ''}: fetch its issue into the run, assess it using exploration.md's owner routing, rerun the size check${rollup ? '; every sub-issue is closed, so record what is left or that nothing is (then hand back "close it")' : ''}`, { issue: key, dependsOn: deps })
143
143
  }
144
144
  for (const [key, u] of byKey) {
145
145
  if (DONE.has(u.status)) continue