@frankzhang2026/opencode-android-orchestrator 1.0.4 → 1.1.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 +78 -0
- package/README.md +79 -18
- package/dist/config/queue-policy.d.ts.map +1 -1
- package/dist/config/queue-policy.js +1 -2
- package/dist/config/queue-policy.js.map +1 -1
- package/dist/doctor/index.d.ts.map +1 -1
- package/dist/doctor/index.js +14 -3
- package/dist/doctor/index.js.map +1 -1
- package/dist/doctor/installation.d.ts +1 -1
- package/dist/doctor/installation.d.ts.map +1 -1
- package/dist/doctor/installation.js +10 -1
- package/dist/doctor/installation.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/installer/adaptive-templates.d.ts +4 -1
- package/dist/installer/adaptive-templates.d.ts.map +1 -1
- package/dist/installer/adaptive-templates.js +49 -13
- package/dist/installer/adaptive-templates.js.map +1 -1
- package/dist/installer/android-project.d.ts +3 -1
- package/dist/installer/android-project.d.ts.map +1 -1
- package/dist/installer/android-project.js.map +1 -1
- package/dist/installer/capabilities-script.d.ts +2 -0
- package/dist/installer/capabilities-script.d.ts.map +1 -0
- package/dist/installer/capabilities-script.js +77 -0
- package/dist/installer/capabilities-script.js.map +1 -0
- package/dist/installer/gradle-verification.d.ts.map +1 -1
- package/dist/installer/gradle-verification.js +13 -6
- package/dist/installer/gradle-verification.js.map +1 -1
- package/dist/installer/init.d.ts.map +1 -1
- package/dist/installer/init.js +2 -1
- package/dist/installer/init.js.map +1 -1
- package/dist/installer/opencode-config.d.ts +3 -3
- package/dist/installer/opencode-config.js +1 -1
- package/dist/installer/project-capabilities.d.ts +35 -0
- package/dist/installer/project-capabilities.d.ts.map +1 -0
- package/dist/installer/project-capabilities.js +82 -0
- package/dist/installer/project-capabilities.js.map +1 -0
- package/dist/installer/upgrade.d.ts.map +1 -1
- package/dist/installer/upgrade.js +9 -1
- package/dist/installer/upgrade.js.map +1 -1
- package/dist/queue/cli.d.ts.map +1 -1
- package/dist/queue/cli.js +32 -5
- package/dist/queue/cli.js.map +1 -1
- package/dist/queue/executor.d.ts +1 -0
- package/dist/queue/executor.d.ts.map +1 -1
- package/dist/queue/executor.js +155 -11
- package/dist/queue/executor.js.map +1 -1
- package/dist/queue/process-ownership.d.ts +12 -0
- package/dist/queue/process-ownership.d.ts.map +1 -0
- package/dist/queue/process-ownership.js +58 -0
- package/dist/queue/process-ownership.js.map +1 -0
- package/dist/queue/queue.d.ts +25 -1
- package/dist/queue/queue.d.ts.map +1 -1
- package/dist/queue/queue.js +152 -11
- package/dist/queue/queue.js.map +1 -1
- package/dist/queue/service.d.ts.map +1 -1
- package/dist/queue/service.js +19 -2
- package/dist/queue/service.js.map +1 -1
- package/dist/queue/storage.d.ts +3 -1
- package/dist/queue/storage.d.ts.map +1 -1
- package/dist/queue/storage.js +25 -15
- package/dist/queue/storage.js.map +1 -1
- package/dist/queue/supervision.d.ts +38 -0
- package/dist/queue/supervision.d.ts.map +1 -0
- package/dist/queue/supervision.js +247 -0
- package/dist/queue/supervision.js.map +1 -0
- package/dist/queue/tools.d.ts.map +1 -1
- package/dist/queue/tools.js +4 -2
- package/dist/queue/tools.js.map +1 -1
- package/docs/MIGRATION.md +110 -9
- package/docs/QUEUE.md +360 -6
- package/docs/SECURITY.md +5 -2
- package/docs/TROUBLESHOOTING.md +82 -8
- package/package.json +1 -1
- package/templates/.opencode/agents/scheduled-coder.md +22 -0
- package/templates/.opencode/agents/scheduled-planner.md +73 -2
- package/templates/.opencode/skills/scheduled-quality-coder/SKILL.md +34 -2
- package/templates/.opencode/skills/scheduled-quality-orchestrator/SKILL.md +65 -4
- package/templates/.opencode/skills/scheduled-quality-reviewer/SKILL.md +22 -0
- package/templates/AGENTS.md.fragment +10 -4
- package/templates/README.md +3 -1
- package/templates/automation/config.schema.json +212 -22
- package/templates/automation/task-contract.schema.json +617 -21
- package/templates/automation/tasks/TASK-TEMPLATE.json.example +31 -3
- package/templates/automation/verification/collect.init.gradle +98 -0
- package/templates/automation/verification/contract.cjs +93 -0
- package/templates/automation/verification/inventory.cjs +433 -0
- package/templates/automation/verification/project.cjs +172 -0
- package/templates/automation/verification/recovery.cjs +426 -0
- package/templates/scripts/automation/acceptance-report.sh +29 -0
- package/templates/scripts/automation/claim-task.sh +35 -2
- package/templates/scripts/automation/integration-scope-gate.sh +3 -3
- package/templates/scripts/automation/lib.sh +167 -17
- package/templates/scripts/automation/orchestrate-task.sh +7 -1
- package/templates/scripts/automation/preflight.sh +1 -2
- package/templates/scripts/automation/quality-gate.sh +10 -1
- package/templates/scripts/automation/record-red.sh +182 -32
- package/templates/scripts/automation/resume-task.sh +3 -0
- package/templates/scripts/automation/scope-gate.sh +4 -4
- package/templates/scripts/automation/show-acceptance-review.sh +8 -0
- package/templates/scripts/automation/status.sh +38 -0
- package/templates/scripts/automation/submit-review.sh +10 -1
- package/templates/scripts/automation/validate-contract.sh +56 -3
- package/templates/scripts/automation/verify-integration.sh +3 -0
- package/templates/scripts/automation/verify-task.sh +17 -0
|
@@ -21,6 +21,28 @@ workspace_json="$(if [[ -f "$workspace_file" ]]; then jq -c . "$workspace_file";
|
|
|
21
21
|
origin_json="$(if [[ -f "$origin_file" ]]; then jq -c . "$origin_file"; else printf 'null'; fi)"
|
|
22
22
|
baseline_json="$(if [[ -f "$evidence_dir/baseline.json" ]]; then jq -c . "$evidence_dir/baseline.json"; else printf 'null'; fi)"
|
|
23
23
|
red_json="$(if [[ -f "$evidence_dir/red.json" ]]; then jq -c . "$evidence_dir/red.json"; else printf 'null'; fi)"
|
|
24
|
+
preflight_json="$(if [[ -f "$evidence_dir/test-preflight.json" ]]; then jq -c . "$evidence_dir/test-preflight.json"; else printf 'null'; fi)"
|
|
25
|
+
manifest_json="$(if [[ -f "$evidence_dir/test-manifest.json" ]]; then jq -c . "$evidence_dir/test-manifest.json"; else printf 'null'; fi)"
|
|
26
|
+
inventory_baseline_json="$(if [[ -f "$evidence_dir/baseline-inventory.json" ]]; then jq -c . "$evidence_dir/baseline-inventory.json"; else printf 'null'; fi)"
|
|
27
|
+
inventory_green_json="$(if [[ -f "$evidence_dir/green-inventory.json" ]]; then jq -c . "$evidence_dir/green-inventory.json"; else printf 'null'; fi)"
|
|
28
|
+
inventory_status_json="$(if [[ -f "$evidence_dir/inventory-status.json" ]]; then jq -c . "$evidence_dir/inventory-status.json"; else printf 'null'; fi)"
|
|
29
|
+
baseline_recovery_json="$(if [[ -f "$evidence_dir/baseline-recovery.json" ]]; then jq -c . "$evidence_dir/baseline-recovery.json"; else printf 'null'; fi)"
|
|
30
|
+
stage_recovery_json='{}'
|
|
31
|
+
for phase in red green review; do
|
|
32
|
+
if [[ -f "$evidence_dir/stage-recovery/$phase.json" ]]; then
|
|
33
|
+
stage_recovery_json="$(jq -nc --argjson current "$stage_recovery_json" --arg phase "$phase" \
|
|
34
|
+
--slurpfile record "$evidence_dir/stage-recovery/$phase.json" '$current + {($phase): $record[0]}')"
|
|
35
|
+
fi
|
|
36
|
+
done
|
|
37
|
+
supervision_json=null
|
|
38
|
+
if [[ -f "$AUTOMATION_RUNTIME_ROOT/inbox/queue.json" ]]; then
|
|
39
|
+
supervision_json="$(jq -c --arg task "$task_id" '
|
|
40
|
+
([.items[]? | select(.taskId == $task)] | last | .key) as $key |
|
|
41
|
+
([.runs[]?, .active] | map(select(.key == $key)) | last | .supervision) |
|
|
42
|
+
if . == null then null else {state, stage, deadline, stageDeadline, stopReason, termAt, killAt} end
|
|
43
|
+
' "$AUTOMATION_RUNTIME_ROOT/inbox/queue.json")"
|
|
44
|
+
supervision_json="${supervision_json:-null}"
|
|
45
|
+
fi
|
|
24
46
|
ready_json="$(if [[ -f "$evidence_dir/ready.json" ]]; then jq -c . "$evidence_dir/ready.json"; else printf 'null'; fi)"
|
|
25
47
|
review_json="$(if [[ -f "$evidence_dir/review.json" ]]; then jq -c . "$evidence_dir/review.json"; else printf 'null'; fi)"
|
|
26
48
|
gate_json=null
|
|
@@ -93,6 +115,14 @@ jq -n \
|
|
|
93
115
|
--argjson origin "$origin_json" \
|
|
94
116
|
--argjson baseline "$baseline_json" \
|
|
95
117
|
--argjson red "$red_json" \
|
|
118
|
+
--argjson testPreflight "$preflight_json" \
|
|
119
|
+
--argjson testManifest "$manifest_json" \
|
|
120
|
+
--argjson baselineInventory "$inventory_baseline_json" \
|
|
121
|
+
--argjson greenInventory "$inventory_green_json" \
|
|
122
|
+
--argjson inventoryStatus "$inventory_status_json" \
|
|
123
|
+
--argjson baselineRecovery "$baseline_recovery_json" \
|
|
124
|
+
--argjson stageRecovery "$stage_recovery_json" \
|
|
125
|
+
--argjson workerSupervision "$supervision_json" \
|
|
96
126
|
--argjson ready "$ready_json" \
|
|
97
127
|
--argjson gate "$gate_json" \
|
|
98
128
|
--argjson review "$review_json" \
|
|
@@ -118,6 +148,14 @@ jq -n \
|
|
|
118
148
|
directory: $evidence,
|
|
119
149
|
baseline: $baseline,
|
|
120
150
|
red: $red,
|
|
151
|
+
testPreflight: $testPreflight,
|
|
152
|
+
testManifest: $testManifest,
|
|
153
|
+
baselineInventory: $baselineInventory,
|
|
154
|
+
greenInventory: $greenInventory,
|
|
155
|
+
inventoryStatus: $inventoryStatus,
|
|
156
|
+
baselineRecovery: $baselineRecovery,
|
|
157
|
+
stageRecovery: $stageRecovery,
|
|
158
|
+
workerSupervision: $workerSupervision,
|
|
121
159
|
ready: $ready,
|
|
122
160
|
latestGate: $gate,
|
|
123
161
|
review: $review,
|
|
@@ -36,9 +36,18 @@ review_log="$evidence_dir/review-verification.log"
|
|
|
36
36
|
verification_status=0
|
|
37
37
|
if [[ "$decision" == "APPROVED" ]]; then
|
|
38
38
|
set +e
|
|
39
|
-
"$
|
|
39
|
+
contract="$(automation_contract_path "$task_id")"
|
|
40
|
+
if [[ "$(jq -r '.schemaVersion' "$contract")" -ge "7" ]]; then
|
|
41
|
+
node "$AUTOMATION_ROOT/automation/verification/recovery.cjs" --stage review "$contract" "$AUTOMATION_CONFIG" "$AUTOMATION_ROOT" "$evidence_dir" 2>&1 | tee "$review_log"
|
|
42
|
+
else
|
|
43
|
+
"$SCRIPT_DIR/verify-task.sh" "$task_id" 2>&1 | tee "$review_log"
|
|
44
|
+
fi
|
|
40
45
|
verification_status=${PIPESTATUS[0]}
|
|
41
46
|
set -e
|
|
47
|
+
if [[ "$(jq -r '.schemaVersion' "$contract")" -ge "7" && ( "$verification_status" -eq 75 || "$verification_status" -eq 76 ) ]]; then
|
|
48
|
+
automation_transition_state "$task_id" "REVIEWING" "BLOCKED" "reviewer" "independent verification stopped; inspect stage-recovery/review.json; no implementation change requested"
|
|
49
|
+
exit "$verification_status"
|
|
50
|
+
fi
|
|
42
51
|
if [[ "$verification_status" -ne 0 ]]; then
|
|
43
52
|
decision="CHANGES_REQUESTED"
|
|
44
53
|
summary="Independent verification failed with exit $verification_status. $summary"
|
|
@@ -26,8 +26,12 @@ fi
|
|
|
26
26
|
[[ -f "$contract" ]] || automation_die "contract not found: $contract"
|
|
27
27
|
jq -e . "$contract" >/dev/null || automation_die "contract is not valid JSON: $contract"
|
|
28
28
|
|
|
29
|
+
if [[ "$(jq -r '.schemaVersion' "$contract")" -ge "4" ]]; then
|
|
30
|
+
node "$AUTOMATION_ROOT/automation/verification/contract.cjs" "$contract" "$AUTOMATION_CONFIG" || \
|
|
31
|
+
automation_die "V4/V5 contract validation failed"
|
|
32
|
+
else
|
|
29
33
|
jq -e '
|
|
30
|
-
(.schemaVersion == 1 or .schemaVersion == 2) and
|
|
34
|
+
(.schemaVersion == 1 or .schemaVersion == 2 or .schemaVersion == 3) and
|
|
31
35
|
(.id | type == "string" and test("^TASK-[A-Z0-9-]+$")) and
|
|
32
36
|
(.title | type == "string" and length > 0) and
|
|
33
37
|
.designApproved == true and
|
|
@@ -53,11 +57,60 @@ jq -e '
|
|
|
53
57
|
([.targetTests[].filter] | length == (unique | length)) and
|
|
54
58
|
(.deviceTestsRequired | type == "boolean") and
|
|
55
59
|
(.testPolicy == "required" or .testPolicy == "not-required") and
|
|
56
|
-
(if .testPolicy == "not-required" then (.testPolicyReason | type == "string" and length >= 20) else true end)
|
|
60
|
+
(if .testPolicy == "not-required" then (.testPolicyReason | type == "string" and length >= 20) else true end) and
|
|
61
|
+
(if .schemaVersion == 3 then
|
|
62
|
+
(.acceptanceCriteria | length) as $criterionCount |
|
|
63
|
+
(.targetTests | length) as $targetCount |
|
|
64
|
+
(.verification | type == "object" and
|
|
65
|
+
keys == ["cases", "maxPreparationFixes", "version"] and
|
|
66
|
+
.version == 1 and
|
|
67
|
+
(.maxPreparationFixes | type == "number" and floor == . and . >= 0 and . <= 1) and
|
|
68
|
+
(.cases | type == "array" and length > 0) and
|
|
69
|
+
([.cases[].id] | length == (unique | length)) and
|
|
70
|
+
([.cases[] | [.test.target, .test.className, .test.name] | @json] | length == (unique | length)) and
|
|
71
|
+
(any(.cases[]; .intent == "change")) and
|
|
72
|
+
all(.cases[];
|
|
73
|
+
type == "object" and
|
|
74
|
+
([keys[]] - ["id", "criterion", "intent", "before", "after", "source", "test", "expectedFailure"] | length == 0) and
|
|
75
|
+
(.id | type == "string" and test("^[A-Z][A-Z0-9-]{2,63}$")) and
|
|
76
|
+
(.criterion | type == "number" and floor == . and . >= 1 and . <= $criterionCount) and
|
|
77
|
+
.after == "pass" and
|
|
78
|
+
(.test | type == "object" and keys == ["className", "name", "target"] and
|
|
79
|
+
(.target | type == "number" and floor == . and . >= 0 and . < $targetCount) and
|
|
80
|
+
(.className | type == "string" and length > 0) and
|
|
81
|
+
(.name | type == "string" and length > 0)) and
|
|
82
|
+
(if .intent == "preserve" then
|
|
83
|
+
.before == "pass" and
|
|
84
|
+
(.source == "existingTest" or .source == "baselineCapture" or .source == "measuredFact") and
|
|
85
|
+
(has("expectedFailure") | not)
|
|
86
|
+
elif .intent == "change" then
|
|
87
|
+
.before == "fail" and .source == "userRequirement" and
|
|
88
|
+
(.expectedFailure | type == "object" and
|
|
89
|
+
([keys[]] - ["type", "messageIncludes", "origin"] | length == 0) and
|
|
90
|
+
(.type | type == "string" and length > 0) and
|
|
91
|
+
(.origin | type == "string" and length >= 12) and
|
|
92
|
+
(if has("messageIncludes") then (.messageIncludes | type == "string" and length >= 3) else true end))
|
|
93
|
+
elif .intent == "observe" then
|
|
94
|
+
.before == "observe" and
|
|
95
|
+
(.source == "userRequirement" or .source == "existingTest" or .source == "baselineCapture" or .source == "measuredFact") and
|
|
96
|
+
(if has("expectedFailure") then
|
|
97
|
+
(.expectedFailure | type == "object" and
|
|
98
|
+
([keys[]] - ["type", "messageIncludes", "origin"] | length == 0) and
|
|
99
|
+
(.type | type == "string" and length > 0) and
|
|
100
|
+
(.origin | type == "string" and length >= 12) and
|
|
101
|
+
(if has("messageIncludes") then (.messageIncludes | type == "string" and length >= 3) else true end))
|
|
102
|
+
else true end)
|
|
103
|
+
else false end)))
|
|
104
|
+
else true end)
|
|
57
105
|
' "$contract" >/dev/null || automation_die "contract is missing required fields or violates limits"
|
|
106
|
+
fi
|
|
58
107
|
|
|
59
108
|
task_id="$(jq -r '.id' "$contract")"
|
|
60
109
|
automation_validate_task_id "$task_id"
|
|
110
|
+
if [[ "$(jq -r '.deviceTestsRequired' "$contract")" == "true" ]]; then
|
|
111
|
+
jq -e '.gradleVerification.deviceTestTasks | length > 0' "$AUTOMATION_CONFIG" >/dev/null || \
|
|
112
|
+
automation_die "Device tests are required by this contract but no device test tasks are available"
|
|
113
|
+
fi
|
|
61
114
|
|
|
62
115
|
if [[ "$contract" == "$AUTOMATION_TASKS_DIR/"* ]]; then
|
|
63
116
|
expected_contract="$(automation_contract_path "$task_id")"
|
|
@@ -89,7 +142,7 @@ while IFS=$'\t' read -r gradle_task filter; do
|
|
|
89
142
|
automation_die "target test Gradle task is not allowed by automation/config.json: $gradle_task"
|
|
90
143
|
done < <(jq -r '.targetTests[] | [.gradleTask, .filter] | @tsv' "$contract")
|
|
91
144
|
|
|
92
|
-
if rg -n -i 'replace with|TASK-EXAMPLE|todo|tbd|placeholder' "$contract" >/dev/null; then
|
|
145
|
+
if [[ "$(jq -r '.schemaVersion' "$contract")" -lt "4" ]] && rg -n -i 'replace with|TASK-EXAMPLE|todo|tbd|placeholder' "$contract" >/dev/null; then
|
|
93
146
|
automation_die "contract still contains template placeholders"
|
|
94
147
|
fi
|
|
95
148
|
|
|
@@ -28,4 +28,7 @@ if [[ "$(jq -r '.deviceTestsRequired' "$contract")" == "true" ]]; then
|
|
|
28
28
|
automation_run_gradle_group "deviceTestTasks" "$AUTOMATION_ROOT"
|
|
29
29
|
fi
|
|
30
30
|
|
|
31
|
+
if [[ "$(jq -r '.schemaVersion' "$contract")" -ge "4" ]]; then
|
|
32
|
+
automation_run_inventory check "$task_id"
|
|
33
|
+
fi
|
|
31
34
|
automation_info "integration candidate passed all deterministic verification"
|
|
@@ -15,6 +15,20 @@ evidence_dir="$(automation_evidence_path "$task_id")"
|
|
|
15
15
|
[[ -f "$evidence_dir/baseline.json" ]] || { automation_die "baseline evidence is missing"; exit 41; }
|
|
16
16
|
[[ -f "$evidence_dir/red.json" ]] || { automation_die "RED evidence is missing"; exit 41; }
|
|
17
17
|
|
|
18
|
+
contract_schema="$(jq -er '.schemaVersion' "$contract")"
|
|
19
|
+
if [[ "$contract_schema" == "3" ]]; then
|
|
20
|
+
preflight_meta="$evidence_dir/test-preflight.json"
|
|
21
|
+
manifest_meta="$evidence_dir/test-manifest.json"
|
|
22
|
+
red_meta="$evidence_dir/red.json"
|
|
23
|
+
[[ -f "$preflight_meta" && -f "$manifest_meta" ]] || { automation_die "structured RED evidence is incomplete"; exit 41; }
|
|
24
|
+
[[ "$(jq -er '.valid' "$preflight_meta")" == "true" ]] || { automation_die "structured RED preflight was not valid"; exit 41; }
|
|
25
|
+
[[ "$(jq -er '.contractSha256' "$red_meta")" == "$(automation_file_sha256 "$contract")" ]] || { automation_die "RED contract binding changed"; exit 41; }
|
|
26
|
+
[[ "$(jq -er '.baselineHead' "$red_meta")" == "$(jq -er '.head' "$evidence_dir/baseline.json")" ]] || { automation_die "RED baseline binding changed"; exit 41; }
|
|
27
|
+
[[ "$(jq -er '.testDiffSha256' "$red_meta")" == "$(automation_test_diff_sha "$task_id" "$AUTOMATION_ROOT")" ]] || { automation_die "tests changed after structured RED"; exit 41; }
|
|
28
|
+
[[ "$(jq -er '.preflightSha256' "$red_meta")" == "$(automation_file_sha256 "$preflight_meta")" ]] || { automation_die "RED preflight evidence changed"; exit 41; }
|
|
29
|
+
[[ "$(jq -er '.manifestSha256' "$red_meta")" == "$(automation_file_sha256 "$manifest_meta")" ]] || { automation_die "RED test manifest changed"; exit 41; }
|
|
30
|
+
fi
|
|
31
|
+
|
|
18
32
|
"$SCRIPT_DIR/scope-gate.sh" "$task_id"
|
|
19
33
|
|
|
20
34
|
automation_run_configured_unit_tests "$contract" "$AUTOMATION_ROOT"
|
|
@@ -30,6 +44,9 @@ if [[ "$(jq -r '.deviceTestsRequired' "$contract")" == "true" ]]; then
|
|
|
30
44
|
fi
|
|
31
45
|
|
|
32
46
|
automation_info "all deterministic verification commands passed"
|
|
47
|
+
if [[ "$contract_schema" -ge "4" ]]; then
|
|
48
|
+
automation_run_inventory check "$task_id"
|
|
49
|
+
fi
|
|
33
50
|
if [[ -n "${AUTOMATION_QUEUE_RUN_ID:-}" ]]; then
|
|
34
51
|
[[ -n "${AUTOMATION_FULL_TEST_LOG:-}" ]] || automation_die "fresh full unit-test evidence is missing"
|
|
35
52
|
jq -n \
|