@hunter-harness/workflow-harness 0.2.28 → 0.2.29

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 (138) hide show
  1. package/harness/bundles/general/claude-code/.harness-build.json +1 -1
  2. package/harness/bundles/general/claude-code/contracts/workflow-policy.json +34 -2
  3. package/harness/bundles/general/claude-code/harness-archive/SKILL.md +1 -1
  4. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
  5. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  6. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
  7. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +1 -1
  8. package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
  9. package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
  10. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +1 -1
  11. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
  12. package/harness/bundles/general/claude-code/harness-test/SKILL.md +26 -2
  13. package/harness/bundles/general/claude-code/harness-test/checklist.md +15 -0
  14. package/harness/bundles/general/claude-code/harness-test/reference.md +28 -4
  15. package/harness/bundles/general/claude-code/scripts/harness_test_runner.py +974 -0
  16. package/harness/bundles/general/claude-code/scripts/harness_workflow_policy.py +87 -0
  17. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  18. package/harness/bundles/general/codebuddy/contracts/workflow-policy.json +34 -2
  19. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
  20. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
  21. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  22. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  23. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +1 -1
  24. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
  25. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
  26. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +1 -1
  27. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
  28. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +26 -2
  29. package/harness/bundles/general/codebuddy/harness-test/checklist.md +15 -0
  30. package/harness/bundles/general/codebuddy/harness-test/reference.md +28 -4
  31. package/harness/bundles/general/codebuddy/scripts/harness_test_runner.py +974 -0
  32. package/harness/bundles/general/codebuddy/scripts/harness_workflow_policy.py +87 -0
  33. package/harness/bundles/general/codex/.harness-build.json +1 -1
  34. package/harness/bundles/general/codex/contracts/workflow-policy.json +34 -2
  35. package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
  36. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
  37. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
  38. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
  39. package/harness/bundles/general/codex/harness-plan/SKILL.md +1 -1
  40. package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
  41. package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
  42. package/harness/bundles/general/codex/harness-submit/SKILL.md +1 -1
  43. package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
  44. package/harness/bundles/general/codex/harness-test/SKILL.md +26 -2
  45. package/harness/bundles/general/codex/harness-test/checklist.md +15 -0
  46. package/harness/bundles/general/codex/harness-test/reference.md +28 -4
  47. package/harness/bundles/general/codex/scripts/harness_test_runner.py +974 -0
  48. package/harness/bundles/general/codex/scripts/harness_workflow_policy.py +87 -0
  49. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  50. package/harness/bundles/general/cursor/contracts/workflow-policy.json +34 -2
  51. package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
  52. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
  53. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  54. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
  55. package/harness/bundles/general/cursor/harness-plan/SKILL.md +1 -1
  56. package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
  57. package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
  58. package/harness/bundles/general/cursor/harness-submit/SKILL.md +1 -1
  59. package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
  60. package/harness/bundles/general/cursor/harness-test/SKILL.md +26 -2
  61. package/harness/bundles/general/cursor/harness-test/checklist.md +15 -0
  62. package/harness/bundles/general/cursor/harness-test/reference.md +28 -4
  63. package/harness/bundles/general/cursor/scripts/harness_test_runner.py +974 -0
  64. package/harness/bundles/general/cursor/scripts/harness_workflow_policy.py +87 -0
  65. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  66. package/harness/bundles/java/claude-code/contracts/workflow-policy.json +34 -2
  67. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
  68. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
  69. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
  70. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  71. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
  72. package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
  73. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +1 -1
  74. package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
  75. package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
  76. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +1 -1
  77. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
  78. package/harness/bundles/java/claude-code/harness-test/SKILL.md +26 -2
  79. package/harness/bundles/java/claude-code/scripts/harness_test_runner.py +974 -0
  80. package/harness/bundles/java/claude-code/scripts/harness_workflow_policy.py +87 -0
  81. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  82. package/harness/bundles/java/codebuddy/contracts/workflow-policy.json +34 -2
  83. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
  84. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
  85. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
  86. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  87. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  88. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
  89. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +1 -1
  90. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
  91. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
  92. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +1 -1
  93. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
  94. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +26 -2
  95. package/harness/bundles/java/codebuddy/scripts/harness_test_runner.py +974 -0
  96. package/harness/bundles/java/codebuddy/scripts/harness_workflow_policy.py +87 -0
  97. package/harness/bundles/java/codex/.harness-build.json +1 -1
  98. package/harness/bundles/java/codex/contracts/workflow-policy.json +34 -2
  99. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
  100. package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
  101. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
  102. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
  103. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
  104. package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
  105. package/harness/bundles/java/codex/harness-plan/SKILL.md +1 -1
  106. package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
  107. package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
  108. package/harness/bundles/java/codex/harness-submit/SKILL.md +1 -1
  109. package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
  110. package/harness/bundles/java/codex/harness-test/SKILL.md +26 -2
  111. package/harness/bundles/java/codex/scripts/harness_test_runner.py +974 -0
  112. package/harness/bundles/java/codex/scripts/harness_workflow_policy.py +87 -0
  113. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  114. package/harness/bundles/java/cursor/contracts/workflow-policy.json +34 -2
  115. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
  116. package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
  117. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
  118. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  119. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
  120. package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
  121. package/harness/bundles/java/cursor/harness-plan/SKILL.md +1 -1
  122. package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
  123. package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
  124. package/harness/bundles/java/cursor/harness-submit/SKILL.md +1 -1
  125. package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
  126. package/harness/bundles/java/cursor/harness-test/SKILL.md +26 -2
  127. package/harness/bundles/java/cursor/scripts/harness_test_runner.py +974 -0
  128. package/harness/bundles/java/cursor/scripts/harness_workflow_policy.py +87 -0
  129. package/harness/manifests/general/claude-code.json +20 -16
  130. package/harness/manifests/general/codebuddy.json +20 -16
  131. package/harness/manifests/general/codex.json +20 -16
  132. package/harness/manifests/general/cursor.json +20 -16
  133. package/harness/manifests/java/claude-code.json +20 -16
  134. package/harness/manifests/java/codebuddy.json +20 -16
  135. package/harness/manifests/java/codex.json +20 -16
  136. package/harness/manifests/java/cursor.json +20 -16
  137. package/hunter-workflow-family.json +2 -2
  138. package/package.json +1 -1
@@ -15,6 +15,7 @@ POLICY_REL = Path("harness") / "contracts" / "workflow-policy.json"
15
15
  TOP_LEVEL_KEYS = frozenset(
16
16
  {
17
17
  "schemaVersion",
18
+ "testExecution",
18
19
  "riskTiers",
19
20
  "skills",
20
21
  "requiredArtifacts",
@@ -62,6 +63,27 @@ CHECKPOINT_RULE_KEYS = frozenset(
62
63
  "reviewerTool",
63
64
  }
64
65
  )
66
+ TEST_EXECUTION_KEYS = frozenset(
67
+ {
68
+ "runner",
69
+ "defaultProfile",
70
+ "maxWorkers",
71
+ "singleInstance",
72
+ "processTreeCleanup",
73
+ "detachedProcessPreflight",
74
+ "confirmationFlag",
75
+ "confirmationRequiredProfiles",
76
+ "resourceIntensiveModules",
77
+ "profiles",
78
+ }
79
+ )
80
+ TEST_EXECUTION_PROFILE_KEYS = frozenset(
81
+ {
82
+ "description",
83
+ "includesResourceIntensive",
84
+ "moduleTimeoutSeconds",
85
+ }
86
+ )
65
87
 
66
88
 
67
89
  class PolicyValidationError(ValueError):
@@ -94,6 +116,71 @@ def validate_policy(data: Any) -> dict[str, Any]:
94
116
  if data["schemaVersion"] != 1:
95
117
  raise PolicyValidationError("unsupported schemaVersion")
96
118
 
119
+ test_execution = data["testExecution"]
120
+ _require_type(test_execution, dict, "testExecution")
121
+ _reject_unknown(test_execution, TEST_EXECUTION_KEYS, "testExecution")
122
+ for key in ("runner", "defaultProfile", "confirmationFlag"):
123
+ _require_type(test_execution[key], str, f"testExecution.{key}")
124
+ max_workers = test_execution["maxWorkers"]
125
+ _require_type(max_workers, int, "testExecution.maxWorkers")
126
+ if isinstance(max_workers, bool) or max_workers < 1 or max_workers > 2:
127
+ raise PolicyValidationError("testExecution.maxWorkers must be 1 or 2")
128
+ for key in (
129
+ "singleInstance",
130
+ "processTreeCleanup",
131
+ "detachedProcessPreflight",
132
+ ):
133
+ _require_type(test_execution[key], bool, f"testExecution.{key}")
134
+ if not test_execution[key]:
135
+ raise PolicyValidationError(f"testExecution.{key} must be true")
136
+ for key in ("confirmationRequiredProfiles", "resourceIntensiveModules"):
137
+ values = test_execution[key]
138
+ _require_type(values, list, f"testExecution.{key}")
139
+ if any(not isinstance(item, str) or not item for item in values):
140
+ raise PolicyValidationError(
141
+ f"testExecution.{key} must contain non-empty strings"
142
+ )
143
+
144
+ execution_profiles = test_execution["profiles"]
145
+ _require_type(execution_profiles, dict, "testExecution.profiles")
146
+ required_profile_names = {"safe", "system", "full"}
147
+ if set(execution_profiles) != required_profile_names:
148
+ raise PolicyValidationError(
149
+ "testExecution.profiles must define exactly safe, system, and full"
150
+ )
151
+ if test_execution["defaultProfile"] != "safe":
152
+ raise PolicyValidationError("testExecution.defaultProfile must be safe")
153
+ confirmation_profiles = set(test_execution["confirmationRequiredProfiles"])
154
+ if not {"system", "full"}.issubset(confirmation_profiles):
155
+ raise PolicyValidationError(
156
+ "testExecution confirmation must cover system and full"
157
+ )
158
+ for profile_name, profile in execution_profiles.items():
159
+ path = f"testExecution.profiles.{profile_name}"
160
+ _require_type(profile, dict, path)
161
+ _reject_unknown(profile, TEST_EXECUTION_PROFILE_KEYS, path)
162
+ _require_type(profile["description"], str, f"{path}.description")
163
+ _require_type(
164
+ profile["includesResourceIntensive"],
165
+ bool,
166
+ f"{path}.includesResourceIntensive",
167
+ )
168
+ timeout = profile["moduleTimeoutSeconds"]
169
+ _require_type(timeout, int, f"{path}.moduleTimeoutSeconds")
170
+ if isinstance(timeout, bool) or timeout <= 0:
171
+ raise PolicyValidationError(
172
+ f"{path}.moduleTimeoutSeconds must be a positive integer"
173
+ )
174
+ if execution_profiles["safe"]["includesResourceIntensive"]:
175
+ raise PolicyValidationError(
176
+ "testExecution.profiles.safe must exclude resource-intensive tests"
177
+ )
178
+ for profile_name in ("system", "full"):
179
+ if not execution_profiles[profile_name]["includesResourceIntensive"]:
180
+ raise PolicyValidationError(
181
+ f"testExecution.profiles.{profile_name} must include resource-intensive tests"
182
+ )
183
+
97
184
  risk_tiers = data["riskTiers"]
98
185
  _require_type(risk_tiers, dict, "riskTiers")
99
186
  for tier_name, tier in risk_tiers.items():
@@ -2,5 +2,5 @@
2
2
  "schemaVersion": 1,
3
3
  "overlay": "java",
4
4
  "agent": "claude-code",
5
- "coreHash": "305f32827cd4de18"
5
+ "coreHash": "777d8783b2b2f001"
6
6
  }
@@ -1,5 +1,36 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
+ "testExecution": {
4
+ "runner": "harness/scripts/harness_test_runner.py",
5
+ "defaultProfile": "safe",
6
+ "maxWorkers": 2,
7
+ "singleInstance": true,
8
+ "processTreeCleanup": true,
9
+ "detachedProcessPreflight": true,
10
+ "confirmationFlag": "--confirm-resource-intensive",
11
+ "confirmationRequiredProfiles": ["system", "full"],
12
+ "resourceIntensiveModules": [
13
+ "test_harness_integration.py",
14
+ "test_harness_service.py"
15
+ ],
16
+ "profiles": {
17
+ "safe": {
18
+ "description": "Default low-load profile; runs regular test modules sequentially in isolated processes.",
19
+ "includesResourceIntensive": false,
20
+ "moduleTimeoutSeconds": 300
21
+ },
22
+ "system": {
23
+ "description": "Runs integration and service-lifecycle modules only after explicit confirmation.",
24
+ "includesResourceIntensive": true,
25
+ "moduleTimeoutSeconds": 600
26
+ },
27
+ "full": {
28
+ "description": "Runs regular modules followed by resource-intensive modules after explicit confirmation.",
29
+ "includesResourceIntensive": true,
30
+ "moduleTimeoutSeconds": 600
31
+ }
32
+ }
33
+ },
3
34
  "riskTiers": {
4
35
  "fast": {
5
36
  "description": "Low-risk docs/comments/non-behavioral config; no API/DB/security/concurrency. Policy notes: checkpointRules apply only when meta/implementation-checkpoints.json defines the entry for this change; missing file/entry = disabled (gate must not require --task).",
@@ -45,8 +76,8 @@
45
76
  "inputs": ["test-scenarios", "verification-ledger"],
46
77
  "artifacts": ["test-reports", "verification-ledger"],
47
78
  "events": ["phase.start", "phase.end", "command", "verification"],
48
- "allowedInteractions": [],
49
- "capabilities": ["gate-begin", "gate-close", "test-guard", "ledger-record"]
79
+ "allowedInteractions": ["resource-intensive-test-confirmation"],
80
+ "capabilities": ["gate-begin", "gate-close", "test-guard", "ledger-record", "resource-safe-test-runner"]
50
81
  },
51
82
  "harness-review": {
52
83
  "phase": "review",
@@ -184,6 +215,7 @@
184
215
  },
185
216
  "interactionWhitelist": {
186
217
  "global": [],
218
+ "harness-test": ["resource-intensive-test-confirmation"],
187
219
  "harness-submit": ["merge-conflict-resolution"],
188
220
  "harness-plan": ["risk-confirmation"]
189
221
  },
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
24
24
  # harness-apidoc — 前端接口文档(Java overlay)
25
25
 
26
26
  ## Purpose
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
24
24
  # harness-archive — 变更归档
25
25
 
26
26
  ## Purpose
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
24
24
  # harness-codebase-map — 代码库地图
25
25
 
26
26
  ## Purpose
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
24
24
  # harness-knowledge-ingest
25
25
 
26
26
  从 `.harness/archive/**/reports/final/summary-data.json` 抽取项目知识,生成并维护本地 `.harness/knowledge/` 索引。
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
24
24
  # harness-knowledge-query
25
25
 
26
26
  并行 change 中查询必须传 `--change <change-id>`;成功后以该 change 的 `meta/knowledge-context.json` 为稳定指针。全局 `context-packs/latest.json` 仅向后兼容,不得用于判断多个 active change 的上下文归属。
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
24
24
  # harness-package — 增量模块打包(Java overlay)
25
25
 
26
26
  ## Purpose
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
24
24
  # harness-plan — 需求规划
25
25
 
26
26
  ## Purpose
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(curl *)
22
22
  - Bash(codegraph *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
25
25
  # harness-review — 代码审查
26
26
 
27
27
  ## Purpose
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(curl *)
22
22
  - Bash(codegraph *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
25
25
  # harness-run — 需求编码
26
26
 
27
27
  ## Purpose
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
24
24
  # harness-submit — 最终提交(含 worktree 合并)
25
25
 
26
26
  ## Purpose
@@ -19,7 +19,7 @@ disallowed-tools:
19
19
  - Bash(awk *)
20
20
  - Bash(curl *)
21
21
  ---
22
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
22
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
23
23
  # harness-sync — 元数据同步
24
24
 
25
25
  ## Purpose
@@ -22,7 +22,7 @@ disallowed-tools:
22
22
  - Bash(node *)
23
23
  - Bash(codegraph *)
24
24
  ---
25
- <!-- generated by harness_deploy.py; core=305f32827cd4de18; overlay=java; agent=claude-code; do not edit -->
25
+ <!-- generated by harness_deploy.py; core=777d8783b2b2f001; overlay=java; agent=claude-code; do not edit -->
26
26
  # harness-test — 测试执行
27
27
 
28
28
  ## Purpose
@@ -67,6 +67,29 @@ disallowed-tools:
67
67
 
68
68
  并行服务测试先运行 `harness_change.py lease-port --change <id> --run-id <run-id> --range <start-end> --json`,再把返回端口传给 `harness_service.py ensure --leased-port <port> --lease-owner <run-id>`。`serviceStart` 的 command/health/overlay 可用 `{leasedPort}` 占位符;用户自启进程仍只进入 Service Gate,禁止 kill。测试清理的 `finally` 中运行 `harness_change.py release-port --change <id> --run-id <run-id> --json`,避免租约池耗尽。
69
69
 
70
+ ### Phase -1:资源安全门(任何测试命令之前)
71
+
72
+ 测试默认使用 `safe` 资源档位,禁止直接执行会把整套测试放进同一长生命周期的裸命令。所有本地测试命令必须由 `harness/scripts/harness_test_runner.py` 托管:
73
+
74
+ ```text
75
+ python harness/scripts/harness_test_runner.py exec --profile safe --timeout-seconds <秒> -- <测试命令及参数>
76
+ ```
77
+
78
+ 对于 Python `unittest` 测试库,必须使用逐模块隔离模式,不得执行裸 `python -m unittest discover ...`:
79
+
80
+ ```text
81
+ python harness/scripts/harness_test_runner.py unittest --profile safe --tests-dir <测试目录>
82
+ ```
83
+
84
+ 资源档位是硬合同:
85
+
86
+ - `safe`:默认;普通测试模块串行执行,每个模块使用全新进程。
87
+ - `system`:只执行服务生命周期、集成等资源密集型模块。
88
+ - `full`:先执行普通模块,再执行资源密集型模块;仍保持逐模块串行。
89
+ - `system` / `full` 只有在用户明确要求资源密集型测试、传入 `--confirm-resource-intensive`,或受控 CI 设置 `CI=true` / `HARNESS_ALLOW_RESOURCE_INTENSIVE_TESTS=1` 时才允许执行。
90
+
91
+ Runner 强制同项目单实例、低调度优先级、逐命令超时、正常结束和异常结束的进程树清理。`HARNESS_TEST_MAX_WORKERS` 默认且最高为 `2`,只能调低,不能调高;技术栈自身的并发参数也必须收敛到该值。Windows detached-service 模块在执行前先做 nested-breakaway 能力探测,受限沙箱不支持时立即返回 `DETACHED_PROCESS_CAPABILITY_UNAVAILABLE`,不得让每个服务用例逐一超时。出现该错误、`TEST_RUN_ALREADY_ACTIVE`、`PROCESS_TREE_ISOLATION_UNAVAILABLE` 或 `TEST_COMMAND_TIMEOUT` 必须停止,不得绕过 Runner 重跑裸命令。完整约束见 `checklist.md`「0.0-A 资源安全档位」。
92
+
70
93
  ### Phase 0:环境准备(主会话执行,需要交互确认)
71
94
 
72
95
  先 `harness_change.py resolve [--change] --json` 解析 change-id;再 **`harness_gate.py begin --phase test --change <id>`**(禁止手工 phase.start / 手写 ledger)。执行各项强制环境检查 + **命令执行模式 preflight (0.1)**;只有首选执行器不可用时,才执行 fallback 执行器探测。
@@ -146,7 +169,7 @@ Phase 1 前先读 `.harness/changes/<change-name>/evidence/verification-ledger.j
146
169
 
147
170
  ### 五、命令与请求超时治理
148
171
 
149
- 所有命令必须有「预期时长 + 超时上限」,超过预期必须输出一次状态行,**不得静默等待**。`durationMs > 10000` → 🟡 SLOW,`> 30000` → ❌ TIMEOUT_RISK。详见 `reference.md`「命令与请求超时治理」。
172
+ 所有命令必须通过资源安全 Runner 设置「预期时长 + 超时上限」,超过预期必须输出一次状态行,**不得静默等待**。测试模块超时或退出时必须清理其进程树;`durationMs > 10000` → 🟡 SLOW,`> 30000` → ❌ TIMEOUT_RISK。详见 `reference.md`「命令与请求超时治理」。
150
173
 
151
174
  ### 五-A、陈旧测试安全修复
152
175
 
@@ -201,6 +224,7 @@ python <skills-root>/scripts/harness_test_guard.py record --project . --change-d
201
224
  本 skill **仅允许**以下 blocking user confirmation;其余默认值 + `decision` 事件:
202
225
 
203
226
  1. **Service Gate**:仅当 `harness_service.py ensure` 返回 `needs-user-decision`(用户进程占端口)时询问处理方式
227
+ 2. **资源密集型测试确认**:仅当发布/验收确实需要 `system` 或 `full` 档位,且用户尚未明确授权时询问;获得授权后传入 `--confirm-resource-intensive`
204
228
 
205
229
  ## 执行日志
206
230