@frankzhang2026/opencode-android-orchestrator 1.0.4 → 1.0.5

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.
@@ -79,6 +79,13 @@ jq -r '.nonGoals[] | "- \(.)"' "$report_file"
79
79
 
80
80
  printf '\n### P1 · 自动证据是否可信\n\n'
81
81
  printf -- '- RED 退出码:`%s`(应为非 0,证明测试先真实失败)\n' "$(jq -r '.evidence.redExitCode' "$report_file")"
82
+ if [[ "$(jq -r '.evidence.structuredRed != null' "$report_file")" == "true" ]]; then
83
+ printf -- '- 结构化 RED:声明 `%s` 个,用例匹配 `%s` 个,额外用例 `%s` 个\n' \
84
+ "$(jq -r '.evidence.structuredRed.summary.declared' "$report_file")" \
85
+ "$(jq -r '.evidence.structuredRed.summary.valid' "$report_file")" \
86
+ "$(jq -r '.evidence.structuredRed.summary.undeclared' "$report_file")"
87
+ jq -r '.evidence.structuredRed.cases[] | " - `\(.id)` · \(.intent) · 修改前应 \(.expectedBefore) · 已核验 \(.valid)"' "$report_file"
88
+ fi
82
89
  printf -- '- 质量门:`%s`,第 %s 个编码周期内共运行 %s 次\n' \
83
90
  "$(jq -r '.evidence.qualityGate' "$report_file")" \
84
91
  "$(jq -r '.evidence.codingCycle' "$report_file")" \
@@ -21,6 +21,8 @@ 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)"
24
26
  ready_json="$(if [[ -f "$evidence_dir/ready.json" ]]; then jq -c . "$evidence_dir/ready.json"; else printf 'null'; fi)"
25
27
  review_json="$(if [[ -f "$evidence_dir/review.json" ]]; then jq -c . "$evidence_dir/review.json"; else printf 'null'; fi)"
26
28
  gate_json=null
@@ -93,6 +95,8 @@ jq -n \
93
95
  --argjson origin "$origin_json" \
94
96
  --argjson baseline "$baseline_json" \
95
97
  --argjson red "$red_json" \
98
+ --argjson testPreflight "$preflight_json" \
99
+ --argjson testManifest "$manifest_json" \
96
100
  --argjson ready "$ready_json" \
97
101
  --argjson gate "$gate_json" \
98
102
  --argjson review "$review_json" \
@@ -118,6 +122,8 @@ jq -n \
118
122
  directory: $evidence,
119
123
  baseline: $baseline,
120
124
  red: $red,
125
+ testPreflight: $testPreflight,
126
+ testManifest: $testManifest,
121
127
  ready: $ready,
122
128
  latestGate: $gate,
123
129
  review: $review,
@@ -27,7 +27,7 @@ fi
27
27
  jq -e . "$contract" >/dev/null || automation_die "contract is not valid JSON: $contract"
28
28
 
29
29
  jq -e '
30
- (.schemaVersion == 1 or .schemaVersion == 2) and
30
+ (.schemaVersion == 1 or .schemaVersion == 2 or .schemaVersion == 3) and
31
31
  (.id | type == "string" and test("^TASK-[A-Z0-9-]+$")) and
32
32
  (.title | type == "string" and length > 0) and
33
33
  .designApproved == true and
@@ -53,7 +53,51 @@ jq -e '
53
53
  ([.targetTests[].filter] | length == (unique | length)) and
54
54
  (.deviceTestsRequired | type == "boolean") and
55
55
  (.testPolicy == "required" or .testPolicy == "not-required") and
56
- (if .testPolicy == "not-required" then (.testPolicyReason | type == "string" and length >= 20) else true end)
56
+ (if .testPolicy == "not-required" then (.testPolicyReason | type == "string" and length >= 20) else true end) and
57
+ (if .schemaVersion == 3 then
58
+ (.acceptanceCriteria | length) as $criterionCount |
59
+ (.targetTests | length) as $targetCount |
60
+ (.verification | type == "object" and
61
+ keys == ["cases", "maxPreparationFixes", "version"] and
62
+ .version == 1 and
63
+ (.maxPreparationFixes | type == "number" and floor == . and . >= 0 and . <= 1) and
64
+ (.cases | type == "array" and length > 0) and
65
+ ([.cases[].id] | length == (unique | length)) and
66
+ ([.cases[] | [.test.target, .test.className, .test.name] | @json] | length == (unique | length)) and
67
+ (any(.cases[]; .intent == "change")) and
68
+ all(.cases[];
69
+ type == "object" and
70
+ ([keys[]] - ["id", "criterion", "intent", "before", "after", "source", "test", "expectedFailure"] | length == 0) and
71
+ (.id | type == "string" and test("^[A-Z][A-Z0-9-]{2,63}$")) and
72
+ (.criterion | type == "number" and floor == . and . >= 1 and . <= $criterionCount) and
73
+ .after == "pass" and
74
+ (.test | type == "object" and keys == ["className", "name", "target"] and
75
+ (.target | type == "number" and floor == . and . >= 0 and . < $targetCount) and
76
+ (.className | type == "string" and length > 0) and
77
+ (.name | type == "string" and length > 0)) and
78
+ (if .intent == "preserve" then
79
+ .before == "pass" and
80
+ (.source == "existingTest" or .source == "baselineCapture" or .source == "measuredFact") and
81
+ (has("expectedFailure") | not)
82
+ elif .intent == "change" then
83
+ .before == "fail" and .source == "userRequirement" and
84
+ (.expectedFailure | type == "object" and
85
+ ([keys[]] - ["type", "messageIncludes", "origin"] | length == 0) and
86
+ (.type | type == "string" and length > 0) and
87
+ (.origin | type == "string" and length >= 12) and
88
+ (if has("messageIncludes") then (.messageIncludes | type == "string" and length >= 3) else true end))
89
+ elif .intent == "observe" then
90
+ .before == "observe" and
91
+ (.source == "userRequirement" or .source == "existingTest" or .source == "baselineCapture" or .source == "measuredFact") and
92
+ (if has("expectedFailure") then
93
+ (.expectedFailure | type == "object" and
94
+ ([keys[]] - ["type", "messageIncludes", "origin"] | length == 0) and
95
+ (.type | type == "string" and length > 0) and
96
+ (.origin | type == "string" and length >= 12) and
97
+ (if has("messageIncludes") then (.messageIncludes | type == "string" and length >= 3) else true end))
98
+ else true end)
99
+ else false end)))
100
+ else true end)
57
101
  ' "$contract" >/dev/null || automation_die "contract is missing required fields or violates limits"
58
102
 
59
103
  task_id="$(jq -r '.id' "$contract")"
@@ -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"