@frankzhang2026/opencode-android-orchestrator 1.0.5 → 1.2.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 (109) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +79 -15
  3. package/dist/config/queue-policy.d.ts.map +1 -1
  4. package/dist/config/queue-policy.js +1 -2
  5. package/dist/config/queue-policy.js.map +1 -1
  6. package/dist/doctor/index.d.ts.map +1 -1
  7. package/dist/doctor/index.js +27 -3
  8. package/dist/doctor/index.js.map +1 -1
  9. package/dist/doctor/installation.d.ts +1 -1
  10. package/dist/doctor/installation.d.ts.map +1 -1
  11. package/dist/doctor/installation.js +11 -1
  12. package/dist/doctor/installation.js.map +1 -1
  13. package/dist/index.d.ts +1 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +1 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/installer/adaptive-templates.d.ts +4 -1
  18. package/dist/installer/adaptive-templates.d.ts.map +1 -1
  19. package/dist/installer/adaptive-templates.js +42 -13
  20. package/dist/installer/adaptive-templates.js.map +1 -1
  21. package/dist/installer/android-project.d.ts +3 -1
  22. package/dist/installer/android-project.d.ts.map +1 -1
  23. package/dist/installer/android-project.js.map +1 -1
  24. package/dist/installer/capabilities-script.d.ts +2 -0
  25. package/dist/installer/capabilities-script.d.ts.map +1 -0
  26. package/dist/installer/capabilities-script.js +84 -0
  27. package/dist/installer/capabilities-script.js.map +1 -0
  28. package/dist/installer/gradle-verification.d.ts.map +1 -1
  29. package/dist/installer/gradle-verification.js +13 -6
  30. package/dist/installer/gradle-verification.js.map +1 -1
  31. package/dist/installer/init.d.ts.map +1 -1
  32. package/dist/installer/init.js +3 -2
  33. package/dist/installer/init.js.map +1 -1
  34. package/dist/installer/opencode-config.d.ts +3 -3
  35. package/dist/installer/opencode-config.js +1 -1
  36. package/dist/installer/project-capabilities.d.ts +35 -0
  37. package/dist/installer/project-capabilities.d.ts.map +1 -0
  38. package/dist/installer/project-capabilities.js +82 -0
  39. package/dist/installer/project-capabilities.js.map +1 -0
  40. package/dist/installer/upgrade.d.ts.map +1 -1
  41. package/dist/installer/upgrade.js +10 -2
  42. package/dist/installer/upgrade.js.map +1 -1
  43. package/dist/queue/cli.d.ts.map +1 -1
  44. package/dist/queue/cli.js +32 -5
  45. package/dist/queue/cli.js.map +1 -1
  46. package/dist/queue/executor.d.ts +1 -0
  47. package/dist/queue/executor.d.ts.map +1 -1
  48. package/dist/queue/executor.js +160 -11
  49. package/dist/queue/executor.js.map +1 -1
  50. package/dist/queue/process-ownership.d.ts +12 -0
  51. package/dist/queue/process-ownership.d.ts.map +1 -0
  52. package/dist/queue/process-ownership.js +58 -0
  53. package/dist/queue/process-ownership.js.map +1 -0
  54. package/dist/queue/queue.d.ts +25 -1
  55. package/dist/queue/queue.d.ts.map +1 -1
  56. package/dist/queue/queue.js +96 -11
  57. package/dist/queue/queue.js.map +1 -1
  58. package/dist/queue/service.d.ts.map +1 -1
  59. package/dist/queue/service.js +19 -2
  60. package/dist/queue/service.js.map +1 -1
  61. package/dist/queue/storage.d.ts +3 -1
  62. package/dist/queue/storage.d.ts.map +1 -1
  63. package/dist/queue/storage.js +25 -15
  64. package/dist/queue/storage.js.map +1 -1
  65. package/dist/queue/supervision.d.ts +38 -0
  66. package/dist/queue/supervision.d.ts.map +1 -0
  67. package/dist/queue/supervision.js +247 -0
  68. package/dist/queue/supervision.js.map +1 -0
  69. package/dist/queue/tools.d.ts.map +1 -1
  70. package/dist/queue/tools.js +4 -2
  71. package/dist/queue/tools.js.map +1 -1
  72. package/docs/GRADLE-6.7.1.md +112 -0
  73. package/docs/MIGRATION.md +125 -11
  74. package/docs/QUEUE.md +350 -16
  75. package/docs/SECURITY.md +5 -2
  76. package/docs/TROUBLESHOOTING.md +81 -8
  77. package/package.json +1 -1
  78. package/templates/.opencode/agents/scheduled-coder.md +14 -1
  79. package/templates/.opencode/agents/scheduled-planner.md +64 -3
  80. package/templates/.opencode/skills/scheduled-quality-coder/SKILL.md +36 -3
  81. package/templates/.opencode/skills/scheduled-quality-orchestrator/SKILL.md +65 -4
  82. package/templates/.opencode/skills/scheduled-quality-reviewer/SKILL.md +23 -1
  83. package/templates/AGENTS.md.fragment +10 -4
  84. package/templates/README.md +3 -1
  85. package/templates/automation/config.schema.json +212 -22
  86. package/templates/automation/task-contract.schema.json +659 -49
  87. package/templates/automation/tasks/TASK-TEMPLATE.json.example +14 -8
  88. package/templates/automation/verification/collect.init.gradle +108 -0
  89. package/templates/automation/verification/contract.cjs +119 -0
  90. package/templates/automation/verification/inventory.cjs +536 -0
  91. package/templates/automation/verification/project.cjs +230 -0
  92. package/templates/automation/verification/recovery.cjs +425 -0
  93. package/templates/automation/verification/runtime.init.gradle +58 -0
  94. package/templates/scripts/automation/acceptance-report.sh +17 -0
  95. package/templates/scripts/automation/claim-task.sh +35 -2
  96. package/templates/scripts/automation/integration-scope-gate.sh +3 -3
  97. package/templates/scripts/automation/lib.sh +61 -19
  98. package/templates/scripts/automation/orchestrate-task.sh +7 -1
  99. package/templates/scripts/automation/preflight.sh +1 -2
  100. package/templates/scripts/automation/quality-gate.sh +10 -1
  101. package/templates/scripts/automation/record-red.sh +13 -1
  102. package/templates/scripts/automation/resume-task.sh +3 -0
  103. package/templates/scripts/automation/scope-gate.sh +4 -4
  104. package/templates/scripts/automation/show-acceptance-review.sh +1 -0
  105. package/templates/scripts/automation/status.sh +35 -0
  106. package/templates/scripts/automation/submit-review.sh +10 -1
  107. package/templates/scripts/automation/validate-contract.sh +10 -1
  108. package/templates/scripts/automation/verify-integration.sh +3 -0
  109. package/templates/scripts/automation/verify-task.sh +3 -0
@@ -62,7 +62,16 @@ approval. After approval, assemble a complete plan and contract in memory and
62
62
  call `android_orchestrator_intake` with action `draft`; do not create files in the
63
63
  product checkout. Preserve the snapshot's target branch and planningHead.
64
64
 
65
- Use schema V3 structured verification. Give every verification case a stable ID,
65
+ Use schema V4 with verification version 2 unless the proposal explicitly includes
66
+ bounded baseline recovery; use schema V5 only with that newly approved policy. Declare only task behavior cases;
67
+ the executor captures existing focused tests before Coder edits and adds them
68
+ as regression coverage. Explicitly approve inventory mode `focusedBaseline`,
69
+ existing skips (`reject` or `preserve`) and empty baseline (`reject` or `allow`).
70
+ Default both policies to `reject`; use `allow` only for an intentionally empty
71
+ scope such as a new test class. Use fully qualified configured Test task paths,
72
+ and include each parameter instance in the exact behavior identity. Discovered
73
+ test/resource directories do not expand `allowedPaths` or agent permissions.
74
+ Give every verification case a stable ID,
66
75
  its one-based acceptance-criterion reference, its source, and its exact test
67
76
  identity. Classify preserved behavior as `before: pass`, changed behavior as
68
77
  `before: fail`, and an uncertain old boundary as `before: observe`. Do not infer
@@ -72,13 +81,50 @@ the value for baseline capture. Plan examples are implementation guidance and
72
81
  must not add requirements beyond the contract. Check acceptance criteria,
73
82
  non-goals and verification expectations for contradictions before drafting.
74
83
 
84
+ For V5/V6/V7/V8, present all recovery fields before contract approval: `version: 1`,
85
+ `scope: baseline`, `maxEnvironmentRetries`, `maxManualRetries`,
86
+ `maxSameFailureRetries` (each 0..3), `maxElapsedMs` (1000..86400000), and
87
+ `initialDelayMs`/`maxDelayMs` (1000..600000, maximum at least initial).
88
+ Explain that classified temporary network/rate-limit failures may retry only
89
+ in deterministic baseline capture. Unknown failures require a fresh resume
90
+ approval within the separate manual budget. Historical test failures, changed
91
+ inputs and corrupted evidence cannot use this route. The elapsed limit stops
92
+ new attempts; it does not terminate a hung process. Recovery does not authorize
93
+ model retries, changed tests, wider scope, or automatic local integration.
94
+ Keep existing V4 contracts unchanged; do not silently add V5 authority.
95
+
96
+ Use schema V6, V7 or V8 only when the proposal also explicitly approves Worker
97
+ termination. Present `execution: { version: 1, maxRunMs, maxStageMs,
98
+ terminationGraceMs }`: run/stage limits are 1000..86400000 ms, stage at most
99
+ run, and TERM grace is 1000..60000 ms. These wall-clock limits apply to each
100
+ reserved execution, including baseline recovery, review, integration and
101
+ abort. An independent supervisor may TERM owned processes and then KILL
102
+ survivors after grace. Deadlines include sleep time and survive scheduler or
103
+ supervisor restart. Log silence is never a reason to kill. Show the actual
104
+ limits before contract approval; do not infer this authority for old tasks.
105
+ Unknown ownership retains the slot. A stopped candidate is not accepted; a
106
+ visible commit keeps its existing transaction for idempotent recovery.
107
+
108
+ Use V7/V8 only with separately approved `stageRecovery`: `version: 1`,
109
+ `maxEnvironmentRetries`, `maxSameFailureRetries` (0..3), `maxElapsedMs`
110
+ (1000..86400000), `initialDelayMs` and `maxDelayMs` (1000..600000,
111
+ maximum at least initial). Each of RED, GREEN and independent Review has its
112
+ own cumulative environment budget and recovery window. Only deterministic
113
+ verification is retried; no model call or commit is replayed. Attempts and
114
+ backoff are durable; changed inputs, ambiguous processes and altered evidence
115
+ stop recovery. Exhausted or unknown verification failures preserve the task
116
+ without spending implementation or Review correction cycles. This does not
117
+ authorize a task-wide model-cost budget, provider retries or evidence revision.
118
+ V1..V6 contracts gain none of this authority through an upgrade.
119
+
75
120
  When the draft does not specify a workspace or commit policy, use the values in
76
121
  `automation/config.json`; new installations configure `inPlaceExclusive` and
77
122
  `humanApproval`. A user may explicitly override the commit policy to
78
- `autoCommit` only for `inPlaceExclusive`. Explain the effective policy before
123
+ `autoCommit` for `inPlaceExclusive`, or for `isolatedWorktree` with a new V8
124
+ contract explicitly setting `continuity.isolatedAutoIntegration: true`. Explain the effective policy before
79
125
  sealing: quality gates still include build, fresh full unit tests and independent
80
126
  Review; automatic mode authorizes local commit and integration, never remote
81
- push. `isolatedWorktree` supports human acceptance only. Never infer a policy
127
+ push. Older isolated contracts retain human acceptance. Never infer a policy
82
128
  from an old approval or successful tests.
83
129
 
84
130
  Present the returned sealed contract, plan, digest, version, schedule,
@@ -117,3 +163,18 @@ respective recovery jobs. Commit-transaction recovery uses `recover`; it may
117
163
  reuse only already sealed authorization and verified local commit metadata.
118
164
  Failures preserve the workspace. Do not reset, clean, force-update refs, delete
119
165
  user changes, commit directly or push.
166
+
167
+
168
+ For V8, retain V7 recovery/execution policies and present `continuity` with
169
+ `version: 1`, `isolatedAutoIntegration`, `planningRefresh` (`reject` or
170
+ `completedQueueTasks`) and 1..128 unique repository-relative `planningInputs`.
171
+ Declare all code, interfaces, tests and resources used to reason about the task,
172
+ including dependencies outside allowed edit paths. Exact files or path selectors
173
+ are fingerprinted at the immutable planning HEAD, including absent matches.
174
+ If semantic dependencies are unclear, select `reject` rather than claiming that
175
+ nonconflicting files establish independence. The sealed draft and question must
176
+ show the input selectors/digest and refresh policy. Completed-queue refresh may
177
+ only advance before execution over recorded integrations with unchanged inputs
178
+ and configuration; changed requirements or tests require a revised contract.
179
+ This policy does not authorize automatic candidate rebasing, weakening tests,
180
+ retry-budget resets, new requirements, remote pushes or publication.
@@ -50,15 +50,37 @@ it with `./scripts/automation/block-task.sh <TASK-ID> <reason>` before stopping.
50
50
  - For `CODING` after an interrupted initial run, inspect existing evidence
51
51
  and continue from the first incomplete mandatory action.
52
52
 
53
- 4. On the initial coding cycle, add or change the smallest behavior test
53
+ 4. For V4/V5/V6/V7, confirm successful claim recorded `baselineInventory` in status
54
+ before editing any test. Discovery classifies evidence inputs only; all
55
+ edits still need contract and agent permission. On the initial coding cycle,
56
+ add or change the smallest behavior test
54
57
  permitted by `allowedPaths`.
55
58
  5. If RED evidence does not already exist, capture a genuine RED result. For a
56
- schema V3 contract use:
59
+ schema V3/V4/V5/V6/V7 contract use:
57
60
 
58
61
  `./scripts/automation/record-red.sh <TASK-ID>`
59
62
 
60
63
  It checks every declared preserved, changed and observed case against fresh
61
- structured output. For a legacy schema V1/V2 contract use:
64
+ structured output. V4/V5/V6/V7 also checks every captured existing regression case;
65
+ RED and GREEN share that manifest. After RED, test sources and resources are
66
+ frozen. An explicitly approved `verification.supplementalTests` policy may
67
+ permit one append-only revision of new Java/Kotlin/Groovy test files. Do not
68
+ change existing test files, resources, filters or approved case identities.
69
+ GREEN validates the new cases on an isolated original baseline before sealing
70
+ supplemental evidence. They must all pass there and on the implementation;
71
+ failures, missing execution or changed original tests require a revised task.
72
+ Without this permission, request a revised task instead of repeatedly trying
73
+ to add tests to a frozen manifest. For V4, if baseline inventory capture fails after `baseline.json` is written,
74
+ stop: baseline-only resume cannot retry it. Preserve evidence and request
75
+ approved abort/archive followed by a newly approved task; do not delete
76
+ baseline files or keep retrying the original task.
77
+ For V5/V6/V7, the queue completes deterministic baseline capture before launching
78
+ Coder. Inspect `baselineRecovery` and require a complete sealed baseline.
79
+ If capture is blocked, stop; only the queue may schedule approved recovery.
80
+ Never invoke recovery.cjs directly, change its ledger or retry a claim.
81
+ Read `inventoryStatus` for the exact reason and next action on
82
+ failure; never regenerate a baseline or overwrite sealed RED to bypass it.
83
+ For a legacy schema V1/V2 contract use:
62
84
 
63
85
  `./scripts/automation/record-red.sh <TASK-ID> <expected-failure-text> -- <test-filter>`
64
86
 
@@ -103,3 +125,14 @@ Do not invoke `android-orchestrator-brainstorming`,
103
125
  `finishing-a-development-branch`, `requesting-code-review`, parallel agents, or
104
126
  subagent-driven development. Planning and approval happen before this session;
105
127
  review happens in a separate fresh read-only session.
128
+
129
+ ## Approved V7 verification recovery
130
+
131
+ For V7, record-red.sh, quality-gate.sh and submit-review.sh handle explicitly
132
+ approved transient verification retries with separate RED/GREEN/Review budgets.
133
+ Do not retry these commands to reset an exhausted environment budget. Status
134
+ `stageRecovery` shows attempt history, failure classification and persistent
135
+ backoff. An environment/unknown stop is not a request to change production code
136
+ or weaken tests; preserve the candidate and stop. Provider/model failures still
137
+ follow the existing approved recovery route. Never edit the recovery ledger,
138
+ locks or earlier logs. V1..V6 keep their original retry semantics.
@@ -26,9 +26,10 @@ description: Plan stable committed code, approve independent inbox contracts, an
26
26
  from `automation/config.json`; new installations configure
27
27
  `inPlaceExclusive` + `humanApproval`. If the user explicitly wants a
28
28
  different policy, show the effective choice in the proposal and seal it.
29
- `autoCommit` is supported only with `inPlaceExclusive`; the unsupported
30
- `isolatedWorktree` + `autoCommit` combination must fail. Older approvals
31
- retain their sealed policies.
29
+ `autoCommit` supports `inPlaceExclusive`, or `isolatedWorktree` with a new
30
+ V8 contract explicitly granting `continuity.isolatedAutoIntegration: true`.
31
+ Older approvals retain their sealed policies and cannot acquire this
32
+ authority from repository defaults.
32
33
  5. Display the returned full plan, contract and review card: task ID/version,
33
34
  digest, target local branch/planningHead, allowed paths/file count, tests,
34
35
  acceptance/non-goals, dependencies/notBefore, workspace and commit policies.
@@ -53,7 +54,7 @@ contract authorization. Never create a final human approval for autoCommit.
53
54
  `/acceptance <TASK-ID>` reads the current item and acceptance report. Present
54
55
  the candidate/diff hash, target branch, baseline, build, actual full-test results,
55
56
  independent Review, scope and commit policy. If the local target has advanced
56
- for an isolated candidate, request `revalidate`. That job waits for the same
57
+ for a human-approval isolated candidate, request `revalidate`. That job waits for the same
57
58
  execution slot, runs fresh verification/Review and invalidates old acceptance.
58
59
  After a fresh candidate exists, call queue `review` with
59
60
  `operation: integrate` and the task key. Present its evidence, then call
@@ -80,3 +81,63 @@ independent tasks run. Dependencies complete only after local integration.
80
81
 
81
82
  After completion, show the true authorization source, local commit SHA and
82
83
  “未推送”. No workflow, failure or recovery grants remote push rights.
84
+
85
+ ## Approved V5 baseline recovery
86
+
87
+ V5 contracts explicitly seal a bounded baseline-only recovery policy. Queue
88
+ status exposes the failure category, retained attempts, deadline and next run.
89
+ A scheduled environment retry uses the existing execution slot without another
90
+ model call or question. Do not submit a duplicate manual recovery while it is
91
+ waiting. `/resume-task` remains a fresh approval for an unknown failure and
92
+ uses the separate manual budget. Neither route can replace a successful
93
+ baseline, accept changed inputs, or weaken V4/V5 RED/GREEN checks. No recovery
94
+ policy is inferred for V4 contracts. Preserve incomplete RUNNING attempts after
95
+ an ambiguous process exit for ownership diagnosis; do not reset their budgets.
96
+
97
+ ## Approved V6 Worker supervision
98
+
99
+ V6 adds explicit per-execution run/stage deadlines and TERM grace to the V5
100
+ contract. The independent supervisor applies that sealed policy without a new
101
+ question for each timeout. Queue and task status expose `workerSupervision`;
102
+ inspect the stop reason and durable signal/exit evidence. Never issue broad
103
+ process-name kills, clear ownership faults to force scheduling, or delete
104
+ leases. A known stopped isolated candidate is sealed before independent work
105
+ continues; its dependents still wait. An interrupted local commit stays
106
+ `INTEGRATION_BLOCKED`; use the existing transaction recovery route, never make
107
+ a replacement commit. `queue stop` stops the scheduler and leaves supervision
108
+ active. On restart the scheduler reattaches a missing supervisor without
109
+ relaunching a live Worker or resetting its deadlines/grace.
110
+
111
+ ## Approved V7 verification recovery
112
+
113
+ For V7, record-red.sh, quality-gate.sh and submit-review.sh handle explicitly
114
+ approved transient verification retries with separate RED/GREEN/Review budgets.
115
+ Do not retry these commands to reset an exhausted environment budget. Status
116
+ `stageRecovery` shows attempt history, failure classification and persistent
117
+ backoff. An environment/unknown stop is not a request to change production code
118
+ or weaken tests; preserve the candidate and stop. Provider/model failures still
119
+ follow the existing approved recovery route. Never edit the recovery ledger,
120
+ locks or earlier logs. V1..V6 keep their original retry semantics.
121
+
122
+ ## Approved V8 isolated integration and planning refresh
123
+
124
+ V8 retains the V7 recovery and execution policies. Present all `continuity`
125
+ fields before approval: `version: 1`, `isolatedAutoIntegration`, `planningRefresh`
126
+ and `planningInputs`. Isolated automatic integration requires both sealed
127
+ `isolatedWorktree` and `autoCommit` policies. Use the complete returned approval
128
+ question, including its continuity authority; never synthesize a shorter label.
129
+
130
+ Declare every repository input used to reason about the requirement, interfaces,
131
+ design and tests in `planningInputs`, including dependencies and relevant
132
+ resources. Selectors do not grant edit permission. If this dependency declaration
133
+ is uncertain, use `planningRefresh: "reject"`. `completedQueueTasks` permits a
134
+ fresh execution baseline only before execution, with unchanged declared inputs
135
+ and configuration and a verified linear history of completed queue integrations.
136
+ It cannot reset recovery budgets or replace an existing task's RED/Review.
137
+
138
+ For BASELINE_REVIEW, inspect `planning-baseline` evidence and propose a revised
139
+ contract when required. Preserve the original planning HEAD and approval. Target
140
+ drift during automatic integration does not authorize rebase or automatic
141
+ revalidation. Preserve the candidate; an existing commit transaction requires
142
+ explicit `recover`, while a revised plan requires a new approval. Report the
143
+ actual local commit and automatic authorization source after completion.
@@ -38,10 +38,21 @@ you review.
38
38
  5. Check each acceptance criterion against observable behavior. Inspect for
39
39
  regression risk, missing edge cases, out-of-scope changes, test deletion,
40
40
  ignored tests, relaxed assertions, and implementation-shaped tests.
41
- For schema V3, also verify every structured case source and identity, that
41
+ For schema V3/V4/V5/V6/V7, also verify every structured case source and identity, that
42
42
  preserved cases passed before implementation, that changed cases failed only
43
43
  for their declared reason, and that RED contains no undeclared failure. Treat
44
44
  the Planner and Coder summaries as claims; use the bound preflight evidence.
45
+ For V4/V5/V6/V7 inspect `baselineInventory`, `testManifest`, `greenInventory` and
46
+ `inventoryStatus` from status. Check complete regression coverage, explicit
47
+ existing-skip/empty-baseline policy and frozen test/resource inputs. The
48
+ collector checks type/message and the declared stack location, including
49
+ a test-body invocation. Independently assess assertion meaning and whether
50
+ the approved origin actually exercises the requirement. An approved
51
+ `supplementalTests` policy permits one new-file-only regression supplement;
52
+ inspect its original-baseline results and GREEN binding. Never weaken frozen
53
+ assertions or overwrite the original RED to satisfy a review request.
54
+ `processExitCode` is Gradle's actual exit; a RED `exitCode` of 1 represents
55
+ approved case failure, not a failed Gradle build.
45
56
  6. Decide independently:
46
57
 
47
58
  - approve only when the diff is correct and evidence is sufficient;
@@ -74,3 +85,14 @@ you review.
74
85
  `AWAITING_HUMAN`.
75
86
  - If verification cannot run, submit `CHANGES_REQUESTED` with the environmental
76
87
  blocker. Do not manufacture approval.
88
+
89
+ ## Approved V7 verification recovery
90
+
91
+ For V7, record-red.sh, quality-gate.sh and submit-review.sh handle explicitly
92
+ approved transient verification retries with separate RED/GREEN/Review budgets.
93
+ Do not retry these commands to reset an exhausted environment budget. Status
94
+ `stageRecovery` shows attempt history, failure classification and persistent
95
+ backoff. An environment/unknown stop is not a request to change production code
96
+ or weaken tests; preserve the candidate and stop. Provider/model failures still
97
+ follow the existing approved recovery route. Never edit the recovery ledger,
98
+ locks or earlier logs. V1..V6 keep their original retry semantics.
@@ -3,10 +3,16 @@
3
3
 
4
4
  Run orchestration commands from the Git repository root.
5
5
 
6
- For automated local unit-test verification, run `./gradlew testDebugUnitTest`
7
- as a standalone command. Do not prepend environment assignments or wrap it in
8
- another script; this keeps the invocation aligned with the installed OpenCode
9
- command allowlist.
6
+ For automated local unit-test verification, use the task paths in
7
+ `automation/config.json` under `gradleVerification.fullUnitTestTasks`.
8
+ For manual runs, execute `./gradlew` followed by those configured tasks from
9
+ `androidProject.capabilities.buildRoot` relative to the Git root (default `.`).
10
+ Use a standalone command without environment assignments or shell chaining.
11
+ For nested builds, unattended agents must use the managed verification scripts
12
+ from the Git root; direct Gradle commands are rejected by the executor guard.
13
+ Task execution uses the controlled verification scripts, which read the same
14
+ configuration. Empty lint/device task lists mean the capability is unavailable;
15
+ they never count as a passed check when that capability is required.
10
16
 
11
17
  Treat `.opencode/`, `automation/`, `scripts/automation/`, `opencode.json`,
12
18
  and this managed block as orchestration infrastructure. Product tasks must not
@@ -12,7 +12,9 @@ Migrated template roots:
12
12
  - `.opencode/commands`: `change`, `acceptance`, `resume-task`, `resume-review`,
13
13
  and `abort-task`
14
14
  - `.opencode/skills`: the three `scheduled-quality-*` skills
15
- - `scripts/automation`: all 29 deterministic V3 Bash transactions and their
15
+ - `automation/verification`: the shared V4/V5 contract validator, bounded V5 baseline recovery, inventory evaluator
16
+ and Gradle collector. Discovered tests are evidence inputs, not edit permission.
17
+ - `scripts/automation`: all 29 deterministic Bash transactions and their
16
18
  test runner, preserved as executable files
17
19
  - `automation`: the portable V5 configuration render source, both JSON Schemas,
18
20
  and the task contract example
@@ -22,6 +22,13 @@
22
22
  "minLength": 1,
23
23
  "pattern": "^(?:[A-Za-z][A-Za-z0-9_.-]*|(?::[A-Za-z0-9_.-]+)+)$"
24
24
  },
25
+ "optionalGradleTaskList": {
26
+ "type": "array",
27
+ "uniqueItems": true,
28
+ "items": {
29
+ "$ref": "#/$defs/gradleTask"
30
+ }
31
+ },
25
32
  "gradleTaskList": {
26
33
  "type": "array",
27
34
  "minItems": 1,
@@ -184,10 +191,10 @@
184
191
  "$ref": "#/$defs/gradleTaskList"
185
192
  },
186
193
  "lintTasks": {
187
- "$ref": "#/$defs/gradleTaskList"
194
+ "$ref": "#/$defs/optionalGradleTaskList"
188
195
  },
189
196
  "deviceTestTasks": {
190
- "$ref": "#/$defs/gradleTaskList"
197
+ "$ref": "#/$defs/optionalGradleTaskList"
191
198
  }
192
199
  }
193
200
  },
@@ -266,7 +273,8 @@
266
273
  "library",
267
274
  "dynamic-feature",
268
275
  "test",
269
- "asset-pack"
276
+ "asset-pack",
277
+ "jvm-library"
270
278
  ]
271
279
  },
272
280
  "namespace": {
@@ -283,14 +291,7 @@
283
291
  "minItems": 1,
284
292
  "uniqueItems": true,
285
293
  "items": {
286
- "allOf": [
287
- {
288
- "$ref": "#/$defs/repositoryPath"
289
- },
290
- {
291
- "pattern": "(^|/)src/main/\\*\\*$"
292
- }
293
- ]
294
+ "$ref": "#/$defs/repositoryPath"
294
295
  }
295
296
  },
296
297
  "testPaths": {
@@ -298,17 +299,202 @@
298
299
  "minItems": 1,
299
300
  "uniqueItems": true,
300
301
  "items": {
301
- "allOf": [
302
- {
303
- "$ref": "#/$defs/repositoryPath"
302
+ "$ref": "#/$defs/repositoryPath"
303
+ }
304
+ },
305
+ "capabilities": {
306
+ "type": "object",
307
+ "additionalProperties": false,
308
+ "required": [
309
+ "version",
310
+ "buildRoot",
311
+ "modules"
312
+ ],
313
+ "properties": {
314
+ "version": {
315
+ "const": 1
316
+ },
317
+ "buildRoot": {
318
+ "$ref": "#/$defs/repositoryPath"
319
+ },
320
+ "modules": {
321
+ "type": "array",
322
+ "items": {
323
+ "type": "object",
324
+ "additionalProperties": false,
325
+ "required": [
326
+ "gradlePath",
327
+ "directory",
328
+ "buildFile",
329
+ "type",
330
+ "namespace",
331
+ "applicationId",
332
+ "dependencies",
333
+ "sources",
334
+ "tasks"
335
+ ],
336
+ "properties": {
337
+ "gradlePath": {
338
+ "type": "string",
339
+ "pattern": "^:(?:[A-Za-z0-9_.-]+(?::[A-Za-z0-9_.-]+)*)?$"
340
+ },
341
+ "directory": {
342
+ "$ref": "#/$defs/repositoryPath"
343
+ },
344
+ "buildFile": {
345
+ "$ref": "#/$defs/repositoryPath"
346
+ },
347
+ "type": {
348
+ "enum": [
349
+ "application",
350
+ "library",
351
+ "dynamic-feature",
352
+ "test",
353
+ "asset-pack",
354
+ "jvm-library"
355
+ ]
356
+ },
357
+ "namespace": {
358
+ "$ref": "#/$defs/nullableIdentifier"
359
+ },
360
+ "applicationId": {
361
+ "$ref": "#/$defs/nullableIdentifier"
362
+ },
363
+ "dependencies": {
364
+ "type": "array",
365
+ "items": {
366
+ "type": "string",
367
+ "pattern": "^:(?:[A-Za-z0-9_.-]+(?::[A-Za-z0-9_.-]+)*)?$"
368
+ },
369
+ "uniqueItems": true
370
+ },
371
+ "sources": {
372
+ "type": "array",
373
+ "items": {
374
+ "type": "object",
375
+ "additionalProperties": false,
376
+ "required": [
377
+ "name",
378
+ "kind",
379
+ "paths"
380
+ ],
381
+ "properties": {
382
+ "name": {
383
+ "type": "string",
384
+ "pattern": "^[A-Za-z0-9_.-]+$"
385
+ },
386
+ "kind": {
387
+ "enum": [
388
+ "production",
389
+ "test"
390
+ ]
391
+ },
392
+ "paths": {
393
+ "type": "array",
394
+ "items": {
395
+ "$ref": "#/$defs/repositoryPath"
396
+ },
397
+ "uniqueItems": true
398
+ }
399
+ }
400
+ },
401
+ "uniqueItems": true
402
+ },
403
+ "tasks": {
404
+ "type": "array",
405
+ "items": {
406
+ "type": "object",
407
+ "additionalProperties": false,
408
+ "required": [
409
+ "path",
410
+ "kind",
411
+ "variant"
412
+ ],
413
+ "properties": {
414
+ "path": {
415
+ "type": "string",
416
+ "pattern": "^:(?:[A-Za-z0-9_.-]+:)*[A-Za-z][A-Za-z0-9_.-]*$"
417
+ },
418
+ "kind": {
419
+ "enum": [
420
+ "unit",
421
+ "assemble",
422
+ "lint",
423
+ "device"
424
+ ]
425
+ },
426
+ "variant": {
427
+ "type": [
428
+ "string",
429
+ "null"
430
+ ],
431
+ "pattern": "^[A-Za-z0-9]+$"
432
+ }
433
+ }
434
+ },
435
+ "uniqueItems": true
436
+ }
437
+ }
304
438
  },
305
- {
306
- "pattern": "(^|/)src/(?:test|androidTest)/\\*\\*$"
307
- }
439
+ "uniqueItems": true,
440
+ "minItems": 1
441
+ }
442
+ }
443
+ }
444
+ },
445
+ "allOf": [
446
+ {
447
+ "if": {
448
+ "required": [
449
+ "capabilities"
308
450
  ]
451
+ },
452
+ "then": {},
453
+ "else": {
454
+ "properties": {
455
+ "productionPaths": {
456
+ "items": {
457
+ "allOf": [
458
+ {
459
+ "$ref": "#/$defs/repositoryPath"
460
+ },
461
+ {
462
+ "pattern": "(^|/)src/main/\\*\\*$"
463
+ }
464
+ ]
465
+ }
466
+ },
467
+ "testPaths": {
468
+ "items": {
469
+ "allOf": [
470
+ {
471
+ "$ref": "#/$defs/repositoryPath"
472
+ },
473
+ {
474
+ "pattern": "(^|/)src/(?:test|androidTest)/\\*\\*$"
475
+ }
476
+ ]
477
+ }
478
+ },
479
+ "modules": {
480
+ "items": {
481
+ "properties": {
482
+ "type": {
483
+ "enum": [
484
+ "application",
485
+ "library",
486
+ "dynamic-feature",
487
+ "test",
488
+ "asset-pack"
489
+ ]
490
+ }
491
+ }
492
+ }
493
+ }
494
+ }
309
495
  }
310
496
  }
311
- }
497
+ ]
312
498
  },
313
499
  "protectedPaths": {
314
500
  "type": "array",
@@ -356,15 +542,19 @@
356
542
  {
357
543
  "if": {
358
544
  "properties": {
359
- "workspaceStrategy": {
360
- "const": "isolatedWorktree"
545
+ "lintEnabled": {
546
+ "const": true
361
547
  }
362
548
  }
363
549
  },
364
550
  "then": {
365
551
  "properties": {
366
- "commitPolicy": {
367
- "const": "humanApproval"
552
+ "gradleVerification": {
553
+ "properties": {
554
+ "lintTasks": {
555
+ "minItems": 1
556
+ }
557
+ }
368
558
  }
369
559
  }
370
560
  }