@hunter-harness/workflow-harness 0.2.49 → 0.2.50
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/harness/bundles/general/claude-code/.harness-build.json +1 -1
- package/harness/bundles/general/claude-code/harness-archive/SKILL.md +9 -1
- package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +6 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +21 -4
- package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +17 -6
- package/harness/bundles/general/claude-code/harness-plan/SKILL.md +6 -1
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +6 -1
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +7 -2
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +6 -1
- package/harness/bundles/general/claude-code/harness-sync/SKILL.md +6 -1
- package/harness/bundles/general/claude-code/harness-test/SKILL.md +6 -1
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +31 -1
- package/harness/bundles/general/claude-code/scripts/harness_events_sync.py +90 -12
- package/harness/bundles/general/claude-code/scripts/harness_gate.py +17 -0
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +9 -1
- package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +6 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +21 -4
- package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +17 -6
- package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +6 -1
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +6 -1
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +7 -2
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +6 -1
- package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +6 -1
- package/harness/bundles/general/codebuddy/harness-test/SKILL.md +6 -1
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +31 -1
- package/harness/bundles/general/codebuddy/scripts/harness_events_sync.py +90 -12
- package/harness/bundles/general/codebuddy/scripts/harness_gate.py +17 -0
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/harness-archive/SKILL.md +9 -1
- package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +6 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +21 -4
- package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +17 -6
- package/harness/bundles/general/codex/harness-plan/SKILL.md +6 -1
- package/harness/bundles/general/codex/harness-review/SKILL.md +6 -1
- package/harness/bundles/general/codex/harness-run/SKILL.md +7 -2
- package/harness/bundles/general/codex/harness-submit/SKILL.md +6 -1
- package/harness/bundles/general/codex/harness-sync/SKILL.md +6 -1
- package/harness/bundles/general/codex/harness-test/SKILL.md +6 -1
- package/harness/bundles/general/codex/scripts/harness_archive.py +31 -1
- package/harness/bundles/general/codex/scripts/harness_events_sync.py +90 -12
- package/harness/bundles/general/codex/scripts/harness_gate.py +17 -0
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +9 -1
- package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +6 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +21 -4
- package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +17 -6
- package/harness/bundles/general/cursor/harness-plan/SKILL.md +6 -1
- package/harness/bundles/general/cursor/harness-review/SKILL.md +6 -1
- package/harness/bundles/general/cursor/harness-run/SKILL.md +7 -2
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +6 -1
- package/harness/bundles/general/cursor/harness-sync/SKILL.md +6 -1
- package/harness/bundles/general/cursor/harness-test/SKILL.md +6 -1
- package/harness/bundles/general/cursor/scripts/harness_archive.py +31 -1
- package/harness/bundles/general/cursor/scripts/harness_events_sync.py +90 -12
- package/harness/bundles/general/cursor/scripts/harness_gate.py +17 -0
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +6 -1
- package/harness/bundles/java/claude-code/harness-archive/SKILL.md +9 -1
- package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +6 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +21 -4
- package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +17 -6
- package/harness/bundles/java/claude-code/harness-package/SKILL.md +6 -1
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +6 -1
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +6 -1
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +7 -2
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +6 -1
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +6 -1
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +6 -1
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +31 -1
- package/harness/bundles/java/claude-code/scripts/harness_events_sync.py +90 -12
- package/harness/bundles/java/claude-code/scripts/harness_gate.py +17 -0
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +6 -1
- package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +9 -1
- package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +6 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +21 -4
- package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +17 -6
- package/harness/bundles/java/codebuddy/harness-package/SKILL.md +6 -1
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +6 -1
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +6 -1
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +7 -2
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +6 -1
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +6 -1
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +6 -1
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +31 -1
- package/harness/bundles/java/codebuddy/scripts/harness_events_sync.py +90 -12
- package/harness/bundles/java/codebuddy/scripts/harness_gate.py +17 -0
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- package/harness/bundles/java/codex/harness-apidoc/SKILL.md +6 -1
- package/harness/bundles/java/codex/harness-archive/SKILL.md +9 -1
- package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +6 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +21 -4
- package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +17 -6
- package/harness/bundles/java/codex/harness-package/SKILL.md +6 -1
- package/harness/bundles/java/codex/harness-plan/SKILL.md +6 -1
- package/harness/bundles/java/codex/harness-review/SKILL.md +6 -1
- package/harness/bundles/java/codex/harness-run/SKILL.md +7 -2
- package/harness/bundles/java/codex/harness-submit/SKILL.md +6 -1
- package/harness/bundles/java/codex/harness-sync/SKILL.md +6 -1
- package/harness/bundles/java/codex/harness-test/SKILL.md +6 -1
- package/harness/bundles/java/codex/scripts/harness_archive.py +31 -1
- package/harness/bundles/java/codex/scripts/harness_events_sync.py +90 -12
- package/harness/bundles/java/codex/scripts/harness_gate.py +17 -0
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +6 -1
- package/harness/bundles/java/cursor/harness-archive/SKILL.md +9 -1
- package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +6 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +21 -4
- package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +17 -6
- package/harness/bundles/java/cursor/harness-package/SKILL.md +6 -1
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +6 -1
- package/harness/bundles/java/cursor/harness-review/SKILL.md +6 -1
- package/harness/bundles/java/cursor/harness-run/SKILL.md +7 -2
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +6 -1
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +6 -1
- package/harness/bundles/java/cursor/harness-test/SKILL.md +6 -1
- package/harness/bundles/java/cursor/scripts/harness_archive.py +31 -1
- package/harness/bundles/java/cursor/scripts/harness_events_sync.py +90 -12
- package/harness/bundles/java/cursor/scripts/harness_gate.py +17 -0
- package/harness/manifests/general/claude-code.json +16 -16
- package/harness/manifests/general/codebuddy.json +16 -16
- package/harness/manifests/general/codex.json +16 -16
- package/harness/manifests/general/cursor.json +16 -16
- package/harness/manifests/java/claude-code.json +18 -18
- package/harness/manifests/java/codebuddy.json +18 -18
- package/harness/manifests/java/codex.json +18 -18
- package/harness/manifests/java/cursor.json +18 -18
- package/hunter-workflow-family.json +4 -4
- package/package.json +1 -1
|
@@ -3,12 +3,21 @@ name: harness-knowledge-ingest
|
|
|
3
3
|
description: 从 .harness/archive 归档整理、同步和维护项目知识索引。适用场景:ingest knowledge、sync
|
|
4
4
|
knowledge、rebuild knowledge index、promote knowledge、确认知识条目、检查知识库是否过期。
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=1d73d4fd0925f557; overlay=java; agent=cursor; do not edit -->
|
|
7
7
|
# harness-knowledge-ingest
|
|
8
8
|
|
|
9
|
-
从 `.harness/archive/**/reports/final/summary-data.json`
|
|
9
|
+
从 `.harness/archive/**/reports/final/summary-data.json` **本地抽取**知识条目,产物随归档 push 上传;**裁决与投影以平台为准**(远程优先)。本地 SQLite / Agent judge 仅作离线或未连接平台时的回退。
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
> 语言约定:知识条目的 title / summary / body 及一切生成文档优先使用中文(标识符与字段名保持原文)。详见 [[../shared/p0-trust.md|p0-trust]] 的"生成内容语言约定"。
|
|
12
|
+
|
|
13
|
+
## 远程优先模式(平台连接后)
|
|
14
|
+
|
|
15
|
+
1. **本地职责**:抽取 candidate 条目 JSON,写入 `.harness/knowledge/entries/**`(及可选本地 index)。
|
|
16
|
+
2. **上传**:条目随 `hunter-harness push` / 归档 finalize 的 auto-push 上传(见归档分级清单:核心含 `knowledge/entries/active|candidate`)。
|
|
17
|
+
3. **平台职责**:服务端 ingest 后自动裁决 status(promote→active 等启发式),并投影到语义知识库;`deprecate` 粘性不被后续 push 覆盖。
|
|
18
|
+
4. **本地 judge / SQLite**:无平台凭据或离线时仍可用;已连接平台时**不要**把本地裁决当作多人共享真源。
|
|
19
|
+
|
|
20
|
+
未连接平台时,行为退回本地离线 MVP:`candidate` / `stale` / `active` / `superseded` / `conflicted` + SQLite FTS。按新需求查询历史由独立的 `harness-knowledge-query` 负责(默认远程语义搜索,本地索引离线回退)。
|
|
12
21
|
|
|
13
22
|
## Triggers
|
|
14
23
|
|
|
@@ -28,13 +37,16 @@ description: 从 .harness/archive 归档整理、同步和维护项目知识索
|
|
|
28
37
|
- `.harness/knowledge/index.json`
|
|
29
38
|
- `.harness/codebase/map-summary.md`(如存在)
|
|
30
39
|
- design.md
|
|
40
|
+
- (可选)`.harness/credentials.local.yaml` — 已连接平台时走远程裁决
|
|
31
41
|
|
|
32
42
|
## Purpose
|
|
33
43
|
|
|
34
44
|
解决两个问题:
|
|
35
45
|
|
|
36
46
|
1. **整理知识库内容**:把归档里的 `businessGoal`、`changedFiles`、`maintenanceNotes`、`knownRisks`、`manualActions`、`verification`、`reviewSummary` 抽成知识条目。
|
|
37
|
-
2.
|
|
47
|
+
2. **维护知识生命周期**:
|
|
48
|
+
- **远程优先**:平台 ingest 后裁决并投影;本地只需保证条目 JSON 可上传。
|
|
49
|
+
- **离线回退**:检查索引是否过期,保留 active;高置信 candidate 由 `autoPromote` 自动提升;其余由 **Agent judge** 闭环裁决。
|
|
38
50
|
|
|
39
51
|
## Outputs
|
|
40
52
|
|
|
@@ -234,6 +246,11 @@ powershell.exe -Command "python '<skill-dir>\scripts\harness_knowledge.py' sync
|
|
|
234
246
|
- 命令结果不得靠猜测;普通 Bash 被拒 → 立即改用等价 PowerShell 重试一次
|
|
235
247
|
- 仅 PowerShell 成功且有明确证据(构建/git/测试输出、文件存在、exit 0)时可标 ✅OK;否则 ❌FAIL 或 🟡WARN
|
|
236
248
|
- 禁止把 hook 拒绝、静态验证、无输出、用户跳过说成成功 → 详见 [[../protocols/powershell-protocol.md|powershell-protocol]]、[[../protocols/evidence-based-reporting-protocol.md|evidence-based-reporting-protocol]]
|
|
249
|
+
|
|
250
|
+
## 生成内容语言约定
|
|
251
|
+
|
|
252
|
+
- sync/ingest 等生成的文档、规则、知识条目、架构说明一律**优先使用中文**撰写(标识符、命令、代码、API 字段名保持原文)
|
|
253
|
+
- 面向平台展示的标题/摘要/正文默认中文;仅当用户明确要求或目标系统强制时才用英文
|
|
237
254
|
> 片段:p0-trust · ingest/sync 须绑定 `upToDate`/产物路径证据
|
|
238
255
|
|
|
239
256
|
## Output Format
|
|
@@ -3,14 +3,18 @@ name: harness-knowledge-query
|
|
|
3
3
|
description: 根据新需求、设计任务、代码修改请求或问题排查,在规划和编码前查询 .harness/knowledge
|
|
4
4
|
历史上下文。适用场景:query knowledge、查找历史需求、根据归档理解需求、继续之前类似开发、生成需求上下文包。
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=1d73d4fd0925f557; overlay=java; agent=cursor; do not edit -->
|
|
7
7
|
# harness-knowledge-query
|
|
8
8
|
|
|
9
9
|
并行 change 中查询必须传 `--change <change-id>`;成功后以该 change 的 `meta/knowledge-context.json` 为稳定指针。全局 `context-packs/latest.json` 仅向后兼容,不得用于判断多个 active change 的上下文归属。
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
根据用户的新需求或排查问题检索历史需求、决策、实现、风险和测试证据,并生成 AI 可读的 context pack。
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## 远程优先 / 离线回退
|
|
14
|
+
|
|
15
|
+
1. **默认(已 `hunter-harness connect`)**:优先查询平台语义知识库(与 ingest 上传 + 服务端裁决结果一致);多机/多人共享同一裁决结果。
|
|
16
|
+
2. **离线回退**:无凭据、网络失败或平台不可用时,回退到本地 `.harness/knowledge`(SQLite FTS / 条目文件)。
|
|
17
|
+
3. 此 skill 只负责查询和使用知识。整理与上传由 `harness-knowledge-ingest` + push/归档负责;**不要**在已连接平台时把本地 promote 当作共享真源。
|
|
14
18
|
|
|
15
19
|
## Triggers
|
|
16
20
|
|
|
@@ -25,9 +29,9 @@ description: 根据新需求、设计任务、代码修改请求或问题排查
|
|
|
25
29
|
|
|
26
30
|
## Automatic Use
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
当用户提出新功能、改造、排查、设计方案、继续历史任务,且项目存在平台连接或 `.harness/archive` / `.harness/knowledge` 时,AI 应主动运行本 skill,不需要等用户提醒。
|
|
29
33
|
|
|
30
|
-
不在 query 前单独执行 sync。`query` 命令内部执行一次 ensure-current
|
|
34
|
+
不在 query 前单独执行 sync。`query` 命令内部执行一次 ensure-current:建立一次当前快照,索引新鲜时无操作,过期或缺失时只构建一次,然后在同一调用内完成查询(离线路径)。
|
|
31
35
|
|
|
32
36
|
## Commands
|
|
33
37
|
|
|
@@ -39,6 +43,8 @@ description: 根据新需求、设计任务、代码修改请求或问题排查
|
|
|
39
43
|
powershell.exe -Command "python '<ingest-skill-dir>\scripts\harness_knowledge.py' query --project '<project-root>' --query '<用户需求原文>'"
|
|
40
44
|
```
|
|
41
45
|
|
|
46
|
+
已连接平台时,优先使用平台语义搜索(CLI/`hunter-harness` 知识查询路径,若可用);上述本地命令作为离线回退。
|
|
47
|
+
|
|
42
48
|
### Query with metadata filters
|
|
43
49
|
|
|
44
50
|
```powershell
|
|
@@ -48,7 +54,7 @@ powershell.exe -Command "python '<ingest-skill-dir>\scripts\harness_knowledge.py
|
|
|
48
54
|
可重复使用:
|
|
49
55
|
|
|
50
56
|
- `--file <path>`:只返回关联到指定文件的知识。
|
|
51
|
-
- `--status active|candidate|stale|superseded|conflicted
|
|
57
|
+
- `--status active|candidate|stale|superseded|conflicted`:按生命周期过滤(远程路径通常已排除 deprecated)。
|
|
52
58
|
- `--type requirement|decision|implementation|risk|test-evidence|pitfall|api-contract`:按知识类型过滤。
|
|
53
59
|
- `--limit <n>`:限制返回数量。
|
|
54
60
|
|
|
@@ -111,6 +117,11 @@ powershell.exe -Command "python '<ingest-skill-dir>\scripts\harness_knowledge.py
|
|
|
111
117
|
- 命令结果不得靠猜测;普通 Bash 被拒 → 立即改用等价 PowerShell 重试一次
|
|
112
118
|
- 仅 PowerShell 成功且有明确证据(构建/git/测试输出、文件存在、exit 0)时可标 ✅OK;否则 ❌FAIL 或 🟡WARN
|
|
113
119
|
- 禁止把 hook 拒绝、静态验证、无输出、用户跳过说成成功 → 详见 [[../protocols/powershell-protocol.md|powershell-protocol]]、[[../protocols/evidence-based-reporting-protocol.md|evidence-based-reporting-protocol]]
|
|
120
|
+
|
|
121
|
+
## 生成内容语言约定
|
|
122
|
+
|
|
123
|
+
- sync/ingest 等生成的文档、规则、知识条目、架构说明一律**优先使用中文**撰写(标识符、命令、代码、API 字段名保持原文)
|
|
124
|
+
- 面向平台展示的标题/摘要/正文默认中文;仅当用户明确要求或目标系统强制时才用英文
|
|
114
125
|
> 片段:p0-trust · query 成功须含 `contextPack`/`planInput.kind` 与 `latest.json` 写入
|
|
115
126
|
|
|
116
127
|
## Output Format
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: harness-package
|
|
3
3
|
description: 增量模块打包:拉取最新→编译验证→mvn package→汇总 jar/war。仅当用户显式调用 /harness-package 时使用,不得自动触发。
|
|
4
4
|
---
|
|
5
|
-
<!-- generated by harness_deploy.py; core=
|
|
5
|
+
<!-- generated by harness_deploy.py; core=1d73d4fd0925f557; overlay=java; agent=cursor; do not edit -->
|
|
6
6
|
# harness-package — 增量模块打包(Java overlay)
|
|
7
7
|
|
|
8
8
|
## Purpose
|
|
@@ -51,6 +51,11 @@ description: 增量模块打包:拉取最新→编译验证→mvn package→
|
|
|
51
51
|
- 命令结果不得靠猜测;普通 Bash 被拒 → 立即改用等价 PowerShell 重试一次
|
|
52
52
|
- 仅 PowerShell 成功且有明确证据(构建/git/测试输出、文件存在、exit 0)时可标 ✅OK;否则 ❌FAIL 或 🟡WARN
|
|
53
53
|
- 禁止把 hook 拒绝、静态验证、无输出、用户跳过说成成功 → 详见 [[../protocols/powershell-protocol.md|powershell-protocol]]、[[../protocols/evidence-based-reporting-protocol.md|evidence-based-reporting-protocol]]
|
|
54
|
+
|
|
55
|
+
## 生成内容语言约定
|
|
56
|
+
|
|
57
|
+
- sync/ingest 等生成的文档、规则、知识条目、架构说明一律**优先使用中文**撰写(标识符、命令、代码、API 字段名保持原文)
|
|
58
|
+
- 面向平台展示的标题/摘要/正文默认中文;仅当用户明确要求或目标系统强制时才用英文
|
|
54
59
|
> 片段:p0-trust
|
|
55
60
|
|
|
56
61
|
## 渐进披露
|
|
@@ -3,7 +3,7 @@ name: harness-plan
|
|
|
3
3
|
description: 将需求转化为设计文档+实施计划+完整测试场景表,必须在编码前完成。仅当用户显式调用 /harness-plan 或明确要求进入
|
|
4
4
|
Harness 规划阶段时使用;不得因用户描述需求就自动触发。
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=1d73d4fd0925f557; overlay=java; agent=cursor; do not edit -->
|
|
7
7
|
# harness-plan — 需求规划
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
@@ -82,6 +82,11 @@ change-name 范围变更 → 提示重命名或记 🟡WARN(→ `reference.md`
|
|
|
82
82
|
- 命令结果不得靠猜测;普通 Bash 被拒 → 立即改用等价 PowerShell 重试一次
|
|
83
83
|
- 仅 PowerShell 成功且有明确证据(构建/git/测试输出、文件存在、exit 0)时可标 ✅OK;否则 ❌FAIL 或 🟡WARN
|
|
84
84
|
- 禁止把 hook 拒绝、静态验证、无输出、用户跳过说成成功 → 详见 [[../protocols/powershell-protocol.md|powershell-protocol]]、[[../protocols/evidence-based-reporting-protocol.md|evidence-based-reporting-protocol]]
|
|
85
|
+
|
|
86
|
+
## 生成内容语言约定
|
|
87
|
+
|
|
88
|
+
- sync/ingest 等生成的文档、规则、知识条目、架构说明一律**优先使用中文**撰写(标识符、命令、代码、API 字段名保持原文)
|
|
89
|
+
- 面向平台展示的标题/摘要/正文默认中文;仅当用户明确要求或目标系统强制时才用英文
|
|
85
90
|
> 片段:p0-trust
|
|
86
91
|
|
|
87
92
|
## 关键规则
|
|
@@ -4,7 +4,7 @@ description: 6维度代码审查(架构/安全/规范/兼容/测试/性能)
|
|
|
4
4
|
.harness/context-index.json)和测试场景表,在隔离上下文运行。仅当用户显式调用 /harness-review 时使用;不得在
|
|
5
5
|
test 结束后自动接续执行。
|
|
6
6
|
---
|
|
7
|
-
<!-- generated by harness_deploy.py; core=
|
|
7
|
+
<!-- generated by harness_deploy.py; core=1d73d4fd0925f557; overlay=java; agent=cursor; do not edit -->
|
|
8
8
|
# harness-review — 代码审查
|
|
9
9
|
|
|
10
10
|
## Purpose
|
|
@@ -102,6 +102,11 @@ review:
|
|
|
102
102
|
- 命令结果不得靠猜测;普通 Bash 被拒 → 立即改用等价 PowerShell 重试一次
|
|
103
103
|
- 仅 PowerShell 成功且有明确证据(构建/git/测试输出、文件存在、exit 0)时可标 ✅OK;否则 ❌FAIL 或 🟡WARN
|
|
104
104
|
- 禁止把 hook 拒绝、静态验证、无输出、用户跳过说成成功 → 详见 [[../protocols/powershell-protocol.md|powershell-protocol]]、[[../protocols/evidence-based-reporting-protocol.md|evidence-based-reporting-protocol]]
|
|
105
|
+
|
|
106
|
+
## 生成内容语言约定
|
|
107
|
+
|
|
108
|
+
- sync/ingest 等生成的文档、规则、知识条目、架构说明一律**优先使用中文**撰写(标识符、命令、代码、API 字段名保持原文)
|
|
109
|
+
- 面向平台展示的标题/摘要/正文默认中文;仅当用户明确要求或目标系统强制时才用英文
|
|
105
110
|
> 片段:p0-trust
|
|
106
111
|
|
|
107
112
|
## 关键规则(硬门禁速查)
|
|
@@ -3,7 +3,7 @@ name: harness-run
|
|
|
3
3
|
description: 按变更簇执行 TDD 编码循环(RED→GREEN→REFACTOR→编译验证),逐变更簇实现计划中的任务。仅当用户显式调用
|
|
4
4
|
/harness-run 时使用;不得因用户提到编码/实现就自动触发,也不得被其他阶段 skill 自动接续。
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=1d73d4fd0925f557; overlay=java; agent=cursor; do not edit -->
|
|
7
7
|
# harness-run — 需求编码
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
@@ -59,7 +59,7 @@ description: 按变更簇执行 TDD 编码循环(RED→GREEN→REFACTOR→编
|
|
|
59
59
|
|
|
60
60
|
## Workflow 概要
|
|
61
61
|
|
|
62
|
-
0. 加载上下文:先 `harness_context.py prepare --phase run --executor <tool> [--change <id>] --json`,以返回的唯一 change/executionRoot/transition receipt 为准(多 active 缺参 → `ACTIVE_CHANGE_AMBIGUOUS`,禁止按 mtime 猜测);再 **`harness_context.py begin --phase run --change <id> --executor <tool> --json`** 校验 Plan artifact/hash/HEAD,读 spec/plan/detail/scenarios/ledger/run-task-status/worktree;`--fixback` 读 fixback → **`harness_gate.py begin --phase run --change <id>`**(claim + phase.start + identity;禁止手工 Write `events.ndjson` / 手工 `phase.end
|
|
62
|
+
0. 加载上下文:先 `harness_context.py prepare --phase run --executor <tool> [--change <id>] --json`,以返回的唯一 change/executionRoot/transition receipt 为准(多 active 缺参 → `ACTIVE_CHANGE_AMBIGUOUS`,禁止按 mtime 猜测);再 **`harness_context.py begin --phase run --change <id> --executor <tool> --json`** 校验 Plan artifact/hash/HEAD,读 spec/plan/detail/scenarios/ledger/run-task-status/worktree;`--fixback` 读 fixback → **`harness_gate.py begin --phase run --change <id>`**(claim + phase.start + identity;禁止手工 Write `events.ndjson` / 手工 `phase.end`)。**C3 钩子**:`harness_gate.py begin` 在已连接平台时会 best-effort 调用 events-sync(注册 run / `running`);失败只告警,不阻断 begin。
|
|
63
63
|
0.5. **测试基础设施探测**(先写 `CHECKING`,四项证据齐备后再结论)→ `reference.md` Step 0.5;进入 TDD 前执行 `harness_test_guard.py begin --project . --change-dir ".harness/changes/<cn>" --json`
|
|
64
64
|
1. **变更簇 TDD** — `protocols.md` `run-tdd-protocol`;批量 RED/GREEN;按需 `change-cluster-review-protocol`(高风险 + reviewer 预检可用)
|
|
65
65
|
2. 构建验证 + **仅**通过 `harness_ledger.py record` 写 ledger(禁止 Write/Edit `verification-ledger.json`);`diff-hash --change-dir` 纳入 ignored tests → `reference.md` Step 2c
|
|
@@ -83,6 +83,11 @@ description: 按变更簇执行 TDD 编码循环(RED→GREEN→REFACTOR→编
|
|
|
83
83
|
- 命令结果不得靠猜测;普通 Bash 被拒 → 立即改用等价 PowerShell 重试一次
|
|
84
84
|
- 仅 PowerShell 成功且有明确证据(构建/git/测试输出、文件存在、exit 0)时可标 ✅OK;否则 ❌FAIL 或 🟡WARN
|
|
85
85
|
- 禁止把 hook 拒绝、静态验证、无输出、用户跳过说成成功 → 详见 [[../protocols/powershell-protocol.md|powershell-protocol]]、[[../protocols/evidence-based-reporting-protocol.md|evidence-based-reporting-protocol]]
|
|
86
|
+
|
|
87
|
+
## 生成内容语言约定
|
|
88
|
+
|
|
89
|
+
- sync/ingest 等生成的文档、规则、知识条目、架构说明一律**优先使用中文**撰写(标识符、命令、代码、API 字段名保持原文)
|
|
90
|
+
- 面向平台展示的标题/摘要/正文默认中文;仅当用户明确要求或目标系统强制时才用英文
|
|
86
91
|
> 片段:p0-trust
|
|
87
92
|
|
|
88
93
|
## 关键规则(硬门禁速查)
|
|
@@ -3,7 +3,7 @@ name: harness-submit
|
|
|
3
3
|
description: 最终提交封装:验证→中文 commit→提交/推送;worktree 模式含 --no-ff 合并回主分支。仅当用户显式调用
|
|
4
4
|
/harness-submit(或 /harness-merge 重入合并段)时使用;用户口头说'提交/commit/push'时必须先确认,不得自动触发。
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=1d73d4fd0925f557; overlay=java; agent=cursor; do not edit -->
|
|
7
7
|
# harness-submit — 最终提交(含 worktree 合并)
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
@@ -101,6 +101,11 @@ M7. **ledger + 收尾** — 经 `harness_ledger.py record` 写入 `mergeFinalHas
|
|
|
101
101
|
- 命令结果不得靠猜测;普通 Bash 被拒 → 立即改用等价 PowerShell 重试一次
|
|
102
102
|
- 仅 PowerShell 成功且有明确证据(构建/git/测试输出、文件存在、exit 0)时可标 ✅OK;否则 ❌FAIL 或 🟡WARN
|
|
103
103
|
- 禁止把 hook 拒绝、静态验证、无输出、用户跳过说成成功 → 详见 [[../protocols/powershell-protocol.md|powershell-protocol]]、[[../protocols/evidence-based-reporting-protocol.md|evidence-based-reporting-protocol]]
|
|
104
|
+
|
|
105
|
+
## 生成内容语言约定
|
|
106
|
+
|
|
107
|
+
- sync/ingest 等生成的文档、规则、知识条目、架构说明一律**优先使用中文**撰写(标识符、命令、代码、API 字段名保持原文)
|
|
108
|
+
- 面向平台展示的标题/摘要/正文默认中文;仅当用户明确要求或目标系统强制时才用英文
|
|
104
109
|
> 片段:p0-trust
|
|
105
110
|
|
|
106
111
|
## 关键规则(硬门禁速查)
|
|
@@ -4,7 +4,7 @@ description: Use when the user asks to synchronize, refresh, or validate Harness
|
|
|
4
4
|
metadata, adapters, knowledge, rules, instruction entrypoints, config origins,
|
|
5
5
|
or CodeGraph status.
|
|
6
6
|
---
|
|
7
|
-
<!-- generated by harness_deploy.py; core=
|
|
7
|
+
<!-- generated by harness_deploy.py; core=1d73d4fd0925f557; overlay=java; agent=cursor; do not edit -->
|
|
8
8
|
# harness-sync
|
|
9
9
|
|
|
10
10
|
## Purpose
|
|
@@ -56,6 +56,11 @@ JSON 报告回显到对话。
|
|
|
56
56
|
- 命令结果不得靠猜测;普通 Bash 被拒 → 立即改用等价 PowerShell 重试一次
|
|
57
57
|
- 仅 PowerShell 成功且有明确证据(构建/git/测试输出、文件存在、exit 0)时可标 ✅OK;否则 ❌FAIL 或 🟡WARN
|
|
58
58
|
- 禁止把 hook 拒绝、静态验证、无输出、用户跳过说成成功 → 详见 [[../protocols/powershell-protocol.md|powershell-protocol]]、[[../protocols/evidence-based-reporting-protocol.md|evidence-based-reporting-protocol]]
|
|
59
|
+
|
|
60
|
+
## 生成内容语言约定
|
|
61
|
+
|
|
62
|
+
- sync/ingest 等生成的文档、规则、知识条目、架构说明一律**优先使用中文**撰写(标识符、命令、代码、API 字段名保持原文)
|
|
63
|
+
- 面向平台展示的标题/摘要/正文默认中文;仅当用户明确要求或目标系统强制时才用英文
|
|
59
64
|
> 片段:p0-trust
|
|
60
65
|
|
|
61
66
|
## 执行日志
|
|
@@ -3,7 +3,7 @@ name: harness-test
|
|
|
3
3
|
description: 测试执行:读取场景表,执行单元测试+API接口测试+数据兼容验证,输出测试报告。仅当用户显式调用 /harness-test
|
|
4
4
|
时使用;不得在 run 结束后自动接续执行。
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=1d73d4fd0925f557; overlay=java; agent=cursor; do not edit -->
|
|
7
7
|
# harness-test — 测试执行
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
@@ -136,6 +136,11 @@ Runner 强制同项目单实例、低调度优先级、逐命令超时、正常
|
|
|
136
136
|
- 命令结果不得靠猜测;普通 Bash 被拒 → 立即改用等价 PowerShell 重试一次
|
|
137
137
|
- 仅 PowerShell 成功且有明确证据(构建/git/测试输出、文件存在、exit 0)时可标 ✅OK;否则 ❌FAIL 或 🟡WARN
|
|
138
138
|
- 禁止把 hook 拒绝、静态验证、无输出、用户跳过说成成功 → 详见 [[../protocols/powershell-protocol.md|powershell-protocol]]、[[../protocols/evidence-based-reporting-protocol.md|evidence-based-reporting-protocol]]
|
|
139
|
+
|
|
140
|
+
## 生成内容语言约定
|
|
141
|
+
|
|
142
|
+
- sync/ingest 等生成的文档、规则、知识条目、架构说明一律**优先使用中文**撰写(标识符、命令、代码、API 字段名保持原文)
|
|
143
|
+
- 面向平台展示的标题/摘要/正文默认中文;仅当用户明确要求或目标系统强制时才用英文
|
|
139
144
|
> 片段:p0-trust
|
|
140
145
|
|
|
141
146
|
## 关键规则(硬门禁速查)
|
|
@@ -70,6 +70,7 @@ if str(SCRIPTS_DIR) not in sys.path:
|
|
|
70
70
|
sys.path.insert(0, str(SCRIPTS_DIR))
|
|
71
71
|
|
|
72
72
|
import harness_events as he # noqa: E402
|
|
73
|
+
import harness_events_sync as hes # noqa: E402
|
|
73
74
|
import harness_efficiency as heff # noqa: E402
|
|
74
75
|
import harness_gate as hgate # noqa: E402
|
|
75
76
|
import harness_ledger as hl # noqa: E402
|
|
@@ -8284,6 +8285,9 @@ def cmd_finalize(
|
|
|
8284
8285
|
|
|
8285
8286
|
# Publish only after every validator passes. The archive path is never used
|
|
8286
8287
|
# as mutable staging, so a failed attempt cannot poison the next retry.
|
|
8288
|
+
# Capture monitoring run_id from the live change path before it is deleted
|
|
8289
|
+
# so archive finalize can report terminal status on the same platform run.
|
|
8290
|
+
monitoring_run_id = hes.run_id_for(original_change_dir)
|
|
8287
8291
|
try:
|
|
8288
8292
|
archive_root.mkdir(parents=True, exist_ok=True)
|
|
8289
8293
|
shutil.move(str(operation_temp_dir), str(archive_dir))
|
|
@@ -8368,6 +8372,23 @@ def cmd_finalize(
|
|
|
8368
8372
|
if push_result.get("warning"):
|
|
8369
8373
|
warnings.append(str(push_result["warning"]))
|
|
8370
8374
|
|
|
8375
|
+
# C3: best-effort terminal events-sync so platform run ends (succeeded/failed).
|
|
8376
|
+
# Use the pre-delete change-path run_id + original change_key for continuity.
|
|
8377
|
+
try:
|
|
8378
|
+
monitor = hes.auto_events_sync(
|
|
8379
|
+
project_root,
|
|
8380
|
+
archive_dir,
|
|
8381
|
+
run_id=monitoring_run_id,
|
|
8382
|
+
change_key=change_name,
|
|
8383
|
+
)
|
|
8384
|
+
payload["steps"]["platform_events_sync"] = monitor
|
|
8385
|
+
if monitor.get("warning"):
|
|
8386
|
+
warnings.append(str(monitor["warning"]))
|
|
8387
|
+
except Exception as exc: # noqa: BLE001 — never roll back archive
|
|
8388
|
+
warn = f"events-sync terminal hook failed: {exc}"
|
|
8389
|
+
warnings.append(warn)
|
|
8390
|
+
payload["steps"]["platform_events_sync"] = {"ok": False, "warning": warn}
|
|
8391
|
+
|
|
8371
8392
|
payload["ok"] = True
|
|
8372
8393
|
payload["finalStatus"] = "OK"
|
|
8373
8394
|
payload["warnings"] = warnings
|
|
@@ -8387,7 +8408,7 @@ def _remote_credentials_configured(project_root: Path) -> bool:
|
|
|
8387
8408
|
|
|
8388
8409
|
|
|
8389
8410
|
def collect_archive_core_paths(project_root: Path, archive_dir: Path) -> list[str]:
|
|
8390
|
-
"""Relative paths for the
|
|
8411
|
+
"""Relative paths for the archive push allowlist (core + optional supporting)."""
|
|
8391
8412
|
root = project_root.resolve()
|
|
8392
8413
|
archive = archive_dir.resolve()
|
|
8393
8414
|
paths: list[str] = []
|
|
@@ -8403,6 +8424,15 @@ def collect_archive_core_paths(project_root: Path, archive_dir: Path) -> list[st
|
|
|
8403
8424
|
for path in sorted(base.rglob("*")):
|
|
8404
8425
|
if path.is_file():
|
|
8405
8426
|
paths.append(path.relative_to(root).as_posix())
|
|
8427
|
+
# C1 optional supporting files.
|
|
8428
|
+
for folder in (("reports", "review"), ("reports", "test")):
|
|
8429
|
+
base = archive.joinpath(*folder)
|
|
8430
|
+
if base.is_dir():
|
|
8431
|
+
for path in sorted(base.rglob("*")):
|
|
8432
|
+
if path.is_file():
|
|
8433
|
+
paths.append(path.relative_to(root).as_posix())
|
|
8434
|
+
add_if_exists(archive / "meta" / "archive-meta.md")
|
|
8435
|
+
add_if_exists(archive / "meta" / "change-context.json")
|
|
8406
8436
|
knowledge = root / ".harness" / "knowledge" / "entries"
|
|
8407
8437
|
for status in ("active", "candidate"):
|
|
8408
8438
|
folder = knowledge / status
|
|
@@ -119,12 +119,19 @@ def post_json(endpoint: dict[str, str], path: str, body: dict[str, Any]) -> dict
|
|
|
119
119
|
return json.loads(response.read().decode("utf-8"))
|
|
120
120
|
|
|
121
121
|
|
|
122
|
-
def sync_change(
|
|
122
|
+
def sync_change(
|
|
123
|
+
project: Path,
|
|
124
|
+
change_dir: Path,
|
|
125
|
+
*,
|
|
126
|
+
heartbeat_only: bool = False,
|
|
127
|
+
run_id: str | None = None,
|
|
128
|
+
change_key: str | None = None,
|
|
129
|
+
) -> dict[str, Any]:
|
|
123
130
|
endpoint = load_endpoint(project)
|
|
124
131
|
if endpoint is None:
|
|
125
132
|
return {"ok": True, "skipped": True, "reason": "remote credentials not configured"}
|
|
126
|
-
|
|
127
|
-
rid = run_id_for(change_dir)
|
|
133
|
+
resolved_key = change_key or change_dir.name
|
|
134
|
+
rid = run_id or run_id_for(change_dir)
|
|
128
135
|
project_id = endpoint["project_id"]
|
|
129
136
|
|
|
130
137
|
# Always heartbeat so the console can separate connection vs run status.
|
|
@@ -138,20 +145,26 @@ def sync_change(project: Path, change_dir: Path, *, heartbeat_only: bool = False
|
|
|
138
145
|
{
|
|
139
146
|
"protocol_version": "hunter-progress-sync/v1",
|
|
140
147
|
"run_id": rid,
|
|
141
|
-
"change_key":
|
|
148
|
+
"change_key": resolved_key,
|
|
142
149
|
"client_time": client_time,
|
|
143
|
-
"title":
|
|
150
|
+
"title": resolved_key,
|
|
144
151
|
},
|
|
145
152
|
)
|
|
146
153
|
except (urllib.error.URLError, TimeoutError, OSError, json.JSONDecodeError) as exc:
|
|
147
154
|
return {"ok": False, "error": f"heartbeat failed: {exc}", "run_id": rid}
|
|
148
155
|
|
|
149
156
|
if heartbeat_only:
|
|
150
|
-
return {"ok": True, "heartbeat": True, "run_id": rid}
|
|
157
|
+
return {"ok": True, "heartbeat": True, "run_id": rid, "change_key": resolved_key}
|
|
151
158
|
|
|
152
159
|
events_file = change_dir / "events.ndjson"
|
|
153
160
|
if not events_file.is_file():
|
|
154
|
-
return {
|
|
161
|
+
return {
|
|
162
|
+
"ok": True,
|
|
163
|
+
"run_id": rid,
|
|
164
|
+
"change_key": resolved_key,
|
|
165
|
+
"uploaded": 0,
|
|
166
|
+
"reason": "no events.ndjson",
|
|
167
|
+
}
|
|
155
168
|
|
|
156
169
|
lines = events_file.read_text(encoding="utf-8").splitlines()
|
|
157
170
|
acked = load_cursor(change_dir)
|
|
@@ -167,7 +180,7 @@ def sync_change(project: Path, change_dir: Path, *, heartbeat_only: bool = False
|
|
|
167
180
|
continue
|
|
168
181
|
if not isinstance(event, dict):
|
|
169
182
|
continue
|
|
170
|
-
event_id = str(event.get("id") or f"{
|
|
183
|
+
event_id = str(event.get("id") or f"{resolved_key}:{acked + offset}")
|
|
171
184
|
payload = sanitize(event)
|
|
172
185
|
batch.append(
|
|
173
186
|
{
|
|
@@ -181,7 +194,13 @@ def sync_change(project: Path, change_dir: Path, *, heartbeat_only: bool = False
|
|
|
181
194
|
)
|
|
182
195
|
if not batch:
|
|
183
196
|
save_cursor(change_dir, len(lines))
|
|
184
|
-
return {
|
|
197
|
+
return {
|
|
198
|
+
"ok": True,
|
|
199
|
+
"run_id": rid,
|
|
200
|
+
"change_key": resolved_key,
|
|
201
|
+
"uploaded": 0,
|
|
202
|
+
"acked_lines": len(lines),
|
|
203
|
+
}
|
|
185
204
|
|
|
186
205
|
# Drop None phase keys for strict schema.
|
|
187
206
|
for item in batch:
|
|
@@ -195,8 +214,8 @@ def sync_change(project: Path, change_dir: Path, *, heartbeat_only: bool = False
|
|
|
195
214
|
{
|
|
196
215
|
"protocol_version": "hunter-progress-sync/v1",
|
|
197
216
|
"run_id": rid,
|
|
198
|
-
"change_key":
|
|
199
|
-
"title":
|
|
217
|
+
"change_key": resolved_key,
|
|
218
|
+
"title": resolved_key,
|
|
200
219
|
"events": batch,
|
|
201
220
|
},
|
|
202
221
|
)
|
|
@@ -222,6 +241,7 @@ def sync_change(project: Path, change_dir: Path, *, heartbeat_only: bool = False
|
|
|
222
241
|
return {
|
|
223
242
|
"ok": accepted == len(batch),
|
|
224
243
|
"run_id": rid,
|
|
244
|
+
"change_key": resolved_key,
|
|
225
245
|
"uploaded": accepted,
|
|
226
246
|
"batch_size": len(batch),
|
|
227
247
|
"acked_lines": acked_lines,
|
|
@@ -229,10 +249,62 @@ def sync_change(project: Path, change_dir: Path, *, heartbeat_only: bool = False
|
|
|
229
249
|
}
|
|
230
250
|
|
|
231
251
|
|
|
252
|
+
def auto_events_sync(
|
|
253
|
+
project_root: Path,
|
|
254
|
+
change_dir: Path,
|
|
255
|
+
*,
|
|
256
|
+
heartbeat_only: bool = False,
|
|
257
|
+
run_id: str | None = None,
|
|
258
|
+
change_key: str | None = None,
|
|
259
|
+
) -> dict[str, Any]:
|
|
260
|
+
"""Best-effort platform events sync (same style as auto_push_archive_core).
|
|
261
|
+
|
|
262
|
+
Failures become warnings so the caller never rolls back the main workflow.
|
|
263
|
+
"""
|
|
264
|
+
project_root = project_root.resolve()
|
|
265
|
+
change_dir = change_dir.resolve()
|
|
266
|
+
if load_endpoint(project_root) is None:
|
|
267
|
+
return {"skipped": True, "reason": "no remote credentials"}
|
|
268
|
+
try:
|
|
269
|
+
result = sync_change(
|
|
270
|
+
project_root,
|
|
271
|
+
change_dir,
|
|
272
|
+
heartbeat_only=heartbeat_only,
|
|
273
|
+
run_id=run_id,
|
|
274
|
+
change_key=change_key,
|
|
275
|
+
)
|
|
276
|
+
except Exception as exc: # noqa: BLE001 — best-effort never blocks caller
|
|
277
|
+
return {
|
|
278
|
+
"skipped": False,
|
|
279
|
+
"ok": False,
|
|
280
|
+
"warning": f"events-sync deferred: {exc}",
|
|
281
|
+
}
|
|
282
|
+
if result.get("skipped"):
|
|
283
|
+
return {"skipped": True, "reason": result.get("reason") or "skipped"}
|
|
284
|
+
if result.get("ok"):
|
|
285
|
+
return {"skipped": False, "ok": True, **{
|
|
286
|
+
key: result[key]
|
|
287
|
+
for key in ("run_id", "change_key", "uploaded", "acked_lines", "heartbeat")
|
|
288
|
+
if key in result
|
|
289
|
+
}}
|
|
290
|
+
return {
|
|
291
|
+
"skipped": False,
|
|
292
|
+
"ok": False,
|
|
293
|
+
"warning": str(result.get("error") or "events-sync failed"),
|
|
294
|
+
**{
|
|
295
|
+
key: result[key]
|
|
296
|
+
for key in ("run_id", "change_key")
|
|
297
|
+
if key in result
|
|
298
|
+
},
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
|
|
232
302
|
def main(argv: list[str] | None = None) -> int:
|
|
233
303
|
parser = argparse.ArgumentParser(description="Sync events.ndjson to platform Run monitoring")
|
|
234
304
|
parser.add_argument("--project", default=".", help="Project root")
|
|
235
305
|
parser.add_argument("--change-dir", help="Specific change directory")
|
|
306
|
+
parser.add_argument("--run-id", help="Override stable run_id (archive finalize continuity)")
|
|
307
|
+
parser.add_argument("--change-key", help="Override change_key sent to the platform")
|
|
236
308
|
parser.add_argument("--heartbeat-only", action="store_true")
|
|
237
309
|
parser.add_argument("--json", action="store_true")
|
|
238
310
|
args = parser.parse_args(argv)
|
|
@@ -243,7 +315,13 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
243
315
|
root = project / ".harness" / "changes"
|
|
244
316
|
changes = sorted(path for path in root.glob("*") if path.is_dir()) if root.is_dir() else []
|
|
245
317
|
results = [
|
|
246
|
-
sync_change(
|
|
318
|
+
sync_change(
|
|
319
|
+
project,
|
|
320
|
+
change_dir,
|
|
321
|
+
heartbeat_only=args.heartbeat_only,
|
|
322
|
+
run_id=args.run_id,
|
|
323
|
+
change_key=args.change_key,
|
|
324
|
+
)
|
|
247
325
|
for change_dir in changes
|
|
248
326
|
]
|
|
249
327
|
ok = all(item.get("ok") for item in results) if results else True
|
|
@@ -31,6 +31,7 @@ if str(SCRIPTS_DIR) not in sys.path:
|
|
|
31
31
|
|
|
32
32
|
import harness_change as hc # noqa: E402
|
|
33
33
|
import harness_events as he # noqa: E402
|
|
34
|
+
import harness_events_sync as hes # noqa: E402
|
|
34
35
|
import harness_ledger as hl # noqa: E402
|
|
35
36
|
import harness_paths as hp # noqa: E402
|
|
36
37
|
import harness_plan_finalize as hpf # noqa: E402
|
|
@@ -2213,6 +2214,22 @@ def cmd_begin(args: argparse.Namespace) -> int:
|
|
|
2213
2214
|
"gateSeverityMode": severity_mode,
|
|
2214
2215
|
"gateWarnings": gate_warnings,
|
|
2215
2216
|
}
|
|
2217
|
+
# C3: best-effort start platform run monitoring (register + running via heartbeat/events).
|
|
2218
|
+
try:
|
|
2219
|
+
monitor = hes.auto_events_sync(project, change_dir)
|
|
2220
|
+
payload["platformMonitor"] = monitor
|
|
2221
|
+
if monitor.get("warning"):
|
|
2222
|
+
warnings_msg = str(monitor["warning"])
|
|
2223
|
+
gate_warnings.append({
|
|
2224
|
+
"code": "PLATFORM_EVENTS_SYNC_WARN",
|
|
2225
|
+
"message": warnings_msg,
|
|
2226
|
+
})
|
|
2227
|
+
payload["gateWarnings"] = gate_warnings
|
|
2228
|
+
except Exception as exc: # noqa: BLE001 — never block phase begin
|
|
2229
|
+
payload["platformMonitor"] = {
|
|
2230
|
+
"ok": False,
|
|
2231
|
+
"warning": f"events-sync hook failed: {exc}",
|
|
2232
|
+
}
|
|
2216
2233
|
emit(payload, as_json=as_json)
|
|
2217
2234
|
return 0
|
|
2218
2235
|
|