@frankzhang2026/opencode-android-orchestrator 0.9.0 → 1.0.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 (127) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +92 -55
  3. package/dist/cli.js +14 -1
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config/android-sdk.d.ts +10 -0
  6. package/dist/config/android-sdk.d.ts.map +1 -0
  7. package/dist/config/android-sdk.js +50 -0
  8. package/dist/config/android-sdk.js.map +1 -0
  9. package/dist/config/commit-message-prefix.d.ts +31 -0
  10. package/dist/config/commit-message-prefix.d.ts.map +1 -0
  11. package/dist/config/commit-message-prefix.js +155 -0
  12. package/dist/config/commit-message-prefix.js.map +1 -0
  13. package/dist/config/queue-policy.d.ts +12 -0
  14. package/dist/config/queue-policy.d.ts.map +1 -0
  15. package/dist/config/queue-policy.js +18 -0
  16. package/dist/config/queue-policy.js.map +1 -0
  17. package/dist/config/verification-policy.d.ts +10 -3
  18. package/dist/config/verification-policy.d.ts.map +1 -1
  19. package/dist/config/verification-policy.js +66 -13
  20. package/dist/config/verification-policy.js.map +1 -1
  21. package/dist/doctor/index.d.ts.map +1 -1
  22. package/dist/doctor/index.js +3 -49
  23. package/dist/doctor/index.js.map +1 -1
  24. package/dist/doctor/installation.d.ts.map +1 -1
  25. package/dist/doctor/installation.js +81 -0
  26. package/dist/doctor/installation.js.map +1 -1
  27. package/dist/index.d.ts +1 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +1 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/installer/adaptive-templates.d.ts +8 -2
  32. package/dist/installer/adaptive-templates.d.ts.map +1 -1
  33. package/dist/installer/adaptive-templates.js +10 -0
  34. package/dist/installer/adaptive-templates.js.map +1 -1
  35. package/dist/installer/index.d.ts +1 -0
  36. package/dist/installer/index.d.ts.map +1 -1
  37. package/dist/installer/index.js +1 -0
  38. package/dist/installer/index.js.map +1 -1
  39. package/dist/installer/init.d.ts +4 -1
  40. package/dist/installer/init.d.ts.map +1 -1
  41. package/dist/installer/init.js +60 -9
  42. package/dist/installer/init.js.map +1 -1
  43. package/dist/installer/install-manifest.d.ts +1 -0
  44. package/dist/installer/install-manifest.d.ts.map +1 -1
  45. package/dist/installer/install-manifest.js +6 -1
  46. package/dist/installer/install-manifest.js.map +1 -1
  47. package/dist/installer/opencode-config.d.ts +3 -3
  48. package/dist/installer/opencode-config.js +1 -1
  49. package/dist/installer/uninstall.d.ts.map +1 -1
  50. package/dist/installer/uninstall.js +5 -0
  51. package/dist/installer/uninstall.js.map +1 -1
  52. package/dist/installer/upgrade.d.ts +5 -1
  53. package/dist/installer/upgrade.d.ts.map +1 -1
  54. package/dist/installer/upgrade.js +94 -11
  55. package/dist/installer/upgrade.js.map +1 -1
  56. package/dist/plugin/index.d.ts.map +1 -1
  57. package/dist/plugin/index.js +11 -5
  58. package/dist/plugin/index.js.map +1 -1
  59. package/dist/queue/approvals.d.ts +49 -0
  60. package/dist/queue/approvals.d.ts.map +1 -0
  61. package/dist/queue/approvals.js +68 -0
  62. package/dist/queue/approvals.js.map +1 -0
  63. package/dist/queue/cli.d.ts +3 -0
  64. package/dist/queue/cli.d.ts.map +1 -0
  65. package/dist/queue/cli.js +109 -0
  66. package/dist/queue/cli.js.map +1 -0
  67. package/dist/queue/executor.d.ts +24 -0
  68. package/dist/queue/executor.d.ts.map +1 -0
  69. package/dist/queue/executor.js +445 -0
  70. package/dist/queue/executor.js.map +1 -0
  71. package/dist/queue/lifecycle.d.ts +3 -0
  72. package/dist/queue/lifecycle.d.ts.map +1 -0
  73. package/dist/queue/lifecycle.js +24 -0
  74. package/dist/queue/lifecycle.js.map +1 -0
  75. package/dist/queue/queue.d.ts +154 -0
  76. package/dist/queue/queue.d.ts.map +1 -0
  77. package/dist/queue/queue.js +411 -0
  78. package/dist/queue/queue.js.map +1 -0
  79. package/dist/queue/service.d.ts +15 -0
  80. package/dist/queue/service.d.ts.map +1 -0
  81. package/dist/queue/service.js +152 -0
  82. package/dist/queue/service.js.map +1 -0
  83. package/dist/queue/storage.d.ts +30 -0
  84. package/dist/queue/storage.d.ts.map +1 -0
  85. package/dist/queue/storage.js +171 -0
  86. package/dist/queue/storage.js.map +1 -0
  87. package/dist/queue/tools.d.ts +12 -0
  88. package/dist/queue/tools.d.ts.map +1 -0
  89. package/dist/queue/tools.js +144 -0
  90. package/dist/queue/tools.js.map +1 -0
  91. package/docs/MIGRATION.md +47 -14
  92. package/docs/QUEUE.md +146 -0
  93. package/docs/SECURITY.md +48 -32
  94. package/docs/TROUBLESHOOTING.md +36 -11
  95. package/package.json +1 -1
  96. package/templates/.opencode/agents/scheduled-planner.md +60 -131
  97. package/templates/.opencode/commands/abort-task.md +6 -15
  98. package/templates/.opencode/commands/acceptance.md +6 -15
  99. package/templates/.opencode/commands/change.md +3 -1
  100. package/templates/.opencode/commands/resume-review.md +6 -14
  101. package/templates/.opencode/commands/resume-task.md +6 -23
  102. package/templates/.opencode/skills/scheduled-quality-orchestrator/SKILL.md +69 -248
  103. package/templates/AGENTS.md.fragment +8 -0
  104. package/templates/README.md +9 -1
  105. package/templates/automation/config.json +9 -2
  106. package/templates/automation/config.schema.json +222 -45
  107. package/templates/scripts/automation/abort-task.sh +4 -2
  108. package/templates/scripts/automation/accept-and-integrate.sh +9 -2
  109. package/templates/scripts/automation/acceptance-report.sh +4 -2
  110. package/templates/scripts/automation/approve-and-run.sh +5 -0
  111. package/templates/scripts/automation/begin-review.sh +1 -0
  112. package/templates/scripts/automation/block-task.sh +1 -0
  113. package/templates/scripts/automation/claim-task.sh +1 -0
  114. package/templates/scripts/automation/lib.sh +186 -2
  115. package/templates/scripts/automation/orchestrate-task.sh +12 -0
  116. package/templates/scripts/automation/preflight.sh +25 -4
  117. package/templates/scripts/automation/prepare-contract-review.sh +4 -0
  118. package/templates/scripts/automation/quality-gate.sh +1 -0
  119. package/templates/scripts/automation/record-red.sh +1 -0
  120. package/templates/scripts/automation/resume-review-fix.sh +1 -0
  121. package/templates/scripts/automation/resume-review.sh +1 -0
  122. package/templates/scripts/automation/resume-task.sh +1 -0
  123. package/templates/scripts/automation/scope-gate.sh +10 -2
  124. package/templates/scripts/automation/show-acceptance-review.sh +3 -0
  125. package/templates/scripts/automation/submit-review.sh +8 -2
  126. package/templates/scripts/automation/tests/run-tests.sh +59 -4
  127. package/templates/scripts/automation/verify-task.sh +13 -0
package/docs/MIGRATION.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Migration guide
2
2
 
3
3
  This guide covers migration to
4
- `@frankzhang2026/opencode-android-orchestrator@0.9.0`. Pin the exact version and
4
+ `@frankzhang2026/opencode-android-orchestrator@1.0.0`. Pin the exact version and
5
5
  prove the migration in a disposable clone before changing a long-lived
6
6
  repository.
7
7
 
@@ -9,13 +9,13 @@ repository.
9
9
 
10
10
  | Current state | Correct command after release | Important distinction |
11
11
  | --- | --- | --- |
12
- | No orchestrator files or manifest | `npx @frankzhang2026/opencode-android-orchestrator@0.9.0 init .` | Normal new installation; all runtime-detected Android modules and registered debug verification tasks are discovered automatically. |
12
+ | No orchestrator files or manifest | `npx @frankzhang2026/opencode-android-orchestrator@1.0.0 init .` | Normal new installation; all runtime-detected Android modules and registered debug verification tasks are discovered automatically. |
13
13
  | Published `0.1.0` scaffold only | Remove any project-local `@0.1.0` plugin reference after review, then run `init`. | `0.1.0` did not create a usable managed installation and cannot be upgraded. |
14
- | `0.2.0` through `0.8.1` manifest-managed installation with intact managed/backup content | Run the `0.9.0` `upgrade`; add `--refresh-gradle-discovery` when generated module/task lists are incomplete. | Refresh replaces all derived module metadata, source paths, protected build files, and task allowlists from one Gradle runtime snapshot. Module scope, boolean verification policies, and user-owned AGENTS content remain preserved. |
14
+ | `0.2.0` through `0.10.0` manifest-managed installation with intact managed/backup content | Run the `1.0.0` `upgrade`; add `--refresh-gradle-discovery` when generated module/task lists are incomplete. | Refresh replaces all derived module metadata, source paths, protected build files, and task allowlists from one Gradle runtime snapshot. Module scope, operator policies, user-owned AGENTS content, and an existing commit-prefix sidecar remain preserved. |
15
15
  | Manually copied V3 files, no `.automation-plugin/manifest.json` | Finish active tasks, preserve historical evidence separately, then run `init`. | Exact files can be reused; differing managed files fail as conflicts. |
16
16
  | Healthy older manifest-managed installation | Run `doctor`, then the fixed target version's `upgrade`. | `upgrade` requires a valid installed manifest and intact original backups. |
17
17
  | Healthy current-version manifest | Run `doctor`; repeated `init` or same-version `upgrade` is verification-only and byte-idempotent. | Do not reinstall or delete the manifest. |
18
- | Damaged manifest, ordinary managed-content drift, or damaged backup content | Stop and investigate. | `init` and `upgrade` intentionally refuse to overwrite this state. AGENTS content outside its managed block and Unix-mode drift are handled by `0.9.0 upgrade`. |
18
+ | Damaged manifest, ordinary managed-content drift, or damaged backup content | Stop and investigate. | `init` and `upgrade` intentionally refuse to overwrite this state. AGENTS content outside its managed block and Unix-mode drift are handled by `1.0.0 upgrade`. |
19
19
 
20
20
  `uninstall` is not an upgrade shortcut. It restores verified pre-install files,
21
21
  removes unchanged plugin-created files, and retains drift for manual review.
@@ -35,7 +35,7 @@ removes unchanged plugin-created files, and retains drift for manual review.
35
35
  support bundle.
36
36
  5. If a managed manifest already exists, the installed version's doctor may be
37
37
  used to collect read-only evidence. A mode warning/failure or an AGENTS
38
- content mismatch does not by itself prevent `0.9.0 upgrade`; the target
38
+ content mismatch does not by itself prevent `1.0.0 upgrade`; the target
39
39
  upgrade performs its own content-safe checks. Do not edit manifest hashes to
40
40
  make doctor pass.
41
41
  6. Prove the migration in a disposable clone or temporary Android fixture
@@ -50,14 +50,14 @@ scaffold, not as an older managed installation.
50
50
  If the project OpenCode configuration contains an exact
51
51
  `@frankzhang2026/opencode-android-orchestrator@0.1.0` entry, save the file and
52
52
  remove only that obsolete entry in a reviewed Git change before running
53
- `0.9.0 init`. The merger deliberately rejects a different version of the same
53
+ `1.0.0 init`. The merger deliberately rejects a different version of the same
54
54
  managed package; it will not silently replace the reference. A global npm
55
55
  installation of `0.1.0` alone does not require project-file cleanup.
56
56
 
57
57
  After release, initialize with the fixed version:
58
58
 
59
59
  ```sh
60
- npx @frankzhang2026/opencode-android-orchestrator@0.9.0 init .
60
+ npx @frankzhang2026/opencode-android-orchestrator@1.0.0 init .
61
61
  ```
62
62
 
63
63
  New installations default to all-module scope, so multiple application modules
@@ -105,7 +105,7 @@ Use the lifecycle command selected by the active manifest:
105
105
 
106
106
  ```sh
107
107
  npx --yes --registry=https://registry.npmjs.org/ \
108
- @frankzhang2026/opencode-android-orchestrator@0.9.0 upgrade . --json
108
+ @frankzhang2026/opencode-android-orchestrator@1.0.0 upgrade . --json
109
109
  ```
110
110
 
111
111
  The command-level Registry option is useful when a company-wide npm Registry
@@ -135,7 +135,7 @@ computed includes dynamically or a company convention plugin applied
135
135
 
136
136
  ```sh
137
137
  npx --yes --registry=https://registry.npmjs.org/ \
138
- @frankzhang2026/opencode-android-orchestrator@0.9.0 upgrade . \
138
+ @frankzhang2026/opencode-android-orchestrator@1.0.0 upgrade . \
139
139
  --refresh-gradle-discovery --json
140
140
  ```
141
141
 
@@ -146,7 +146,7 @@ task report. The resulting module/path/task configuration is written through
146
146
  the normal verified upgrade transaction. Omit the flag when the installed task
147
147
  matrix was intentionally supplied with `--gradle-verification-config` and must
148
148
  remain unchanged. An explicit refresh may be rerun on an already installed
149
- `0.9.0` after the Gradle module graph changes; if its generated resources are
149
+ `1.0.0` after the Gradle module graph changes; if its generated resources are
150
150
  unchanged, the operation remains byte-idempotent.
151
151
 
152
152
  Upgrade also preserves an installed `longCommandTimeoutMs`. Installations from
@@ -158,8 +158,19 @@ through `7200000`.
158
158
  Unit-test and Android lint verification are repository policies in
159
159
  `automation/config.json`. Existing boolean values are preserved. Older
160
160
  configurations receive `unitTestsEnabled: true` and `lintEnabled: false`.
161
- After migration, change only those two values in place and commit the
162
- configuration; there are no `init` or `upgrade` flags for these policies.
161
+ After migration, change only those two values or `commitMessagePrefixMode` in
162
+ place and commit the configuration; there are no `init` or `upgrade` flags for
163
+ these policies.
164
+
165
+ Schema V5 defaults `commitMessagePrefixMode` to `required`. Upgrade from
166
+ `0.8.1` or any other earlier managed release succeeds and creates
167
+ `automation/automation-commit-prefix` only when that human-owned file is
168
+ absent. The created comments-only template is intentionally unconfigured:
169
+ before starting a new task, edit it and put the current company prefix on one
170
+ non-comment line. Do not add the prefix file to the installation manifest; it
171
+ is excluded from task diffs and preserved across later upgrades and uninstall.
172
+ If repository policy intentionally does not require a prefix, set the mode to
173
+ `disabled` in a separate reviewed configuration change.
163
174
 
164
175
  Upgrading a healthy `0.7.0` installation removes the exact managed Superpowers
165
176
  v6.2.0 plugin reference that the older Orchestrator added. Upgrade rebuilds the
@@ -183,12 +194,32 @@ The command refuses:
183
194
  Do not repair those conditions by editing the manifest or its hashes. Diagnose
184
195
  the source of drift and use the recorded recovery data.
185
196
 
197
+ ## Moving to the durable 1.0.0 queue
198
+
199
+ Finish or explicitly abort legacy active tasks before upgrading. For an existing
200
+ 1.0.0 installation, stop its background service and complete/abort retained
201
+ workspaces first. The upgrade lock shares queue arbitration so execution cannot
202
+ start while resources are being replaced. Pending inbox contracts remain in the
203
+ Git common directory through upgrade and uninstall; legacy on-disk contracts
204
+ are not silently approved or imported.
205
+
206
+ Schema V6 preserves the selected workspace strategy and defaults missing commit
207
+ policy to `humanApproval`. Old contract approvals never acquire `autoCommit`
208
+ from a changed global default. Queue execution requires full unit tests enabled;
209
+ a migrated `unitTestsEnabled: false` remains preserved but blocks queue
210
+ consumption until the operator enables and commits the setting.
211
+
212
+ Restart OpenCode after upgrading so Planner loads the new bounded intake tools
213
+ and question-receipt hooks. `/change` returns after enqueue; the background
214
+ service owns subsequent execution. Human acceptance and isolated revalidation
215
+ use the queue rather than the old direct Shell commands. See [Queue operation](QUEUE.md).
216
+
186
217
  ## Post-migration verification
187
218
 
188
219
  Run all checks from the detected Git root:
189
220
 
190
221
  ```sh
191
- npx @frankzhang2026/opencode-android-orchestrator@0.9.0 doctor .
222
+ npx @frankzhang2026/opencode-android-orchestrator@1.0.0 doctor .
192
223
  opencode debug config
193
224
  opencode debug skill
194
225
  opencode debug agent scheduled-planner
@@ -205,7 +236,9 @@ Verify all of the following before switching normal work to the plugin:
205
236
  - all three agents, five commands, three scheduled-quality skills, and five
206
237
  `android-orchestrator-*` workflow skills are discoverable;
207
238
  - both read-only custom tools resolve for the scheduled agents;
208
- - the Shell suite ends with `1..44`;
239
+ - `automation/automation-commit-prefix` contains the reviewed current prefix
240
+ when `commitMessagePrefixMode` is `required`;
241
+ - the Shell suite ends with `1..46`;
209
242
  - shadow output contains `"mutationPerformed": false`;
210
243
  - `git status --short` contains only the reviewed installation diff;
211
244
  - no Git push, launchd registration, extra candidate worktree, or copied Android
package/docs/QUEUE.md ADDED
@@ -0,0 +1,146 @@
1
+ # Queue and background execution
2
+
3
+ Version `1.0.0` stores proposals and approved contracts under
4
+ `<git-common-dir>/automation-runtime/inbox/queue.json`. A contract is runnable
5
+ only after its full plan, version, digest, target branch and commit policy are
6
+ approved and durably recorded. Planning reads a fixed `planningHead`, so another
7
+ Coder's active files and branch do not affect the proposal.
8
+
9
+ ## Normal use
10
+
11
+ Start OpenCode with `scheduled-planner` and use `/change`. Approve the displayed
12
+ proposal and the returned contract question. After enqueue, Planner returns;
13
+ you can plan and approve B or C while A is executing or awaiting acceptance.
14
+ Only the current task's plan and contract enter its working diff.
15
+
16
+ Defaults are `inPlaceExclusive` and `humanApproval`. Human tasks stop at
17
+ `AWAITING_HUMAN`; `/acceptance TASK-ID` presents the latest review and candidate
18
+ and asks a new question before requesting integration. Automatic tasks must
19
+ explicitly select `autoCommit` in their reviewed contract and proceed from
20
+ `READY_TO_COMMIT` to local commit and integration without a final question.
21
+ They never produce a fabricated human-acceptance record. Completion shows the
22
+ local commit SHA, authorization source and `pushed: false` (未推送).
23
+
24
+ | Workspace policy | Commit policy | When the next independent task may start |
25
+ | --- | --- | --- |
26
+ | `inPlaceExclusive` (default) | `humanApproval` (default) | After acceptance, local integration and directory handoff, or approved abort |
27
+ | `inPlaceExclusive` | Explicitly sealed `autoCommit` | After build, full tests, Review, local commit/integration and handoff |
28
+ | `isolatedWorktree` | `humanApproval` | After the worker and its children exit and its result is safely sealed |
29
+ | `isolatedWorktree` | `autoCommit` | Rejected; fresh compatible policy approval is required |
30
+
31
+ Both workspaces use one execution slot per Git common directory. A retained
32
+ isolated candidate keeps its own directory; revalidation and integration must
33
+ reacquire that same slot. Dependencies wait for `COMPLETED`, which means
34
+ integrated locally. Review approval and commit creation alone do not satisfy a
35
+ dependency. Fixed workspaces remain occupied during failures and human waiting.
36
+
37
+ The worker resolves the Android SDK from `ANDROID_HOME`, `ANDROID_SDK_ROOT`,
38
+ then the source repository's `local.properties` and passes the resolved location
39
+ to its shell and Gradle processes. Isolated worktrees do not copy that local file.
40
+
41
+ ## Service and scheduling
42
+
43
+ The first enqueue starts the package-owned detached service. Closing the
44
+ Planner does not stop it. Enqueue notifications, deadlines, worker completion,
45
+ startup recovery and periodic scans all use the same atomic reservation logic.
46
+ Idle scans do not call a model. No launchd or external Scheduler is registered.
47
+ The machine must be awake; a restarted service scans overdue entries once
48
+ through normal arbitration. Recurring task-template generation is not exposed
49
+ in this release; each approved contract has at most one initial execution.
50
+
51
+ `notBefore` requires an ISO timestamp with an explicit timezone, for example
52
+ `2026-09-14T22:00:00+08:00`. `dependsOn` contains previously approved task IDs.
53
+ Default ordering is FIFO; priority ranges from -100 to 100, higher first, without
54
+ preempting active work. Duplicate approval of a version returns its queue item.
55
+ To revise an unstarted approval, cancel it and approve a new draft version.
56
+ An executing version stays sealed; use a new task ID for later changes.
57
+
58
+ ```sh
59
+ opencode-android-orchestrator queue status .
60
+ opencode-android-orchestrator queue status . TASK-A
61
+ opencode-android-orchestrator queue pause .
62
+ opencode-android-orchestrator queue resume .
63
+ opencode-android-orchestrator queue priority . TASK-B 10
64
+ opencode-android-orchestrator queue cancel . TASK-C
65
+ opencode-android-orchestrator queue stop .
66
+ opencode-android-orchestrator queue start .
67
+ ```
68
+
69
+ An unsuccessful OpenCode agent process pauses consumption as a shared execution
70
+ fault; inspect its log and fix provider/environment failures before clearing it.
71
+
72
+ Pause stops new reservations. Stop terminates the scheduler while preserving
73
+ its active detached worker. Resume does not clear a fault. Notifications are
74
+ persisted until acknowledged, so the original Planner session need not remain
75
+ open. `queue --help` lists direct local-operator commands; interactive agents
76
+ use bounded plugin tools and actual question receipts instead of the CLI.
77
+
78
+ ## Policy, capacity and verification
79
+
80
+ Pause and finish/abort retained workspaces before changing repository mode:
81
+
82
+ ```sh
83
+ opencode-android-orchestrator queue pause .
84
+ opencode-android-orchestrator queue policy . isolatedWorktree humanApproval
85
+ ```
86
+
87
+ Review and commit the changed `automation/config.json` before resuming. The
88
+ queued task fixes its workspace strategy when claimed. Its commit authorization
89
+ remains exactly the approved choice: changing a default cannot grant autoCommit
90
+ to an older task. Direct configuration drift while a workspace is retained
91
+ blocks scheduling; restore the recorded strategy before recovery.
92
+
93
+ Schema V6 queue defaults are `scanIntervalMs: 5000`, `maxWorkspaces: 3` and
94
+ `maxWorkspaceBytes: 21474836480`. Capacity includes retained isolated workspaces,
95
+ including completed directories when automatic cleanup is disabled. Reaching
96
+ count or disk limits pauses new isolated execution while still accepting intake;
97
+ acceptance, recovery and cleanup of existing tasks remain eligible. Occupied or
98
+ failed directories are never deleted simply to free queue capacity.
99
+
100
+ Queued execution requires `unitTestsEnabled: true`. A temporary Gradle init
101
+ script disables up-to-date and output-cache reuse only for Test tasks, records
102
+ actual suite results and rejects missing/skipped-only evidence. The invocation
103
+ uses `--no-configuration-cache`; compilation and build caches remain usable.
104
+ It does not run `clean` or rerun all dependency tasks. Coder, Reviewer and local
105
+ integration perform the configured full suite and build gates. Evidence records
106
+ fresh-test logs, configured tasks and elapsed seconds.
107
+
108
+ ## Baselines and recovery
109
+
110
+ Before execution, changes to contract-relevant files or execution configuration
111
+ since planning require a revised contract and fresh approval. Planning files of
112
+ other completed queue tasks are not treated as execution configuration changes.
113
+ For an isolated waiting candidate whose local target advanced, request
114
+ `revalidate`; it preserves the original evidence, rebases a nonconflicting
115
+ uncommitted candidate in the same worktree, reruns build/full tests/Review and
116
+ produces a new candidate ID. Conflicts or policy changes preserve the workspace
117
+ and block progress. Old final acceptance cannot approve the new candidate.
118
+
119
+ All local commits use a persisted transaction: `INTENT`, `COMMITTED`, `VERIFIED`,
120
+ `INTEGRATED`, `COMPLETED`. Recovery checks the sealed tree, parent, target,
121
+ authorization and local refs before reusing a commit or completing handoff.
122
+ It never force-updates the target or pushes. A fixed directory is reusable only
123
+ after local integration and handoff succeed.
124
+
125
+ ```sh
126
+ opencode-android-orchestrator queue recover-lock .
127
+ opencode-android-orchestrator queue recover-execution .
128
+ opencode-android-orchestrator queue recover . TASK-A
129
+ opencode-android-orchestrator queue clear-fault .
130
+ ```
131
+
132
+ Inspect status and evidence first. Lock recovery proves the recorded owner has
133
+ exited; a heartbeat timeout alone never steals a live lock. Execution recovery
134
+ also checks the whole worker process group. If a reservation has no registered
135
+ worker, stop its recorded launcher before recovering it. Unknown ownership
136
+ retains the execution slot. `recover` is only for an existing sealed commit
137
+ transaction; baseline/Reviewer interruptions use `/resume-task` or
138
+ `/resume-review`. Running cancellation uses `/abort-task` and waits for a safe
139
+ agent boundary before archival through the execution slot. A hung external
140
+ process must be diagnosed and stopped before ownership recovery can succeed.
141
+
142
+ Upgrade and uninstall require the service stopped, no active execution, and no
143
+ retained unfinished workspace. Inbox, notifications and audit data remain in
144
+ the Git common directory. Commit-message prefix and worktree-allowlist sidecars
145
+ remain human-owned. See [Migration](MIGRATION.md), [Troubleshooting](TROUBLESHOOTING.md)
146
+ and [Security](SECURITY.md) for lifecycle and trust boundaries.
package/docs/SECURITY.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Security model
2
2
 
3
3
  This document describes the security properties of
4
- `@frankzhang2026/opencode-android-orchestrator@0.9.0`. The lifecycle foundation
4
+ `@frankzhang2026/opencode-android-orchestrator@1.0.0`. The lifecycle foundation
5
5
  completed the real OpenCode `1.14.22` and `1.15.13` release matrix in `0.2.0`;
6
- `0.9.0` retains that compatibility boundary.
6
+ `1.0.0` retains that compatibility boundary.
7
7
 
8
8
  ## Security goals and non-goals
9
9
 
@@ -38,31 +38,34 @@ perform actions outside the orchestrator's intended scope.
38
38
 
39
39
  ## Human approval boundary
40
40
 
41
- The normal workflow has three fresh OpenCode `question` selections: proposal,
42
- sealed contract, and final result. Direct chat prose, silence, a dismissed
43
- question, or a copied option label is not a normal-path approval. Baseline-only
44
- recovery and exceptional abort each have their own fresh status/question
45
- boundary.
46
-
47
- Approval phrases stored in `automation/config.json` are validation tokens, not
48
- secrets or cryptographic proof. Security depends on the scheduled planner
49
- showing the current review material, the user acting at that boundary, and the
50
- fixed Shell script independently verifying state, hashes, refs, scope, and
51
- leases. Anyone with direct shell and repository write access can invoke or
52
- modify local files; this package does not claim to protect against that actor.
53
-
54
- OpenCode permission prompts are also not semantic workflow approval. They can
55
- be accepted for the remainder of a session and may be auto-approved. For that
56
- reason `0.8.0` exposes only `android_orchestrator_status` and
57
- `android_orchestrator_doctor` as custom tools. State-changing wrappers remain a
58
- NO-GO until a one-use, non-model-forgeable receipt can bind the approval kind,
59
- task, session/message, sealed SHA or branch, time, and nonce.
41
+ Proposal and contract approval always require fresh OpenCode `question`
42
+ selections. The default `humanApproval` policy additionally requires final
43
+ candidate acceptance. Explicit `autoCommit` authorization is sealed during
44
+ contract approval and replaces only the final human question; build, actual
45
+ full unit tests and independent Review remain mandatory.
46
+
47
+ The plugin observes the host's question arguments and completed answer
48
+ metadata through the common before/after hooks. Its one-use receipt binds
49
+ session, consuming message, question call, operation, task/digest and candidate.
50
+ Changed questions, multi-select answers, ordinary chat, copied labels, another
51
+ session and already consumed receipts cannot authorize a tool mutation. A new
52
+ candidate requires a new acceptance question. Receipts expire after 15 minutes
53
+ and are lost on plugin restart; completed enqueue and consumed proof are stored
54
+ in the durable queue. Repeated enqueue cannot create a second execution.
55
+
56
+ The older mutating-wrapper NO-GO decision is superseded only by the bounded
57
+ 1.0.0 queue interfaces and these receipts. Permission prompts still do not grant
58
+ semantic workflow approval. Direct CLI use is a trusted local-operator surface;
59
+ Planner/Coder/Reviewer cannot call arbitrary CLI commands. An actor who can
60
+ modify the package, host hooks, repository or runtime files remains outside
61
+ this enforcement boundary.
60
62
 
61
63
  ## Agent and tool permissions
62
64
 
63
65
  All three installed agents start with `"*": deny` and add exact permissions.
64
- The planner can write only new planning artifacts and invoke the small set of
65
- orchestration scripts. The Coder can edit detected production/test source sets
66
+ The Planner reads committed Git objects through snapshot and writes only
67
+ the independent inbox through authenticated intake tools. It cannot directly
68
+ read/edit the active working files, run Bash or call execution scripts. The Coder can edit detected production/test source sets
66
69
  but not Gradle, OpenCode, automation, or control files. Reviewer edit access is
67
70
  denied. Subagents, Scheduler/job tools, external directories, web access, push,
68
71
  merge/rebase, destructive Git commands, shell composition, and launchd are
@@ -85,7 +88,8 @@ The read-only status tool additionally:
85
88
  Doctor invokes read-only project, dependency, SDK, and installation checks and
86
89
  returns their failures instead of repairing the project.
87
90
 
88
- The compatible `tool.execute.before` hook may only raise the timeout argument
91
+ The compatible `tool.execute.before` hook validates unattended shell commands,
92
+ records approval challenges and may raise the timeout argument
89
93
  for a fixed list of direct managed long-running scripts. Its generated config
90
94
  value is an integer from `120000` through `7200000` milliseconds, defaults to
91
95
  `1800000`, never shortens a larger caller timeout, and does not rewrite the
@@ -130,14 +134,24 @@ while Gradle settings/build files and orchestration resources remain protected.
130
134
  legacy configuration with no scope field as `primary`, preventing an implicit
131
135
  permission expansion.
132
136
 
133
- `unitTestsEnabled` and `lintEnabled` are the only operator-editable fields in
134
- the otherwise manifest-managed `automation/config.json`. Upgrade authenticates
137
+ `unitTestsEnabled`, `lintEnabled`, `commitMessagePrefixMode` and bounded
138
+ queue/workspace policies are the operator-editable fields in the otherwise manifest-managed
139
+ `automation/config.json`. Upgrade authenticates
135
140
  the remaining generated content before preserving those values, and doctor
136
141
  validates the resulting adaptive configuration. Task agents still cannot edit
137
142
  the protected file. Unit tests default on and lint defaults off; disabling unit
138
- verification does not remove the mandatory RED evidence step. Assemble, scope,
143
+ verification blocks queue consumption and does not remove the mandatory RED
144
+ evidence step for legacy non-queue tasks. Assemble, scope,
139
145
  evidence, and required device-test gates are unaffected.
140
146
 
147
+ When commit prefix mode is `required`, the regular UTF-8 sidecar
148
+ `automation/automation-commit-prefix` must contain exactly one active line.
149
+ The installer creates a comments-only template without failing installation;
150
+ normal preflight and contract execution then block until a human fills it.
151
+ The file is not manifest-managed and is excluded from worktree, evidence, and
152
+ commit pathsets. Accepted and abort-recovery commits read it from the recorded
153
+ source worktree; manual Git commits remain outside this enforcement boundary.
154
+
141
155
  The optional repository-root `.automation-worktree-allowlist` is controlled by
142
156
  the local human operator, not by task agents. It accepts at most 256 exact,
143
157
  normalized repository-relative file paths in a regular file no larger than 64
@@ -157,7 +171,7 @@ writes the target package modes.
157
171
  ## Transaction and recovery safety
158
172
 
159
173
  `init` writes original-file backups before publishing a prepared manifest. It
160
- then applies validated files, runs the 44-case transaction suite and a shadow
174
+ then applies validated files, runs the 46-case transaction suite and a shadow
161
175
  run, verifies final hashes/modes, and only then marks the manifest installed.
162
176
  Failure before completion restores originals and removes safely unchanged new
163
177
  files.
@@ -182,14 +196,15 @@ the recorded before/after hashes and Git refs.
182
196
  ## Git and orchestration invariants
183
197
 
184
198
  - The source repository must have an identifiable original branch and baseline
185
- HEAD. Original-branch drift blocks integration.
199
+ HEAD. Fixed-directory branch drift blocks integration; isolated drift
200
+ requires new full verification, independent Review and human acceptance.
186
201
  - The persistent repository lease prevents concurrent orchestrated tasks from
187
202
  sharing a mutable repository workspace.
188
203
  - Planning artifacts remain uncommitted until the verified product change is
189
204
  ready. Successful integration creates exactly one combined local commit.
190
205
  - Scope gates inspect tracked and untracked changes, reject protected paths and
191
206
  obvious test weakening, and bind the accepted result to a diff SHA.
192
- - An approved task snapshots the validated worktree allowlist. Listed local
207
+ - Workspace preparation snapshots the validated worktree allowlist. Listed local
193
208
  changes are excluded consistently from cleanliness, scope, hashes, evidence,
194
209
  archival, and commits; explicit commit pathsets preserve allowlisted staged
195
210
  entries, and rename detection cannot hide an unlisted source path. Changing
@@ -207,8 +222,9 @@ the recorded before/after hashes and Git refs.
207
222
  - Abort rejects out-of-contract/protected paths, archives the diff, and avoids
208
223
  changing the original branch ref.
209
224
 
210
- Git hooks and Git configuration remain part of the host repository's trust
211
- surface. Review them before running a workflow in an untrusted project.
225
+ Queue-controlled Git writes disable hooks and create local commit objects
226
+ from a sealed tree. Git configuration and project-executed code still remain
227
+ part of the host repository's trust surface. Review them before running a workflow in an untrusted project.
212
228
 
213
229
  ## Dependencies and network behavior
214
230
 
@@ -1,7 +1,7 @@
1
1
  # Troubleshooting
2
2
 
3
3
  Use this guide for
4
- `@frankzhang2026/opencode-android-orchestrator@0.9.0`.
4
+ `@frankzhang2026/opencode-android-orchestrator@1.0.0`.
5
5
 
6
6
  ## Start with read-only evidence
7
7
 
@@ -11,7 +11,7 @@ From the repository root, capture:
11
11
  git status --short --branch
12
12
  git rev-parse HEAD
13
13
  opencode --version
14
- npx @frankzhang2026/opencode-android-orchestrator@0.9.0 doctor . --json
14
+ npx @frankzhang2026/opencode-android-orchestrator@1.0.0 doctor . --json
15
15
  ```
16
16
 
17
17
  If installation never completed, doctor will correctly report a missing or
@@ -39,9 +39,9 @@ command-scoped override:
39
39
 
40
40
  ```sh
41
41
  npm --registry=https://registry.npmjs.org/ view \
42
- @frankzhang2026/opencode-android-orchestrator@0.9.0 version
42
+ @frankzhang2026/opencode-android-orchestrator@1.0.0 version
43
43
  npx --yes --registry=https://registry.npmjs.org/ \
44
- @frankzhang2026/opencode-android-orchestrator@0.9.0 upgrade . --json
44
+ @frankzhang2026/opencode-android-orchestrator@1.0.0 upgrade . --json
45
45
  ```
46
46
 
47
47
  This leaves the company's saved npm configuration unchanged. Use the option
@@ -66,10 +66,12 @@ Git-backed Superpowers plugin at runtime.
66
66
  | Unit tests run but should be skipped | `unitTestsEnabled` is true, which is the default. | Set it to `false` in `automation/config.json`; RED evidence remains mandatory. |
67
67
  | Lint did not run | `lintEnabled` is false, which is the default. | Set it to `true` in `automation/config.json`, commit the change, and rerun the gate. |
68
68
  | Lint runs but should be skipped | `lintEnabled` is true. | Set it to `false` in `automation/config.json` and commit the change. |
69
+ | Doctor warns that the commit prefix is unconfigured, or preflight says it is required | `commitMessagePrefixMode` defaults to `required`, and init/upgrade created a comments-only `automation/automation-commit-prefix` template. | Edit that file once and put the current company prefix on exactly one non-comment line. Do not start the task until preflight passes. |
70
+ | Commit-prefix validation reports multiple lines, whitespace, size, or a symlink | The human-owned prefix file is ambiguous or unsafe. | Replace it with a regular UTF-8 text file containing one active line of at most 256 bytes; blank and `#` comment lines are allowed. |
69
71
  | Invalid `--long-command-timeout-ms` | The value is not an integer from `120000` through `7200000`. | Use the `1800000` ms default or pass an intentional bounded value to `init`/`upgrade`; do not edit the generated config directly. |
70
72
  | Android SDK failure | No valid explicit SDK, `ANDROID_HOME`, `ANDROID_SDK_ROOT`, or `local.properties` `sdk.dir` was found. | Configure one real SDK root containing `platforms/` and `build-tools/`. Do not publish `local.properties`. |
71
73
  | Missing `git`, `jq`, `rg`, `shasum`, or Java | Required deterministic command is unavailable on `PATH`. | Install or restore the missing command, record its version, and rerun the read-only checks. |
72
- | `Bundled Orchestrator skill is unavailable` | The installed `0.9.0` package is incomplete, damaged, or loaded from an unsupported partial copy. | Reinstall the exact package, inspect its `resources/third-party/superpowers-v6.2.0/skills/` entries, restart OpenCode, and rerun `opencode debug skill`. Do not add an external Superpowers plugin as a fallback. |
74
+ | `Bundled Orchestrator skill is unavailable` | The installed `1.0.0` package is incomplete, damaged, or loaded from an unsupported partial copy. | Reinstall the exact package, inspect its `resources/third-party/superpowers-v6.2.0/skills/` entries, restart OpenCode, and rerun `opencode debug skill`. Do not add an external Superpowers plugin as a fallback. |
73
75
  | The exact Superpowers v6.2.0 plugin remains after upgrade | That entry existed in the verified pre-install OpenCode file and is therefore user-owned. | Leave it in place or remove it as a separate reviewed configuration change. Upgrade only removes the old Orchestrator-managed entry. |
74
76
 
75
77
  Version `0.6.0` always passes `--no-configuration-cache` to its temporary
@@ -85,7 +87,7 @@ silence of `./gradlew tasks --all --console=plain | rg ...` in a large build.
85
87
  For an existing installation, run:
86
88
 
87
89
  ```sh
88
- npx @frankzhang2026/opencode-android-orchestrator@0.9.0 upgrade . \
90
+ npx @frankzhang2026/opencode-android-orchestrator@1.0.0 upgrade . \
89
91
  --refresh-gradle-discovery
90
92
  ```
91
93
 
@@ -94,7 +96,7 @@ least `1800000` milliseconds. A higher timeout already supplied by the caller
94
96
  is preserved; unrelated Bash commands are unchanged. To configure one hour,
95
97
  run `upgrade . --long-command-timeout-ms 3600000` on a healthy installation.
96
98
  If a command still reports `120000 ms`, confirm that the project manifest and
97
- OpenCode plugin reference are both `0.9.0`, restart the OpenCode session so the
99
+ OpenCode plugin reference are both `1.0.0`, restart the OpenCode session so the
98
100
  plugin reloads, and rerun doctor before attempting recovery.
99
101
 
100
102
  After installation, inspect OpenCode discovery separately:
@@ -149,7 +151,7 @@ Common fail-closed codes include:
149
151
  | `PLUGIN_VERSION_CONFLICT` | The same managed package identity has another reference/version. | Review and remove or migrate only the obsolete entry; never let init silently replace it. |
150
152
  | `DUPLICATE_PLUGIN` or `DUPLICATE_PROPERTY` | Configuration identity is ambiguous. | Correct the JSON/JSONC structure without discarding unrelated fields or comments. |
151
153
  | `INVALID_JSONC` or `ROOT_NOT_OBJECT` | OpenCode configuration cannot be merged safely. | Repair the user-owned file and validate it before retrying. |
152
- | `AGENTS_BLOCK_CONFLICT` or `AGENTS_MARKERS_INVALID` | During `init`, the bounded block was modified; or a lifecycle command found partial, out-of-order, or duplicate markers. | Keep project-specific instructions outside one valid marker pair. `0.9.0 upgrade` preserves marker-external changes and replaces the old managed block; malformed marker structure still requires manual repair. |
154
+ | `AGENTS_BLOCK_CONFLICT` or `AGENTS_MARKERS_INVALID` | During `init`, the bounded block was modified; or a lifecycle command found partial, out-of-order, or duplicate markers. | Keep project-specific instructions outside one valid marker pair. `1.0.0 upgrade` preserves marker-external changes and replaces the old managed block; malformed marker structure still requires manual repair. |
153
155
  | `FILE_SYMLINK`, `TARGET_SYMLINK`, or `CONFIG_SYMLINK` | A managed target or ancestor is a symbolic link. | Replace it only after understanding ownership and destination. The installer intentionally does not follow it. |
154
156
  | `PLAN_STALE` or `TARGET_MODIFIED` | A file changed between planning and application. | Stop concurrent edits, inspect the diff, and rerun from a stable state. |
155
157
 
@@ -168,8 +170,8 @@ configuration.
168
170
  | --- | --- | --- |
169
171
  | `MANIFEST_MISSING`, `MANIFEST_INVALID`, or `MANIFEST_STATE` | No trustworthy installed manifest is available. | Do not invent a manifest or copy one from another project. Determine whether this is an uninstalled/manual setup or an interrupted transaction. |
170
172
  | `EXISTING_INSTALLATION_DIFFERENT` | `init` found another installed inventory/version. | Use `upgrade` for a healthy older manifest. |
171
- | `EXISTING_INSTALLATION_INVALID` or `INSTALLATION_INVALID` | Manifest, installed files, or required backups failed structural or content validation. In `0.8.0`, this also reported an active manifest whose mode was not exactly `0600`. | Preserve the project and `.automation-plugin/`; use `0.9.0 upgrade` for mode-only drift, and inspect other doctor details or recovery history. |
172
- | `INSTALLED_FILES_MODIFIED` | Upgrade found content/existence drift in an ordinary managed file or missing/modified backup content. | Move intentional customization out of ordinary managed paths or choose manual recovery. `0.9.0` separately merges user-owned `AGENTS.md` content and does not reject mode-only drift. |
173
+ | `EXISTING_INSTALLATION_INVALID` or `INSTALLATION_INVALID` | Manifest, installed files, or required backups failed structural or content validation. In `0.8.0`, this also reported an active manifest whose mode was not exactly `0600`. | Preserve the project and `.automation-plugin/`; use `1.0.0 upgrade` for mode-only drift, and inspect other doctor details or recovery history. |
174
+ | `INSTALLED_FILES_MODIFIED` | Upgrade found content/existence drift in an ordinary managed file or missing/modified backup content. | Move intentional customization out of ordinary managed paths or choose manual recovery. `1.0.0` separately merges user-owned `AGENTS.md` content and does not reject mode-only drift. |
173
175
  | `VERSION_DOWNGRADE_REFUSED` | Target package is older than the installed manifest. | Use a newer fixed package version; never edit the manifest version. |
174
176
  | `UPGRADE_IN_PROGRESS` or `UNINSTALL_IN_PROGRESS` | `.automation-plugin/upgrade.json` or `uninstall.json` records an unfinished transaction. | Inspect the marker and matching recovery directory. Do not delete the marker merely to retry. |
175
177
  | `POST_UPGRADE_VERIFICATION_FAILED` | New resources failed verification. | The implementation attempts a complete old-version rollback; verify the old manifest and inspect upgrade evidence. |
@@ -180,7 +182,7 @@ configuration.
180
182
  Installer control paths are:
181
183
 
182
184
  - active manifest: `.automation-plugin/manifest.json` (new manifests are
183
- written as `0600`; mode-only drift does not block `0.9.0 upgrade`);
185
+ written as `0600`; mode-only drift does not block `1.0.0 upgrade`);
184
186
  - first-install/original backups: `.automation-plugin/backups/<id>/`;
185
187
  - upgrade marker and snapshots: `.automation-plugin/upgrade.json` and
186
188
  `.automation-plugin/upgrades/<id>/`;
@@ -234,6 +236,29 @@ identify the state, workspace, original branch, sealed diff, and evidence.
234
236
  - `TEST_FAILED` or `NEEDS_HUMAN`: inspect the contract and evidence. Do not
235
237
  broaden scope or silently queue the same task again.
236
238
 
239
+ ## Durable queue failures in 1.0.0
240
+
241
+ Start with `opencode-android-orchestrator queue status .` and the task's detailed
242
+ status. The queue and commit transaction are authoritative; an old Planner
243
+ session or a missing notification is not evidence that a task never started.
244
+
245
+ | Symptom | Recovery |
246
+ | --- | --- |
247
+ | Fresh matching question receipt required | Show a new queue review/draft question and select it in the same Planner session; do not paste its approval label into chat. |
248
+ | Waiting for human confirmation or fixed workspace | Accept the current candidate or use the approved abort workflow; further contracts may still be enqueued. |
249
+ | Isolated capacity reached | Integrate or explicitly archive retained workspaces; do not delete failed work simply to advance the queue. |
250
+ | Execution launch ownership unknown | Stop the recorded launcher, prove it exited, then use `queue recover-execution .`; preserve any partial workspace. |
251
+ | Dead transaction owner | Inspect the lock record and use explicit `queue recover-lock .`; a live PID or surviving child process blocks takeover. |
252
+ | OpenCode process failure | Inspect the current agent log, repair provider/environment access, then clear the fault while idle. Resume alone does not clear it. |
253
+ | Local commit already exists but task is blocked | Use `queue recover . TASK-ID`; it reuses the sealed transaction instead of creating another visible commit. |
254
+ | Target advanced for an isolated candidate | Request `revalidate`, wait for fresh full tests/Review, and confirm the new candidate. |
255
+ | Upgrade/uninstall reports a retained workspace | Stop scheduling and finish or approve abort before replacing runtime resources. |
256
+
257
+ The service launches the packaged queue entry with Node.js, independently of the
258
+ OpenCode/Bun executable. Ensure `node` is on the service's inherited `PATH`.
259
+ There is no model polling while idle and no launchd registration. After reboot,
260
+ start the service or enqueue a contract to resume durable scanning.
261
+
237
262
  ## Actions to avoid
238
263
 
239
264
  Never use a troubleshooting shortcut that destroys the evidence needed to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frankzhang2026/opencode-android-orchestrator",
3
- "version": "0.9.0",
3
+ "version": "1.0.0",
4
4
  "description": "Reusable OpenCode orchestration for Android projects",
5
5
  "license": "MIT",
6
6
  "author": "frankzhang2026",