@frankzhang2026/opencode-android-orchestrator 0.1.0 → 0.3.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.
- package/CHANGELOG.md +92 -2
- package/LICENSE +21 -0
- package/README.md +402 -6
- package/THIRD_PARTY_NOTICES.md +119 -0
- package/dist/cli.js +360 -1
- package/dist/cli.js.map +1 -1
- package/dist/compatibility/hooks.d.ts +23 -0
- package/dist/compatibility/hooks.d.ts.map +1 -0
- package/dist/compatibility/hooks.js +44 -0
- package/dist/compatibility/hooks.js.map +1 -0
- package/dist/compatibility/versions.d.ts +19 -0
- package/dist/compatibility/versions.d.ts.map +1 -1
- package/dist/compatibility/versions.js +116 -0
- package/dist/compatibility/versions.js.map +1 -1
- package/dist/doctor/index.d.ts +36 -0
- package/dist/doctor/index.d.ts.map +1 -0
- package/dist/doctor/index.js +289 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/installation.d.ts +4 -0
- package/dist/doctor/installation.d.ts.map +1 -0
- package/dist/doctor/installation.js +497 -0
- package/dist/doctor/installation.js.map +1 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/dist/installer/adaptive-templates.d.ts +78 -0
- package/dist/installer/adaptive-templates.d.ts.map +1 -0
- package/dist/installer/adaptive-templates.js +233 -0
- package/dist/installer/adaptive-templates.js.map +1 -0
- package/dist/installer/agents-config.d.ts +19 -0
- package/dist/installer/agents-config.d.ts.map +1 -0
- package/dist/installer/agents-config.js +147 -0
- package/dist/installer/agents-config.js.map +1 -0
- package/dist/installer/android-project.d.ts +36 -0
- package/dist/installer/android-project.d.ts.map +1 -0
- package/dist/installer/android-project.js +418 -0
- package/dist/installer/android-project.js.map +1 -0
- package/dist/installer/index.d.ts +8 -0
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +8 -1
- package/dist/installer/index.js.map +1 -1
- package/dist/installer/init.d.ts +68 -0
- package/dist/installer/init.d.ts.map +1 -0
- package/dist/installer/init.js +398 -0
- package/dist/installer/init.js.map +1 -0
- package/dist/installer/install-manifest.d.ts +132 -0
- package/dist/installer/install-manifest.d.ts.map +1 -0
- package/dist/installer/install-manifest.js +1047 -0
- package/dist/installer/install-manifest.js.map +1 -0
- package/dist/installer/opencode-config.d.ts +32 -0
- package/dist/installer/opencode-config.d.ts.map +1 -0
- package/dist/installer/opencode-config.js +302 -0
- package/dist/installer/opencode-config.js.map +1 -0
- package/dist/installer/uninstall.d.ts +70 -0
- package/dist/installer/uninstall.d.ts.map +1 -0
- package/dist/installer/uninstall.js +770 -0
- package/dist/installer/uninstall.js.map +1 -0
- package/dist/installer/upgrade.d.ts +101 -0
- package/dist/installer/upgrade.d.ts.map +1 -0
- package/dist/installer/upgrade.js +1140 -0
- package/dist/installer/upgrade.js.map +1 -0
- package/dist/opencode-plugin.d.ts +2 -0
- package/dist/opencode-plugin.d.ts.map +1 -0
- package/dist/opencode-plugin.js +4 -0
- package/dist/opencode-plugin.js.map +1 -0
- package/dist/plugin/index.d.ts +7 -2
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +23 -6
- package/dist/plugin/index.js.map +1 -1
- package/dist/tools/index.d.ts +35 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +197 -1
- package/dist/tools/index.js.map +1 -1
- package/docs/MIGRATION.md +184 -0
- package/docs/SECURITY.md +219 -0
- package/docs/TROUBLESHOOTING.md +171 -0
- package/package.json +23 -5
- package/templates/.opencode/agents/scheduled-coder.md +115 -0
- package/templates/.opencode/agents/scheduled-planner.md +166 -0
- package/templates/.opencode/agents/scheduled-reviewer.md +88 -0
- package/templates/.opencode/commands/abort-task.md +20 -0
- package/templates/.opencode/commands/acceptance.md +20 -0
- package/templates/.opencode/commands/change.md +23 -0
- package/templates/.opencode/commands/resume-review.md +19 -0
- package/templates/.opencode/skills/scheduled-quality-coder/SKILL.md +93 -0
- package/templates/.opencode/skills/scheduled-quality-orchestrator/SKILL.md +216 -0
- package/templates/.opencode/skills/scheduled-quality-reviewer/SKILL.md +68 -0
- package/templates/AGENTS.md.fragment +19 -0
- package/templates/README.md +55 -9
- package/templates/automation/config.json +67 -0
- package/templates/automation/config.schema.json +194 -0
- package/templates/automation/task-contract.schema.json +92 -0
- package/templates/automation/tasks/TASK-TEMPLATE.json.example +56 -0
- package/templates/docs/plans/README.md +26 -0
- package/templates/installation-manifest.schema.json +201 -0
- package/templates/scripts/automation/abort-task.sh +171 -0
- package/templates/scripts/automation/accept-and-integrate.sh +263 -0
- package/templates/scripts/automation/acceptance-report.sh +132 -0
- package/templates/scripts/automation/approve-and-run.sh +175 -0
- package/templates/scripts/automation/begin-review.sh +18 -0
- package/templates/scripts/automation/block-task.sh +26 -0
- package/templates/scripts/automation/claim-task.sh +74 -0
- package/templates/scripts/automation/integration-scope-gate.sh +103 -0
- package/templates/scripts/automation/lib.sh +815 -0
- package/templates/scripts/automation/orchestrate-task.sh +119 -0
- package/templates/scripts/automation/preflight.sh +206 -0
- package/templates/scripts/automation/prepare-contract-review.sh +101 -0
- package/templates/scripts/automation/quality-gate.sh +72 -0
- package/templates/scripts/automation/queue-task.sh +35 -0
- package/templates/scripts/automation/record-red.sh +55 -0
- package/templates/scripts/automation/resume-review-fix.sh +32 -0
- package/templates/scripts/automation/resume-review.sh +120 -0
- package/templates/scripts/automation/scope-gate.sh +110 -0
- package/templates/scripts/automation/select-task.sh +34 -0
- package/templates/scripts/automation/shadow-run.sh +24 -0
- package/templates/scripts/automation/show-acceptance-review.sh +111 -0
- package/templates/scripts/automation/status.sh +125 -0
- package/templates/scripts/automation/submit-review.sh +73 -0
- package/templates/scripts/automation/tests/run-tests.sh +716 -0
- package/templates/scripts/automation/transition-state.sh +21 -0
- package/templates/scripts/automation/validate-contract.sh +98 -0
- package/templates/scripts/automation/verify-integration.sh +38 -0
- package/templates/scripts/automation/verify-task.sh +39 -0
package/docs/SECURITY.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Security model
|
|
2
|
+
|
|
3
|
+
This document describes the security properties of
|
|
4
|
+
`@frankzhang2026/opencode-android-orchestrator@0.3.0`. The lifecycle foundation
|
|
5
|
+
completed the real OpenCode `1.14.22` and `1.15.13` release matrix in `0.2.0`;
|
|
6
|
+
`0.3.0` retains that compatibility boundary.
|
|
7
|
+
|
|
8
|
+
## Security goals and non-goals
|
|
9
|
+
|
|
10
|
+
The orchestrator is designed to reduce accidental or model-initiated scope
|
|
11
|
+
expansion in a local Android repository. It aims to:
|
|
12
|
+
|
|
13
|
+
- keep human proposal, contract, and final-result approval explicit;
|
|
14
|
+
- constrain Coder edits to contract-approved Android source/test paths;
|
|
15
|
+
- keep Reviewer read-only;
|
|
16
|
+
- authenticate packaged and installed orchestration resources;
|
|
17
|
+
- preserve original files and recover complete installer transactions;
|
|
18
|
+
- block silent overwrites, unsafe symlinks, stale plans, branch drift, pushes,
|
|
19
|
+
unbounded retries, and Scheduler/launchd registration;
|
|
20
|
+
- create one local product-and-planning commit only after sealed verification.
|
|
21
|
+
|
|
22
|
+
It is not a privilege boundary against a malicious local user, a compromised
|
|
23
|
+
OpenCode binary/provider, a compromised npm/Git dependency, or another process
|
|
24
|
+
running as the same operating-system account. It does not sandbox Gradle,
|
|
25
|
+
OpenCode, Java, Git hooks, or project tests. A hostile build script or test can
|
|
26
|
+
perform actions outside the orchestrator's intended scope.
|
|
27
|
+
|
|
28
|
+
## Trust boundaries
|
|
29
|
+
|
|
30
|
+
| Boundary | Trusted input | Untrusted or separately verified input |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| Package installation | The exact reviewed npm tarball and its pinned version | Existing project files, paths, modes, symlinks, and concurrent edits |
|
|
33
|
+
| OpenCode interaction | A fresh single-choice result handled by the scheduled planner | Ordinary chat text, command arguments, and model-generated approval phrases |
|
|
34
|
+
| Product implementation | The sealed task contract, baseline HEAD, allowed paths, and deterministic scripts | Coder summaries and any unsealed worktree change |
|
|
35
|
+
| Review | The approved contract and independently recomputed diff/evidence | Coder claims and stale report content |
|
|
36
|
+
| Integration | Task ID, repository lease, sealed diff SHA, approved review, original branch/ref, and fresh acceptance | Branch drift, manual commits, changed worktrees, or a reused acceptance package |
|
|
37
|
+
| Recovery | Manifest, markers, hashes, modes, original backups, snapshots, and Git refs | Guessed cleanup steps or copied state from another repository |
|
|
38
|
+
|
|
39
|
+
## Human approval boundary
|
|
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. Exceptional
|
|
44
|
+
abort has its own fresh status display and confirmation flow.
|
|
45
|
+
|
|
46
|
+
Approval phrases stored in `automation/config.json` are validation tokens, not
|
|
47
|
+
secrets or cryptographic proof. Security depends on the scheduled planner
|
|
48
|
+
showing the current review material, the user acting at that boundary, and the
|
|
49
|
+
fixed Shell script independently verifying state, hashes, refs, scope, and
|
|
50
|
+
leases. Anyone with direct shell and repository write access can invoke or
|
|
51
|
+
modify local files; this package does not claim to protect against that actor.
|
|
52
|
+
|
|
53
|
+
OpenCode permission prompts are also not semantic workflow approval. They can
|
|
54
|
+
be accepted for the remainder of a session and may be auto-approved. For that
|
|
55
|
+
reason `0.3.0` exposes only `android_orchestrator_status` and
|
|
56
|
+
`android_orchestrator_doctor` as custom tools. State-changing wrappers remain a
|
|
57
|
+
NO-GO until a one-use, non-model-forgeable receipt can bind the approval kind,
|
|
58
|
+
task, session/message, sealed SHA or branch, time, and nonce.
|
|
59
|
+
|
|
60
|
+
## Agent and tool permissions
|
|
61
|
+
|
|
62
|
+
All three installed agents start with `"*": deny` and add exact permissions.
|
|
63
|
+
The planner can write only new planning artifacts and invoke the small set of
|
|
64
|
+
orchestration scripts. The Coder can edit detected production/test source sets
|
|
65
|
+
but not Gradle, OpenCode, automation, or control files. Reviewer edit access is
|
|
66
|
+
denied. Subagents, Scheduler/job tools, external directories, web access, push,
|
|
67
|
+
merge/rebase, destructive Git commands, shell composition, and launchd are
|
|
68
|
+
denied where applicable.
|
|
69
|
+
|
|
70
|
+
Permissions are defense in depth, not a substitute for script checks. The
|
|
71
|
+
source preflight resolves each agent and verifies its effective high-risk
|
|
72
|
+
permissions and custom-tool discovery.
|
|
73
|
+
|
|
74
|
+
The read-only status tool additionally:
|
|
75
|
+
|
|
76
|
+
- validates `TASK-[A-Z0-9-]+` at Schema and execution time;
|
|
77
|
+
- binds execution to the worktree that loaded the plugin;
|
|
78
|
+
- authenticates the installation manifest, managed resources, and executable
|
|
79
|
+
modes before running anything;
|
|
80
|
+
- invokes only the fixed `scripts/automation/status.sh` path with separate
|
|
81
|
+
shell expressions;
|
|
82
|
+
- rejects a failed command, malformed/mismatched JSON, or output above 1 MiB.
|
|
83
|
+
|
|
84
|
+
Doctor invokes read-only project, dependency, SDK, and installation checks and
|
|
85
|
+
returns their failures instead of repairing the project.
|
|
86
|
+
|
|
87
|
+
## Filesystem and configuration safety
|
|
88
|
+
|
|
89
|
+
The installer never follows a symbolic link at a managed file or required
|
|
90
|
+
ancestor. Paths must be relative, normalized, unique, within the detected Git
|
|
91
|
+
root, and regular files where required. Existing content, size, and effective
|
|
92
|
+
mode are captured during planning and rechecked before the first write. A stale
|
|
93
|
+
or tampered plan fails closed.
|
|
94
|
+
|
|
95
|
+
Installation strategies are deliberately distinct:
|
|
96
|
+
|
|
97
|
+
- `copy` and `generate` accept a missing target or an exact content/mode match;
|
|
98
|
+
any differing existing file is a conflict;
|
|
99
|
+
- `merge` accepts only output produced by the structure-aware OpenCode JSON/JSONC
|
|
100
|
+
or bounded AGENTS merge planner;
|
|
101
|
+
- no lifecycle command has a force-overwrite flag.
|
|
102
|
+
|
|
103
|
+
OpenCode JSON/JSONC merging preserves unrelated fields, comments, order, and
|
|
104
|
+
plugin options. It rejects malformed/ambiguous files, duplicate identities,
|
|
105
|
+
different managed-plugin versions, and symlinks. AGENTS merging owns only one
|
|
106
|
+
marked block and rejects partial, duplicate, or modified markers.
|
|
107
|
+
|
|
108
|
+
New installations generate task examples in `all` module scope: every detected
|
|
109
|
+
Android module's `src/main`, `src/test`, and `src/androidTest` path is eligible,
|
|
110
|
+
while Gradle settings/build files and orchestration resources remain protected.
|
|
111
|
+
`primary` scope narrows the generated paths to one module. Upgrade treats a
|
|
112
|
+
legacy configuration with no scope field as `primary`, preventing an implicit
|
|
113
|
+
permission expansion.
|
|
114
|
+
|
|
115
|
+
The installed manifest is `0600`. Installer control, backup, recovery, and
|
|
116
|
+
history directories are created with private `0700` defaults; backup files
|
|
117
|
+
preserve the original file mode where recovery requires it. Shell resources
|
|
118
|
+
must be exact packaged bytes with `0755`; other copied templates are
|
|
119
|
+
non-executable.
|
|
120
|
+
|
|
121
|
+
## Transaction and recovery safety
|
|
122
|
+
|
|
123
|
+
`init` writes original-file backups before publishing a prepared manifest. It
|
|
124
|
+
then applies validated files, runs the 38-case transaction suite and a shadow
|
|
125
|
+
run, verifies final hashes/modes, and only then marks the manifest installed.
|
|
126
|
+
Failure before completion restores originals and removes safely unchanged new
|
|
127
|
+
files.
|
|
128
|
+
|
|
129
|
+
`upgrade` requires a healthy installed manifest and original backups. It saves
|
|
130
|
+
the exact old manifest and immediate pre-upgrade snapshots, reconstructs merge
|
|
131
|
+
targets from first-install originals, writes the new version, and replaces the
|
|
132
|
+
manifest only after verification. Failure attempts a whole-version rollback.
|
|
133
|
+
|
|
134
|
+
`uninstall` restores an original or removes a plugin-created path only when the
|
|
135
|
+
current path still matches a safe known state. Content, permission, deletion,
|
|
136
|
+
or existence drift is retained and reported. Before changes it saves the
|
|
137
|
+
active manifest and every affected installed file. Failure before commit
|
|
138
|
+
attempts to restore the installed state.
|
|
139
|
+
|
|
140
|
+
An `*_ROLLBACK_FAILED` result is a hard stop. Do not delete markers or recovery
|
|
141
|
+
data and do not guess at partial cleanup. Preserve the repository and inspect
|
|
142
|
+
the recorded before/after hashes and Git refs.
|
|
143
|
+
|
|
144
|
+
## Git and orchestration invariants
|
|
145
|
+
|
|
146
|
+
- The source repository must have an identifiable original branch and baseline
|
|
147
|
+
HEAD. Original-branch drift blocks integration.
|
|
148
|
+
- The persistent repository lease prevents concurrent orchestrated tasks from
|
|
149
|
+
sharing a mutable repository workspace.
|
|
150
|
+
- Planning artifacts remain uncommitted until the verified product change is
|
|
151
|
+
ready. Successful integration creates exactly one combined local commit.
|
|
152
|
+
- Scope gates inspect tracked and untracked changes, reject protected paths and
|
|
153
|
+
obvious test weakening, and bind the accepted result to a diff SHA.
|
|
154
|
+
- Integration reruns verification before a fast-forward. It never pushes.
|
|
155
|
+
- A successfully integrated task branch is deleted only after the original
|
|
156
|
+
branch reaches the verified commit. Failure preserves the branch for
|
|
157
|
+
recovery.
|
|
158
|
+
- Abort rejects out-of-contract/protected paths, archives the diff, and avoids
|
|
159
|
+
changing the original branch ref.
|
|
160
|
+
|
|
161
|
+
Git hooks and Git configuration remain part of the host repository's trust
|
|
162
|
+
surface. Review them before running a workflow in an untrusted project.
|
|
163
|
+
|
|
164
|
+
## Dependencies and network behavior
|
|
165
|
+
|
|
166
|
+
Use fixed package references. The installer adds the exact orchestrator
|
|
167
|
+
version and the configured pinned Superpowers Git tag; it does not use
|
|
168
|
+
`latest`. The package is compiled against `@opencode-ai/plugin@1.14.22` and
|
|
169
|
+
declares the bounded peer range `>=1.14.22 <1.16.0`.
|
|
170
|
+
|
|
171
|
+
The orchestrator does not contain a telemetry uploader and the deterministic
|
|
172
|
+
Shell flow forbids Git push. Network activity can still occur outside that
|
|
173
|
+
code when npm/npx downloads a package, OpenCode resolves a pinned plugin,
|
|
174
|
+
OpenCode contacts the configured model provider, or project build/test tooling
|
|
175
|
+
uses the network. Apply the host organization's normal npm, Git, OpenCode,
|
|
176
|
+
provider, proxy, certificate, and dependency-review policy.
|
|
177
|
+
|
|
178
|
+
## Secrets and retained evidence
|
|
179
|
+
|
|
180
|
+
Installed agents deny reads of `.env`, `.env.*`, `local.properties`, `*.jks`,
|
|
181
|
+
and `*.keystore`. Do not put secrets in task descriptions, plans, source code,
|
|
182
|
+
test output, commit messages, model prompts, or approval summaries.
|
|
183
|
+
|
|
184
|
+
The following may contain sensitive source, paths, branch names, test logs,
|
|
185
|
+
diffs, or review findings:
|
|
186
|
+
|
|
187
|
+
- `.git/automation-runtime/evidence/`;
|
|
188
|
+
- `.git/automation-runtime/workspaces/` and state/transition records;
|
|
189
|
+
- `.automation-plugin/backups/`, `upgrades/`, `uninstalls/`, and `history/`;
|
|
190
|
+
- generated acceptance, abort, integration, and rollback evidence.
|
|
191
|
+
|
|
192
|
+
These paths are excluded from package templates but remain local audit data.
|
|
193
|
+
Keep repository and filesystem access appropriately restricted. Redact user
|
|
194
|
+
names, absolute paths, proprietary source/diffs, provider details, tokens, SDK
|
|
195
|
+
paths, and signing information before sharing a diagnostic bundle. Do not
|
|
196
|
+
commit installer recovery data unless an explicit internal policy requires it.
|
|
197
|
+
|
|
198
|
+
## Residual risks
|
|
199
|
+
|
|
200
|
+
- Hashes prove byte identity against the running package; they do not prove the
|
|
201
|
+
package itself is trustworthy. Review the tarball and its provenance.
|
|
202
|
+
- A same-user process can race filesystem or Git state around checks. The
|
|
203
|
+
implementation rechecks critical snapshots and locks cooperative workflows,
|
|
204
|
+
but it is not an operating-system sandbox.
|
|
205
|
+
- Gradle tests, Git hooks, OpenCode, model providers, and third-party plugins
|
|
206
|
+
execute outside this package's file planner and may have broader behavior.
|
|
207
|
+
- `inPlaceExclusive` intentionally switches the current worktree to a task
|
|
208
|
+
branch. Use the explicitly configured isolated-worktree strategy only after
|
|
209
|
+
validating its storage and cleanup policy.
|
|
210
|
+
- Recovery evidence improves auditability but increases local sensitive-data
|
|
211
|
+
retention.
|
|
212
|
+
- Real dual-version end-to-end acceptance and a clean install from the final
|
|
213
|
+
tarball remain mandatory release gates.
|
|
214
|
+
|
|
215
|
+
When reporting a suspected security problem, preserve exact versions, error
|
|
216
|
+
codes, hashes, and redacted evidence. Do not publish credentials, proprietary
|
|
217
|
+
diffs, recovery archives, or exploit details that would expose another
|
|
218
|
+
project. See [Troubleshooting](TROUBLESHOOTING.md) for safe first-response
|
|
219
|
+
commands.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Use this guide for
|
|
4
|
+
`@frankzhang2026/opencode-android-orchestrator@0.3.0`.
|
|
5
|
+
|
|
6
|
+
## Start with read-only evidence
|
|
7
|
+
|
|
8
|
+
From the repository root, capture:
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
git status --short --branch
|
|
12
|
+
git rev-parse HEAD
|
|
13
|
+
opencode --version
|
|
14
|
+
npx @frankzhang2026/opencode-android-orchestrator@0.3.0 doctor . --json
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
If installation never completed, doctor will correctly report a missing or
|
|
18
|
+
invalid installed manifest. Preserve the complete error code and details from
|
|
19
|
+
the command that failed. Do not rerun a write command repeatedly while the
|
|
20
|
+
working tree or installer control state is changing.
|
|
21
|
+
|
|
22
|
+
The CLI uses these exit codes:
|
|
23
|
+
|
|
24
|
+
| Exit code | Meaning |
|
|
25
|
+
| ---: | --- |
|
|
26
|
+
| `0` | Command completed, or doctor found no failed check. Doctor warnings are allowed. |
|
|
27
|
+
| `1` | A lifecycle operation failed, or doctor found at least one failed check. |
|
|
28
|
+
| `2` | Unknown command or invalid CLI arguments. |
|
|
29
|
+
|
|
30
|
+
`doctor --json` always emits a structured report. The `--json` option on
|
|
31
|
+
`init`, `upgrade`, and `uninstall` structures successful results; thrown errors
|
|
32
|
+
remain human-readable on stderr with a stable code such as `[FILE_CONFLICT]`.
|
|
33
|
+
|
|
34
|
+
## Prerequisite and discovery failures
|
|
35
|
+
|
|
36
|
+
| Symptom | Likely cause | Safe response |
|
|
37
|
+
| --- | --- | --- |
|
|
38
|
+
| `DOCTOR_FAILED` before any write | One or more required project/tool checks failed. | Read each failed doctor check; fix only the named prerequisite, then rerun doctor or init. |
|
|
39
|
+
| OpenCode version failure | Installed version is below `1.14.22`, at or above `1.16.0`, or cannot be parsed/executed. | Install a certified version (`1.14.22` or `1.15.13`) for release validation. Do not bypass the version gate. |
|
|
40
|
+
| Git root or Android project not detected | The target is outside a Git repository, settings are missing, or no supported Android module was found. | Run from the intended repository/module and inspect `settings.gradle` or `settings.gradle.kts`. Nested Gradle roots are intentionally unsupported. |
|
|
41
|
+
| Gradle Wrapper failure | `gradlew` or `gradle/wrapper/gradle-wrapper.properties` is missing, or `gradlew` is not executable. | Restore the project's reviewed Wrapper files. Do not let the installer generate or replace build configuration. |
|
|
42
|
+
| `MODULE_SCOPE_INVALID` or an invalid `--module-scope` argument | The value is not `all` or `primary`. | Use `all` for the default all-module contract or `primary` for an intentional single-module restriction. |
|
|
43
|
+
| `PRIMARY_MODULE_AMBIGUOUS` | Restrictive `primary` scope has multiple possible Android modules. | Supply an exact Gradle path, for example `--module-scope primary --primary-module :mobile`, or use the default `all` scope. |
|
|
44
|
+
| `PRIMARY_MODULE_NOT_FOUND` | The selected Gradle path was not detected. | Use a module path reported by doctor/project detection; do not pass a filesystem directory. |
|
|
45
|
+
| 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`. |
|
|
46
|
+
| 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. |
|
|
47
|
+
|
|
48
|
+
After installation, inspect OpenCode discovery separately:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
opencode debug config
|
|
52
|
+
opencode debug skill
|
|
53
|
+
opencode debug agent scheduled-planner
|
|
54
|
+
opencode debug agent scheduled-coder
|
|
55
|
+
opencode debug agent scheduled-reviewer
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Then run `./scripts/automation/preflight.sh --source`. It validates pinned
|
|
59
|
+
plugins, required skills, agent permissions, and both read-only custom tools.
|
|
60
|
+
If it fails, preserve its exact output. Do not broaden an agent's default-deny
|
|
61
|
+
permissions to make discovery pass.
|
|
62
|
+
|
|
63
|
+
## Installation conflicts
|
|
64
|
+
|
|
65
|
+
Common fail-closed codes include:
|
|
66
|
+
|
|
67
|
+
| Code | Meaning | Response |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `FILE_CONFLICT` | Existing content or mode differs from a `copy`/`generate` target. | Compare the named path with the packaged template. Preserve local policy elsewhere or restore the audited file deliberately; there is no force flag. |
|
|
70
|
+
| `AMBIGUOUS_CONFIG` | Both `opencode.json` and `opencode.jsonc` exist. | Select and consolidate the user-owned configuration in a separate reviewed change. |
|
|
71
|
+
| `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. |
|
|
72
|
+
| `DUPLICATE_PLUGIN` or `DUPLICATE_PROPERTY` | Configuration identity is ambiguous. | Correct the JSON/JSONC structure without discarding unrelated fields or comments. |
|
|
73
|
+
| `INVALID_JSONC` or `ROOT_NOT_OBJECT` | OpenCode configuration cannot be merged safely. | Repair the user-owned file and validate it before retrying. |
|
|
74
|
+
| `AGENTS_BLOCK_CONFLICT` or `AGENTS_MARKERS_INVALID` | The bounded managed block is modified, partial, or duplicated. | Restore one exact managed block; keep project-specific instructions outside its markers. |
|
|
75
|
+
| `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. |
|
|
76
|
+
| `PLAN_STALE` or `TARGET_MODIFIED` | A file changed between planning and application. | Stop concurrent edits, inspect the diff, and rerun from a stable state. |
|
|
77
|
+
|
|
78
|
+
An init verification failure reports `POST_INSTALL_VERIFICATION_FAILED` and
|
|
79
|
+
automatically rolls back the prepared installation. Confirm the original files
|
|
80
|
+
and inspect `.automation-plugin/history/`; do not assume a failed init left a
|
|
81
|
+
usable installation.
|
|
82
|
+
|
|
83
|
+
## Manifest, upgrade, and uninstall failures
|
|
84
|
+
|
|
85
|
+
Run doctor before deciding on recovery. Its installation section distinguishes
|
|
86
|
+
manifest identity, content drift, permission drift, backups, and semantic
|
|
87
|
+
configuration.
|
|
88
|
+
|
|
89
|
+
| Code or check | Meaning | Response |
|
|
90
|
+
| --- | --- | --- |
|
|
91
|
+
| `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. |
|
|
92
|
+
| `EXISTING_INSTALLATION_DIFFERENT` | `init` found another installed inventory/version. | Use `upgrade` for a healthy older manifest. |
|
|
93
|
+
| `EXISTING_INSTALLATION_INVALID` or `INSTALLATION_INVALID` | Manifest, installed files, or required backups failed validation. | Preserve the project and `.automation-plugin/`; inspect doctor details and recovery history. |
|
|
94
|
+
| `INSTALLED_FILES_MODIFIED` | Upgrade found content, existence, mode, or backup drift. | Move intentional customization out of managed paths or choose manual recovery. Upgrade will not overwrite it. |
|
|
95
|
+
| `VERSION_DOWNGRADE_REFUSED` | Target package is older than the installed manifest. | Use a newer fixed package version; never edit the manifest version. |
|
|
96
|
+
| `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. |
|
|
97
|
+
| `POST_UPGRADE_VERIFICATION_FAILED` | New resources failed verification. | The implementation attempts a complete old-version rollback; verify the old manifest and inspect upgrade evidence. |
|
|
98
|
+
| `UNINSTALL_CONFLICT` | Uninstall planning/application detected unsafe state. | Keep all files and inspect the listed paths. Drift is retained by design. |
|
|
99
|
+
| `POST_UNINSTALL_VERIFICATION_FAILED` | Final restored/removed paths did not verify. | The implementation attempts to restore the installed state; inspect uninstall recovery evidence before another command. |
|
|
100
|
+
| Any `*_ROLLBACK_FAILED` | Automatic recovery could not prove completion. | Stop all automation. Preserve Git refs, the manifest, marker, backups, recovery snapshots, and logs for manual analysis. |
|
|
101
|
+
|
|
102
|
+
Installer control paths are:
|
|
103
|
+
|
|
104
|
+
- active manifest: `.automation-plugin/manifest.json` (`0600`);
|
|
105
|
+
- first-install/original backups: `.automation-plugin/backups/<id>/`;
|
|
106
|
+
- upgrade marker and snapshots: `.automation-plugin/upgrade.json` and
|
|
107
|
+
`.automation-plugin/upgrades/<id>/`;
|
|
108
|
+
- uninstall marker and snapshots: `.automation-plugin/uninstall.json` and
|
|
109
|
+
`.automation-plugin/uninstalls/<id>/`;
|
|
110
|
+
- completed/rolled-back records: `.automation-plugin/history/`.
|
|
111
|
+
|
|
112
|
+
These files are evidence, not cache.
|
|
113
|
+
|
|
114
|
+
## Read-only custom tool failures
|
|
115
|
+
|
|
116
|
+
`android_orchestrator_status` accepts exactly one `TASK-[A-Z0-9-]+` ID. It
|
|
117
|
+
authenticates the installation before invoking the fixed status script.
|
|
118
|
+
|
|
119
|
+
| Code | Meaning |
|
|
120
|
+
| --- | --- |
|
|
121
|
+
| `INVALID_TASK_ID` | The ID contains invalid characters, extra text, or an unsupported format. |
|
|
122
|
+
| `WORKSPACE_MISMATCH` | The tool context differs from the worktree that loaded the plugin. |
|
|
123
|
+
| `UNTRUSTED_INSTALLATION` | Manifest, packaged resource, or executable-mode checks could not authenticate the installed status script. |
|
|
124
|
+
| `STATUS_RUNNER_UNAVAILABLE` | OpenCode did not supply the compatible shell adapter. |
|
|
125
|
+
| `STATUS_COMMAND_FAILED` | The authenticated status script returned a nonzero exit. Its details usually identify a missing contract or invalid runtime layout. |
|
|
126
|
+
| `INVALID_STATUS_OUTPUT` | Output was not valid JSON or identified another task. |
|
|
127
|
+
| `STATUS_OUTPUT_TOO_LARGE` | Output exceeded the 1 MiB safety bound. |
|
|
128
|
+
| `TOOL_ABORTED` | The OpenCode call was cancelled before execution. |
|
|
129
|
+
|
|
130
|
+
Do not bypass `UNTRUSTED_INSTALLATION` by calling a different script path. Run
|
|
131
|
+
doctor, restore the exact managed installation, or perform a reviewed recovery.
|
|
132
|
+
|
|
133
|
+
## Automation task recovery
|
|
134
|
+
|
|
135
|
+
Use `./scripts/automation/status.sh <TASK-ID>` or the read-only status tool to
|
|
136
|
+
identify the state, workspace, original branch, sealed diff, and evidence.
|
|
137
|
+
|
|
138
|
+
- `AWAITING_HUMAN`: use `/acceptance <TASK-ID>` to regenerate the verified
|
|
139
|
+
review card and fresh result question.
|
|
140
|
+
- `BLOCKED` after a Reviewer exited without submitting a decision: use
|
|
141
|
+
`/resume-review <TASK-ID>`. The script accepts only the bounded reviewer-only
|
|
142
|
+
recovery and proves the sealed diff has not changed.
|
|
143
|
+
- A supported stopped state that should be abandoned: use
|
|
144
|
+
`/abort-task <TASK-ID>`, inspect the status card, and complete its explicit
|
|
145
|
+
confirmation. It archives contract-scoped work before restoring the original
|
|
146
|
+
branch.
|
|
147
|
+
- `INTEGRATION_BLOCKED`: preserve the task branch, original branch, lease, and
|
|
148
|
+
integration evidence. Do not reset, cherry-pick, merge, or rerun the
|
|
149
|
+
integrator until the recorded refs and failure are understood.
|
|
150
|
+
- `TEST_FAILED` or `NEEDS_HUMAN`: inspect the contract and evidence. Do not
|
|
151
|
+
broaden scope or silently queue the same task again.
|
|
152
|
+
|
|
153
|
+
## Actions to avoid
|
|
154
|
+
|
|
155
|
+
Never use a troubleshooting shortcut that destroys the evidence needed to
|
|
156
|
+
prove recovery:
|
|
157
|
+
|
|
158
|
+
- do not run `git reset --hard`, `git clean`, an improvised merge/rebase, or a
|
|
159
|
+
manual branch deletion;
|
|
160
|
+
- do not edit manifest hashes, state JSON, approvals, or sealed evidence;
|
|
161
|
+
- do not recursively delete `.automation-plugin/` or
|
|
162
|
+
`.git/automation-runtime/`;
|
|
163
|
+
- do not chmod all managed files to silence permission drift;
|
|
164
|
+
- do not replace a pinned package reference with `latest`;
|
|
165
|
+
- do not expose `.env`, signing keys, keystores, `local.properties`, npm tokens,
|
|
166
|
+
model-provider credentials, or recovery diffs in public reports.
|
|
167
|
+
|
|
168
|
+
For escalation, provide the command, exit code, stable error code, redacted
|
|
169
|
+
details, OpenCode version, package version, current branch/HEAD, and the list of
|
|
170
|
+
affected paths. Share file contents only after applying the guidance in
|
|
171
|
+
[Security](SECURITY.md).
|
package/package.json
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frankzhang2026/opencode-android-orchestrator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Reusable OpenCode orchestration for Android projects",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"author": "frankzhang2026",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/frankzhangtx/npm-orchestrator-plugin.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/frankzhangtx/npm-orchestrator-plugin#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/frankzhangtx/npm-orchestrator-plugin/issues"
|
|
14
|
+
},
|
|
6
15
|
"type": "module",
|
|
7
|
-
"main": "./dist/
|
|
8
|
-
"types": "./dist/
|
|
16
|
+
"main": "./dist/opencode-plugin.js",
|
|
17
|
+
"types": "./dist/opencode-plugin.d.ts",
|
|
9
18
|
"exports": {
|
|
10
19
|
".": {
|
|
20
|
+
"types": "./dist/opencode-plugin.d.ts",
|
|
21
|
+
"import": "./dist/opencode-plugin.js"
|
|
22
|
+
},
|
|
23
|
+
"./api": {
|
|
11
24
|
"types": "./dist/index.d.ts",
|
|
12
25
|
"import": "./dist/index.js"
|
|
13
26
|
}
|
|
@@ -17,9 +30,12 @@
|
|
|
17
30
|
},
|
|
18
31
|
"files": [
|
|
19
32
|
"dist/",
|
|
33
|
+
"docs/",
|
|
20
34
|
"templates/",
|
|
21
35
|
"README.md",
|
|
22
|
-
"CHANGELOG.md"
|
|
36
|
+
"CHANGELOG.md",
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"THIRD_PARTY_NOTICES.md"
|
|
23
39
|
],
|
|
24
40
|
"publishConfig": {
|
|
25
41
|
"access": "public",
|
|
@@ -38,7 +54,6 @@
|
|
|
38
54
|
"automation",
|
|
39
55
|
"orchestration"
|
|
40
56
|
],
|
|
41
|
-
"author": "",
|
|
42
57
|
"peerDependencies": {
|
|
43
58
|
"@opencode-ai/plugin": ">=1.14.22 <1.16.0"
|
|
44
59
|
},
|
|
@@ -46,5 +61,8 @@
|
|
|
46
61
|
"@opencode-ai/plugin": "1.14.22",
|
|
47
62
|
"@types/node": "22.13.9",
|
|
48
63
|
"typescript": "5.8.2"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"jsonc-parser": "3.3.1"
|
|
49
67
|
}
|
|
50
68
|
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Implements or repairs exactly one orchestrated task with TDD and deterministic quality gates
|
|
3
|
+
mode: primary
|
|
4
|
+
temperature: 0.1
|
|
5
|
+
steps: 32
|
|
6
|
+
permission:
|
|
7
|
+
"*": deny
|
|
8
|
+
android_orchestrator_status: allow
|
|
9
|
+
android_orchestrator_doctor: allow
|
|
10
|
+
read:
|
|
11
|
+
"*": allow
|
|
12
|
+
".env": deny
|
|
13
|
+
".env.*": deny
|
|
14
|
+
"local.properties": deny
|
|
15
|
+
"**/*.jks": deny
|
|
16
|
+
"**/*.keystore": deny
|
|
17
|
+
edit:
|
|
18
|
+
"*": deny
|
|
19
|
+
"src/main/**": allow
|
|
20
|
+
"src/test/**": allow
|
|
21
|
+
"src/androidTest/**": allow
|
|
22
|
+
"**/src/main/**": allow
|
|
23
|
+
"**/src/test/**": allow
|
|
24
|
+
"**/src/androidTest/**": allow
|
|
25
|
+
".opencode/**": deny
|
|
26
|
+
".opencode/skills/**": deny
|
|
27
|
+
"automation/**": deny
|
|
28
|
+
"scripts/automation/**": deny
|
|
29
|
+
"opencode.json": deny
|
|
30
|
+
"AGENTS.md": deny
|
|
31
|
+
"gradle/**": deny
|
|
32
|
+
"gradlew": deny
|
|
33
|
+
"gradlew.bat": deny
|
|
34
|
+
"settings.gradle": deny
|
|
35
|
+
"settings.gradle.kts": deny
|
|
36
|
+
"build.gradle": deny
|
|
37
|
+
"build.gradle.kts": deny
|
|
38
|
+
"**/build.gradle": deny
|
|
39
|
+
"**/build.gradle.kts": deny
|
|
40
|
+
bash:
|
|
41
|
+
"*": deny
|
|
42
|
+
"git status": allow
|
|
43
|
+
"git status --short": allow
|
|
44
|
+
"git diff": allow
|
|
45
|
+
"git diff --stat": allow
|
|
46
|
+
"git diff --name-only": allow
|
|
47
|
+
"git rev-parse HEAD": allow
|
|
48
|
+
"git rev-parse --show-toplevel": allow
|
|
49
|
+
"git ls-files": allow
|
|
50
|
+
"./gradlew testDebugUnitTest": allow
|
|
51
|
+
"./gradlew assembleDebug": allow
|
|
52
|
+
"./gradlew lint": allow
|
|
53
|
+
"./gradlew connectedDebugAndroidTest": allow
|
|
54
|
+
"./scripts/automation/status.sh *": allow
|
|
55
|
+
"./scripts/automation/select-task.sh PENDING": allow
|
|
56
|
+
"./scripts/automation/claim-task.sh *": allow
|
|
57
|
+
"./scripts/automation/block-task.sh *": allow
|
|
58
|
+
"./scripts/automation/record-red.sh *": allow
|
|
59
|
+
"./scripts/automation/quality-gate.sh *": allow
|
|
60
|
+
"git push*": deny
|
|
61
|
+
"git merge*": deny
|
|
62
|
+
"git rebase*": deny
|
|
63
|
+
"git worktree*": deny
|
|
64
|
+
"git clean*": deny
|
|
65
|
+
"git reset*": deny
|
|
66
|
+
"rm *": deny
|
|
67
|
+
"*>*": deny
|
|
68
|
+
"*<*": deny
|
|
69
|
+
"*|*": deny
|
|
70
|
+
"*;*": deny
|
|
71
|
+
"*&&*": deny
|
|
72
|
+
"*||*": deny
|
|
73
|
+
"*$(*": deny
|
|
74
|
+
"*`*": deny
|
|
75
|
+
glob: allow
|
|
76
|
+
grep: allow
|
|
77
|
+
list: allow
|
|
78
|
+
skill:
|
|
79
|
+
"*": deny
|
|
80
|
+
"using-superpowers": allow
|
|
81
|
+
"scheduled-quality-coder": allow
|
|
82
|
+
"test-driven-development": allow
|
|
83
|
+
"systematic-debugging": allow
|
|
84
|
+
"verification-before-completion": allow
|
|
85
|
+
schedule_job: deny
|
|
86
|
+
list_jobs: deny
|
|
87
|
+
get_version: deny
|
|
88
|
+
get_skill: deny
|
|
89
|
+
install_skill: deny
|
|
90
|
+
get_job: deny
|
|
91
|
+
update_job: deny
|
|
92
|
+
delete_job: deny
|
|
93
|
+
cleanup_global: deny
|
|
94
|
+
run_job: deny
|
|
95
|
+
job_logs: deny
|
|
96
|
+
task: deny
|
|
97
|
+
question: deny
|
|
98
|
+
external_directory: deny
|
|
99
|
+
webfetch: deny
|
|
100
|
+
websearch: deny
|
|
101
|
+
doom_loop: deny
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
You are the write-capable half of an orchestrated coding quality gate.
|
|
105
|
+
|
|
106
|
+
The orchestrator message must contain exactly one task ID or the compatibility
|
|
107
|
+
selector token `NEXT_PENDING`. Load
|
|
108
|
+
`scheduled-quality-coder` before taking any repository action and follow it
|
|
109
|
+
literally. Do not infer missing requirements and do not ask questions during a
|
|
110
|
+
non-interactive run. If anything is ambiguous or blocked, stop and report the exact
|
|
111
|
+
reason; the deterministic scripts own state transitions.
|
|
112
|
+
|
|
113
|
+
You may edit only paths allowed both by this agent and by the task contract.
|
|
114
|
+
Passing tests never grants permission to push, merge, create worktrees, alter
|
|
115
|
+
automation rules, or declare the task ready for review yourself.
|