@hunter-harness/workflow-harness 0.3.0 → 0.4.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/harness/bundles/general/claude-code/.harness-build.json +1 -1
- package/harness/bundles/general/claude-code/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-archive/reference.md +30 -1
- package/harness/bundles/general/claude-code/harness-archive/templates/summary-data-template.json +1 -0
- package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-execute/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-pull/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-push/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +141 -4
- package/harness/bundles/general/claude-code/scripts/harness_knowledge_candidates.py +140 -4
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/reference.md +30 -1
- package/harness/bundles/general/codebuddy/harness-archive/templates/summary-data-template.json +1 -0
- package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-execute/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-pull/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-push/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +141 -4
- package/harness/bundles/general/codebuddy/scripts/harness_knowledge_candidates.py +140 -4
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-archive/reference.md +30 -1
- package/harness/bundles/general/codex/harness-archive/templates/summary-data-template.json +1 -0
- package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-execute/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-pull/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-push/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/codex/scripts/harness_archive.py +141 -4
- package/harness/bundles/general/codex/scripts/harness_knowledge_candidates.py +140 -4
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-archive/reference.md +30 -1
- package/harness/bundles/general/cursor/harness-archive/templates/summary-data-template.json +1 -0
- package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-execute/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-pull/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-push/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/cursor/scripts/harness_archive.py +141 -4
- package/harness/bundles/general/cursor/scripts/harness_knowledge_candidates.py +140 -4
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-archive/reference.md +30 -1
- package/harness/bundles/java/claude-code/harness-archive/templates/summary-data-template.json +1 -0
- package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-execute/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-pull/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-push/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +141 -4
- package/harness/bundles/java/claude-code/scripts/harness_knowledge_candidates.py +140 -4
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-archive/reference.md +30 -1
- package/harness/bundles/java/codebuddy/harness-archive/templates/summary-data-template.json +1 -0
- package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-execute/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-pull/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-push/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +141 -4
- package/harness/bundles/java/codebuddy/scripts/harness_knowledge_candidates.py +140 -4
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-archive/reference.md +30 -1
- package/harness/bundles/java/codex/harness-archive/templates/summary-data-template.json +1 -0
- package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-execute/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-pull/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-push/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/codex/scripts/harness_archive.py +141 -4
- package/harness/bundles/java/codex/scripts/harness_knowledge_candidates.py +140 -4
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-archive/reference.md +30 -1
- package/harness/bundles/java/cursor/harness-archive/templates/summary-data-template.json +1 -0
- package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-execute/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-pull/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-push/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/cursor/scripts/harness_archive.py +141 -4
- package/harness/bundles/java/cursor/scripts/harness_knowledge_candidates.py +140 -4
- package/harness/manifests/general/claude-code.json +18 -18
- package/harness/manifests/general/codebuddy.json +18 -18
- package/harness/manifests/general/codex.json +18 -18
- package/harness/manifests/general/cursor.json +18 -18
- package/harness/manifests/java/claude-code.json +20 -20
- package/harness/manifests/java/codebuddy.json +20 -20
- package/harness/manifests/java/codex.json +20 -20
- package/harness/manifests/java/cursor.json +20 -20
- package/hunter-workflow-family.json +2 -2
- package/package.json +1 -1
|
@@ -503,6 +503,96 @@ def _remote_ci_history_present(change_dir: Path) -> bool:
|
|
|
503
503
|
)
|
|
504
504
|
|
|
505
505
|
|
|
506
|
+
# decisions.json 单条记录的上限:防呆,不是安全边界(归档包大小限制在服务端)。
|
|
507
|
+
_DECISIONS_MAX_ENTRIES = 200
|
|
508
|
+
_DECISIONS_MAX_TITLE = 500
|
|
509
|
+
_DECISIONS_MAX_RATIONALE = 4000
|
|
510
|
+
_DECISIONS_MAX_KEYWORDS = 32
|
|
511
|
+
_DECISIONS_MAX_KEYWORD_CHARS = 80
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
def _decision_record_valid(record: dict[str, Any]) -> bool:
|
|
515
|
+
"""evidence/decisions.json 单条记录的确定性校验(与 hkc 的消费端口径一致)。"""
|
|
516
|
+
title = str(record.get("title") or "").strip()
|
|
517
|
+
if not title or len(title) > _DECISIONS_MAX_TITLE:
|
|
518
|
+
return False
|
|
519
|
+
if str(record.get("entry_type") or "").strip() not in {
|
|
520
|
+
"decision",
|
|
521
|
+
"requirement",
|
|
522
|
+
"api-contract",
|
|
523
|
+
}:
|
|
524
|
+
return False
|
|
525
|
+
if str(record.get("status") or "").strip().lower() not in {
|
|
526
|
+
"adopted",
|
|
527
|
+
"proposed",
|
|
528
|
+
"rejected",
|
|
529
|
+
"superseded",
|
|
530
|
+
}:
|
|
531
|
+
return False
|
|
532
|
+
rationale = record.get("rationale")
|
|
533
|
+
if rationale is not None and (
|
|
534
|
+
not isinstance(rationale, str) or len(rationale) > _DECISIONS_MAX_RATIONALE
|
|
535
|
+
):
|
|
536
|
+
return False
|
|
537
|
+
record_id = record.get("id")
|
|
538
|
+
if record_id is not None and (
|
|
539
|
+
not isinstance(record_id, str) or len(record_id.strip()) > 80
|
|
540
|
+
):
|
|
541
|
+
return False
|
|
542
|
+
path = record.get("path")
|
|
543
|
+
if path is not None:
|
|
544
|
+
if not isinstance(path, str) or len(path) > 500:
|
|
545
|
+
return False
|
|
546
|
+
normalized = path.replace("\\", "/")
|
|
547
|
+
if normalized.startswith("/") or ".." in normalized.split("/") or ":" in normalized:
|
|
548
|
+
return False
|
|
549
|
+
line = record.get("line")
|
|
550
|
+
if line is not None and (isinstance(line, bool) or not isinstance(line, int) or line < 1):
|
|
551
|
+
return False
|
|
552
|
+
keywords = record.get("keywords")
|
|
553
|
+
if keywords is not None:
|
|
554
|
+
if not isinstance(keywords, list) or len(keywords) > _DECISIONS_MAX_KEYWORDS:
|
|
555
|
+
return False
|
|
556
|
+
if any(
|
|
557
|
+
not isinstance(item, str) or not item.strip() or len(item) > _DECISIONS_MAX_KEYWORD_CHARS
|
|
558
|
+
for item in keywords
|
|
559
|
+
):
|
|
560
|
+
return False
|
|
561
|
+
source = record.get("source")
|
|
562
|
+
if source is not None and str(source).strip() not in {"plan", "review", "manual", "archive"}:
|
|
563
|
+
return False
|
|
564
|
+
return True
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def load_change_decisions(change_dir: Path) -> tuple[list[dict[str, Any]], int]:
|
|
568
|
+
"""Load ``evidence/decisions.json`` — 上游(plan/execute/review)采纳的结构化决策。
|
|
569
|
+
|
|
570
|
+
Returns (valid records, dropped count). 文件缺失/损坏/版本不符视为没有决策;
|
|
571
|
+
单条不合法的记录被丢弃并计数,由调用方决定是否告警——丢弃不能无声。
|
|
572
|
+
"""
|
|
573
|
+
path = _first_archive_path(change_dir, "evidence/decisions.json")
|
|
574
|
+
if path is None:
|
|
575
|
+
return [], 0
|
|
576
|
+
try:
|
|
577
|
+
data = read_json(path)
|
|
578
|
+
except (OSError, json.JSONDecodeError):
|
|
579
|
+
return [], 0
|
|
580
|
+
if not isinstance(data, dict) or data.get("schema_version") != 1:
|
|
581
|
+
return [], 0
|
|
582
|
+
records = data.get("decisions")
|
|
583
|
+
if not isinstance(records, list):
|
|
584
|
+
return [], 0
|
|
585
|
+
valid: list[dict[str, Any]] = []
|
|
586
|
+
dropped = 0
|
|
587
|
+
for record in records[: _DECISIONS_MAX_ENTRIES]:
|
|
588
|
+
if isinstance(record, dict) and _decision_record_valid(record):
|
|
589
|
+
valid.append(record)
|
|
590
|
+
else:
|
|
591
|
+
dropped += 1
|
|
592
|
+
dropped += max(0, len(records) - _DECISIONS_MAX_ENTRIES)
|
|
593
|
+
return valid, dropped
|
|
594
|
+
|
|
595
|
+
|
|
506
596
|
def load_product_candidate_ci(change_dir: Path) -> dict[str, Any] | None:
|
|
507
597
|
"""Load platform-neutral candidate evidence, then legacy CI evidence."""
|
|
508
598
|
for relative in (
|
|
@@ -4201,11 +4291,16 @@ def _stage_status_from_sources(
|
|
|
4201
4291
|
}
|
|
4202
4292
|
projected_events = he.apply_event_corrections(events)
|
|
4203
4293
|
execute_phase_end_seen = False
|
|
4294
|
+
# 服务端 CLI schema 2.3 要求全阶段键集 {plan, run, test, review, submit,
|
|
4295
|
+
# archive},而 2026-08 起事件侧 run+test 已合并为 execute。仍带 run/test
|
|
4296
|
+
# 原名的旧事件在折叠进 execute 之前单独留一份,供归档时拆分还原。
|
|
4297
|
+
raw_run_test: dict[str, str] = {}
|
|
4204
4298
|
for event in projected_events:
|
|
4205
4299
|
if event.get("type") != "phase.end":
|
|
4206
4300
|
continue
|
|
4207
4301
|
# 旧事件的 run/test phase.end 折叠进 execute,按事件序后写胜。
|
|
4208
|
-
|
|
4302
|
+
raw_phase = str(event.get("phase") or "").strip().lower()
|
|
4303
|
+
phase = hp.resolve_phase_name(raw_phase) or ""
|
|
4209
4304
|
raw = str(event.get("status") or "").upper()
|
|
4210
4305
|
if phase not in status or not raw:
|
|
4211
4306
|
continue
|
|
@@ -4218,6 +4313,8 @@ def _stage_status_from_sources(
|
|
|
4218
4313
|
elif raw in {"SKIP", "SKIPPED"}:
|
|
4219
4314
|
raw = "USER_SKIPPED"
|
|
4220
4315
|
status[phase] = raw
|
|
4316
|
+
if raw_phase in {"run", "test"}:
|
|
4317
|
+
raw_run_test[raw_phase] = raw
|
|
4221
4318
|
# Issues in events can downgrade. H-14: informational / hygiene / agent-preflight
|
|
4222
4319
|
# notes must not downgrade an already-OK phase.end.
|
|
4223
4320
|
_informational_markers = (
|
|
@@ -4272,7 +4369,18 @@ def _stage_status_from_sources(
|
|
|
4272
4369
|
if not review_evidence_present(change_dir, projected_events):
|
|
4273
4370
|
status["review"] = "ADVISORY"
|
|
4274
4371
|
|
|
4275
|
-
|
|
4372
|
+
# 服务端 schema 2.3 是 passthrough:execute 键保留供既有消费方使用,
|
|
4373
|
+
# 同时补上 run/test 满足必需键。旧事件带 run/test 原名时按原名拆分,
|
|
4374
|
+
# 否则镜像 execute 聚合值(合并事件流里没有更细的信号可拆)。
|
|
4375
|
+
return {
|
|
4376
|
+
"plan": status["plan"],
|
|
4377
|
+
"execute": status["execute"],
|
|
4378
|
+
"run": raw_run_test.get("run", status["execute"]),
|
|
4379
|
+
"test": raw_run_test.get("test", status["execute"]),
|
|
4380
|
+
"review": status["review"],
|
|
4381
|
+
"submit": status["submit"],
|
|
4382
|
+
"archive": status["archive"],
|
|
4383
|
+
}
|
|
4276
4384
|
|
|
4277
4385
|
|
|
4278
4386
|
def _compute_final_status(
|
|
@@ -5264,6 +5372,7 @@ def collect_summary_data(
|
|
|
5264
5372
|
"changedFiles",
|
|
5265
5373
|
"artifacts",
|
|
5266
5374
|
"reviewSummary",
|
|
5375
|
+
"decisions",
|
|
5267
5376
|
"archiveManifest",
|
|
5268
5377
|
"uncommittedTestEvidence",
|
|
5269
5378
|
"maintenanceNotes",
|
|
@@ -5630,6 +5739,12 @@ def collect_summary_data(
|
|
|
5630
5739
|
)
|
|
5631
5740
|
review_status = hr.status(change_dir)
|
|
5632
5741
|
data["reviewFindings"] = list(review_status.get("items") or [])
|
|
5742
|
+
decisions_dropped = 0
|
|
5743
|
+
if not for_replay:
|
|
5744
|
+
decisions, decisions_dropped = load_change_decisions(change_dir)
|
|
5745
|
+
data["decisions"] = decisions
|
|
5746
|
+
else:
|
|
5747
|
+
data.setdefault("decisions", [])
|
|
5633
5748
|
if not for_replay:
|
|
5634
5749
|
data["timeline"] = _timeline_from_events(event_summary, projected_events)
|
|
5635
5750
|
else:
|
|
@@ -5662,10 +5777,20 @@ def collect_summary_data(
|
|
|
5662
5777
|
if note:
|
|
5663
5778
|
maintenance_notes.append(note)
|
|
5664
5779
|
data["maintenanceNotes"] = maintenance_notes
|
|
5780
|
+
if decisions_dropped:
|
|
5781
|
+
# 丢弃不能无声:decisions.json 是人/agent 显式写的上游产物。
|
|
5782
|
+
data["maintenanceNotes"].append(
|
|
5783
|
+
f"evidence/decisions.json:{decisions_dropped} 条记录不符合 "
|
|
5784
|
+
"schema(缺 title/entry_type/status 或越界)已丢弃"
|
|
5785
|
+
)
|
|
5665
5786
|
scenario_risks, scenario_actions = _risks_from_test_results(change_dir)
|
|
5666
5787
|
data["knownRisks"] = known_risks + scenario_risks
|
|
5667
5788
|
data["manualActions"] = scenario_actions
|
|
5789
|
+
execute_status = (data.get("stageStatus") or {}).get("execute")
|
|
5668
5790
|
for name, value in (data.get("stageStatus") or {}).items():
|
|
5791
|
+
# run/test 镜像 execute 聚合值时不重复生成同一条人工动作。
|
|
5792
|
+
if name in {"run", "test"} and value == execute_status:
|
|
5793
|
+
continue
|
|
5669
5794
|
if value in {"BLOCKED", "BLOCKED_BY_ENV", "BLOCKED_BY_DBA", "NOT_RUN", "USER_SKIPPED"}:
|
|
5670
5795
|
data["manualActions"].append({
|
|
5671
5796
|
"stage": name,
|
|
@@ -8592,15 +8717,27 @@ def cmd_finalize(
|
|
|
8592
8717
|
|
|
8593
8718
|
# --- 8b. knowledge candidates (also before the after-manifest) ---
|
|
8594
8719
|
# Soft-fail like archive-meta: an archive must never be rolled back because
|
|
8595
|
-
# knowledge extraction found nothing. An empty array is a valid outcome
|
|
8720
|
+
# knowledge extraction found nothing. An empty array is a valid outcome —
|
|
8721
|
+
# but an empty array in the presence of unadjudicated findings is a
|
|
8722
|
+
# *different* situation and must be said out loud, not silently shown as
|
|
8723
|
+
# "ready / 0 results" downstream.
|
|
8596
8724
|
try:
|
|
8597
8725
|
summary = read_json(summary_path)
|
|
8598
8726
|
candidates_path = write_knowledge_candidates(work_dir, summary)
|
|
8727
|
+
candidate_count = len(read_json(candidates_path))
|
|
8728
|
+
unadjudicated = hkc.count_unadjudicated_findings(summary)
|
|
8599
8729
|
payload["steps"]["knowledge_candidates"] = {
|
|
8600
8730
|
"ok": True,
|
|
8601
8731
|
"path": str(candidates_path),
|
|
8602
|
-
"count":
|
|
8732
|
+
"count": candidate_count,
|
|
8733
|
+
"droppedUnadjudicated": unadjudicated,
|
|
8603
8734
|
}
|
|
8735
|
+
if unadjudicated > 0 and candidate_count == 0:
|
|
8736
|
+
warnings.append(
|
|
8737
|
+
f"本次归档有 {unadjudicated} 条未裁决(OPEN/UNKNOWN)的评审发现,"
|
|
8738
|
+
"知识候选为 0:它们按现行策略被丢弃而未形成知识。"
|
|
8739
|
+
"若其中有值得沉淀的内容,请先完成裁决再 republish。"
|
|
8740
|
+
)
|
|
8604
8741
|
except Exception as exc: # noqa: BLE001 — candidates soft-fail
|
|
8605
8742
|
warnings.append(f"knowledge candidates write failed: {exc}")
|
|
8606
8743
|
payload["steps"]["knowledge_candidates"] = {"ok": False, "error": str(exc)}
|
|
@@ -2,17 +2,21 @@
|
|
|
2
2
|
"""Knowledge candidate generation from an archived change's summary-data.json.
|
|
3
3
|
|
|
4
4
|
The archive workflow has already filtered once: review findings were produced by
|
|
5
|
-
an independent reviewer and then adjudicated,
|
|
6
|
-
facts
|
|
7
|
-
|
|
5
|
+
an independent reviewer and then adjudicated, knownRisks are evidence-derived
|
|
6
|
+
facts, and decisions are structured records adopted upstream (plan/execute/
|
|
7
|
+
review). This module turns those three — and only those three — into
|
|
8
|
+
KnowledgeCandidate records for the archive package's ``candidates/knowledge.json``.
|
|
8
9
|
|
|
9
10
|
Mapping is fixed by docs/superpowers/specs/2026-08-18-three-views-data-flow-design.md
|
|
10
|
-
("知识来源的选定")::
|
|
11
|
+
("知识来源的选定"), extended 2026-08-23 with the decisions source::
|
|
11
12
|
|
|
12
13
|
disposition = FIXED -> pitfall RED 0.95 / YELLOW 0.85
|
|
13
14
|
disposition = ACCEPTED_RISK | DEFERRED -> risk RED 0.95 / YELLOW 0.85
|
|
14
15
|
knownRisks[] -> risk 0.85
|
|
16
|
+
decisions[status=adopted] -> record's entry_type (decision |
|
|
17
|
+
requirement | api-contract) 0.85
|
|
15
18
|
severity = OK | disposition = NOT_APPLICABLE -> dropped
|
|
19
|
+
decisions[status != adopted] -> kept in summary, not knowledge
|
|
16
20
|
|
|
17
21
|
Dispositions outside the adopted set (OPEN / UNKNOWN) are dropped too: an
|
|
18
22
|
unadjudicated finding is not yet knowledge. maintenanceNotes, finalStatusReasons
|
|
@@ -42,6 +46,16 @@ _DISPOSITION_ENTRY_TYPES = {
|
|
|
42
46
|
_SEVERITY_CONFIDENCE = {"RED": 0.95, "YELLOW": 0.85}
|
|
43
47
|
_KNOWN_RISK_CONFIDENCE = 0.85
|
|
44
48
|
|
|
49
|
+
# decisions[](来自 change 的 evidence/decisions.json,经 summary.decisions 传入)
|
|
50
|
+
# 与 findings 的裁决门槛同源:只有已采纳(adopted)的决策才成为候选——
|
|
51
|
+
# proposed/rejected/superseded 留在 summary 里做记录,但不构成知识。
|
|
52
|
+
# entry_type 直接取自记录,取值与 knowledgeCandidateEntryTypeSchema 对齐;
|
|
53
|
+
# source 对应 candidateProvenanceSourceKindSchema 的枚举。
|
|
54
|
+
_DECISION_ENTRY_TYPES = {"decision", "requirement", "api-contract"}
|
|
55
|
+
_DECISION_STATUSES = {"adopted", "proposed", "rejected", "superseded"}
|
|
56
|
+
_DECISION_SOURCE_KINDS = {"plan", "review", "manual", "archive"}
|
|
57
|
+
_DECISION_CONFIDENCE = 0.85
|
|
58
|
+
|
|
45
59
|
_MAX_KEYWORDS = 32
|
|
46
60
|
_MAX_KEYWORD_CHARS = 80
|
|
47
61
|
_MAX_BODY_CHARS = 20_000
|
|
@@ -204,6 +218,86 @@ def _risk_candidate(
|
|
|
204
218
|
}
|
|
205
219
|
|
|
206
220
|
|
|
221
|
+
def _decision_candidate(
|
|
222
|
+
record: dict[str, Any],
|
|
223
|
+
*,
|
|
224
|
+
change_key: str,
|
|
225
|
+
archive_id: str,
|
|
226
|
+
producer_version: str,
|
|
227
|
+
created_at: str,
|
|
228
|
+
) -> dict[str, Any] | None:
|
|
229
|
+
"""Project one adopted design decision / requirement / API contract entry.
|
|
230
|
+
|
|
231
|
+
Every field is copied from the record (written upstream by a human or an
|
|
232
|
+
agent during plan/execute/review); nothing is inferred at archive time.
|
|
233
|
+
"""
|
|
234
|
+
title = _text(record.get("title"))
|
|
235
|
+
entry_type = _text(record.get("entry_type"))
|
|
236
|
+
status = _text(record.get("status")).lower()
|
|
237
|
+
if not title or entry_type not in _DECISION_ENTRY_TYPES or status != "adopted":
|
|
238
|
+
return None
|
|
239
|
+
|
|
240
|
+
rationale = _text(record.get("rationale"))
|
|
241
|
+
path = _text(record.get("path"))
|
|
242
|
+
line = record.get("line")
|
|
243
|
+
location = _location(path, line)
|
|
244
|
+
segments = _path_segments(path)
|
|
245
|
+
record_id = _text(record.get("id"))
|
|
246
|
+
source = _text(record.get("source"))
|
|
247
|
+
if source not in _DECISION_SOURCE_KINDS:
|
|
248
|
+
source = "plan"
|
|
249
|
+
raw_keywords = record.get("keywords")
|
|
250
|
+
record_keywords = (
|
|
251
|
+
[item for item in raw_keywords if isinstance(item, str)]
|
|
252
|
+
if isinstance(raw_keywords, list)
|
|
253
|
+
else []
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
body_lines = [title]
|
|
257
|
+
if rationale:
|
|
258
|
+
body_lines.append(f"理由:{rationale}")
|
|
259
|
+
if location:
|
|
260
|
+
body_lines.append(f"位置:{location}")
|
|
261
|
+
body_lines.append(f"类型:{entry_type}")
|
|
262
|
+
body = "\n".join(body_lines)[:_MAX_BODY_CHARS]
|
|
263
|
+
keywords = _keywords(
|
|
264
|
+
*record_keywords,
|
|
265
|
+
segments[-1] if segments else "",
|
|
266
|
+
segments[-2] if len(segments) >= 2 else "",
|
|
267
|
+
entry_type,
|
|
268
|
+
)
|
|
269
|
+
if path and location != path:
|
|
270
|
+
source_refs = [f"{path}#L{line}"]
|
|
271
|
+
elif path:
|
|
272
|
+
source_refs = [path]
|
|
273
|
+
else:
|
|
274
|
+
source_refs = [f"archive:{archive_id}"]
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
"schema_version": SCHEMA_VERSION,
|
|
278
|
+
"candidate_id": _candidate_id(
|
|
279
|
+
change_key, "decision", record_id or f"{title}\0{path}\0{line}"
|
|
280
|
+
),
|
|
281
|
+
"source_change_key": change_key,
|
|
282
|
+
"source_refs": source_refs,
|
|
283
|
+
"summary": title,
|
|
284
|
+
"reusability_scope": segments[0] if segments else "project",
|
|
285
|
+
"content_hash": _content_hash(entry_type, title, body, keywords),
|
|
286
|
+
"confidence": _DECISION_CONFIDENCE,
|
|
287
|
+
"status": "pending",
|
|
288
|
+
"entry_type": entry_type,
|
|
289
|
+
"body": body,
|
|
290
|
+
"keywords": keywords,
|
|
291
|
+
"provenance": {
|
|
292
|
+
"source_kind": source,
|
|
293
|
+
"source_ref": f"archive:{archive_id}#{record_id}" if record_id else f"archive:{archive_id}",
|
|
294
|
+
"producer": PRODUCER,
|
|
295
|
+
"producer_version": producer_version,
|
|
296
|
+
"created_at": created_at,
|
|
297
|
+
},
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
|
|
207
301
|
def build_knowledge_candidates(
|
|
208
302
|
summary: dict[str, Any],
|
|
209
303
|
*,
|
|
@@ -252,9 +346,51 @@ def build_knowledge_candidates(
|
|
|
252
346
|
created_at=created_at,
|
|
253
347
|
))
|
|
254
348
|
|
|
349
|
+
decisions = summary.get("decisions")
|
|
350
|
+
if isinstance(decisions, list):
|
|
351
|
+
for record in decisions:
|
|
352
|
+
if isinstance(record, dict):
|
|
353
|
+
collect(_decision_candidate(
|
|
354
|
+
record,
|
|
355
|
+
change_key=change_key,
|
|
356
|
+
archive_id=archive_id,
|
|
357
|
+
producer_version=producer_version,
|
|
358
|
+
created_at=created_at,
|
|
359
|
+
))
|
|
360
|
+
|
|
255
361
|
return candidates
|
|
256
362
|
|
|
257
363
|
|
|
364
|
+
# Dispositions that mean "not yet adjudicated". A finding in this state with a
|
|
365
|
+
# knowledge-carrying severity is dropped by the mapping above — correctly — but
|
|
366
|
+
# the drop must be visible, or an archive with real findings looks identical to
|
|
367
|
+
# an archive with nothing worth keeping (both ship an empty candidates file).
|
|
368
|
+
_UNADJUDICATED_DISPOSITIONS = {"", "OPEN", "UNKNOWN"}
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def count_unadjudicated_findings(summary: dict[str, Any]) -> int:
|
|
372
|
+
"""Count RED/YELLOW reviewFindings whose disposition is not yet adjudicated.
|
|
373
|
+
|
|
374
|
+
These are the findings the mapping table silently drops. Callers use the
|
|
375
|
+
count to warn when an archive would otherwise show "ready / 0 results"
|
|
376
|
+
despite carrying real, unprocessed review signal.
|
|
377
|
+
"""
|
|
378
|
+
if not isinstance(summary, dict):
|
|
379
|
+
return 0
|
|
380
|
+
findings = summary.get("reviewFindings")
|
|
381
|
+
if not isinstance(findings, list):
|
|
382
|
+
return 0
|
|
383
|
+
count = 0
|
|
384
|
+
for finding in findings:
|
|
385
|
+
if not isinstance(finding, dict):
|
|
386
|
+
continue
|
|
387
|
+
severity = _text(finding.get("severity"))
|
|
388
|
+
disposition = _text(finding.get("disposition")).upper()
|
|
389
|
+
if severity in _SEVERITIES and disposition in _UNADJUDICATED_DISPOSITIONS:
|
|
390
|
+
count += 1
|
|
391
|
+
return count
|
|
392
|
+
|
|
393
|
+
|
|
258
394
|
def render_knowledge_candidates_json(candidates: list[dict[str, Any]]) -> str:
|
|
259
395
|
"""Deterministic bytes for the archive package entry."""
|
|
260
396
|
return json.dumps(
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
{
|
|
27
27
|
"path": ".harness-build.json",
|
|
28
|
-
"sha256": "
|
|
28
|
+
"sha256": "f0d33ec19e5b767e139f69ddf99f7b3f279b09f4b034a07846ca879e23cda041"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"path": "agents/harness-evaluator.md",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
91
|
"path": "harness-archive/reference.md",
|
|
92
|
-
"sha256": "
|
|
92
|
+
"sha256": "1c28d9cc85badac2aa99f6e95d31f25dc3ea5c6f682c261b2f978cff98972e1d"
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
"path": "harness-archive/scripts/gen-manifest.ps1",
|
|
@@ -97,11 +97,11 @@
|
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
99
|
"path": "harness-archive/SKILL.md",
|
|
100
|
-
"sha256": "
|
|
100
|
+
"sha256": "b8dde1539e64aeb047836bde1fefbed61c113f9e66486921820c304bea6b9d9c"
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
103
|
"path": "harness-archive/templates/summary-data-template.json",
|
|
104
|
-
"sha256": "
|
|
104
|
+
"sha256": "9fbe0618dcfc8c12a7062a80b78d43ce3ce3ac0732448e0c41461af46822343f"
|
|
105
105
|
},
|
|
106
106
|
{
|
|
107
107
|
"path": "harness-codebase-map/checklist.md",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
},
|
|
114
114
|
{
|
|
115
115
|
"path": "harness-codebase-map/SKILL.md",
|
|
116
|
-
"sha256": "
|
|
116
|
+
"sha256": "3c24469f188da68b46c8058461f89aa930d3713bc41c1ca97226fc24024965ad"
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
"path": "harness-codebase-map/templates/ARCHITECTURE.md",
|
|
@@ -153,15 +153,15 @@
|
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
155
|
"path": "harness-execute/SKILL.md",
|
|
156
|
-
"sha256": "
|
|
156
|
+
"sha256": "5a538066d3a65eed875ccdf6953c17b57c6227a896ff6a83e4def806b9263bcd"
|
|
157
157
|
},
|
|
158
158
|
{
|
|
159
159
|
"path": "harness-knowledge-ingest/SKILL.md",
|
|
160
|
-
"sha256": "
|
|
160
|
+
"sha256": "d8e0f384d54c64d6d4cbb98af84932ce699c770d4ce51760c9c9fd6cbffc2155"
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
163
|
"path": "harness-knowledge-query/SKILL.md",
|
|
164
|
-
"sha256": "
|
|
164
|
+
"sha256": "fea684b9c194e7c421888abbf8ab2e0464e8ac2ba1fd8cc248452c5214cf3f22"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
167
|
"path": "harness-plan/checklist.md",
|
|
@@ -177,15 +177,15 @@
|
|
|
177
177
|
},
|
|
178
178
|
{
|
|
179
179
|
"path": "harness-plan/SKILL.md",
|
|
180
|
-
"sha256": "
|
|
180
|
+
"sha256": "304367db8f6e7095fa55e468eccb7e28dbc8355896c26eb178409acc071c4e50"
|
|
181
181
|
},
|
|
182
182
|
{
|
|
183
183
|
"path": "harness-pull/SKILL.md",
|
|
184
|
-
"sha256": "
|
|
184
|
+
"sha256": "96487069ff3a8c271b2d64c95ded318c12f3e498c90c56f44e31cd58a7ff06f6"
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
187
|
"path": "harness-push/SKILL.md",
|
|
188
|
-
"sha256": "
|
|
188
|
+
"sha256": "944bae63aaea994ae4a351c22a263a7c8adc53d22c34e625e99c9abd6421efd7"
|
|
189
189
|
},
|
|
190
190
|
{
|
|
191
191
|
"path": "harness-review/checklist.md",
|
|
@@ -201,7 +201,7 @@
|
|
|
201
201
|
},
|
|
202
202
|
{
|
|
203
203
|
"path": "harness-review/SKILL.md",
|
|
204
|
-
"sha256": "
|
|
204
|
+
"sha256": "87d11c29701c079d2b9344355f288dd30c0affb8c516a297a62f0c8e9b316763"
|
|
205
205
|
},
|
|
206
206
|
{
|
|
207
207
|
"path": "harness-run/checklist.md",
|
|
@@ -217,7 +217,7 @@
|
|
|
217
217
|
},
|
|
218
218
|
{
|
|
219
219
|
"path": "harness-run/SKILL.md",
|
|
220
|
-
"sha256": "
|
|
220
|
+
"sha256": "a3f67e29f48c7d85de3f801604d05884f423c80b7cedeb8a60c986f61ba72dfe"
|
|
221
221
|
},
|
|
222
222
|
{
|
|
223
223
|
"path": "harness-submit/checklist.md",
|
|
@@ -229,7 +229,7 @@
|
|
|
229
229
|
},
|
|
230
230
|
{
|
|
231
231
|
"path": "harness-submit/SKILL.md",
|
|
232
|
-
"sha256": "
|
|
232
|
+
"sha256": "10df5236533e848015c125ea73c725895d0a970011b7e3bdc9ba04fc7f738351"
|
|
233
233
|
},
|
|
234
234
|
{
|
|
235
235
|
"path": "harness-sync/reference.md",
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
},
|
|
238
238
|
{
|
|
239
239
|
"path": "harness-sync/SKILL.md",
|
|
240
|
-
"sha256": "
|
|
240
|
+
"sha256": "463171a25792b700f221f4d22a7c6c2dbc3614b5b195e278feeacc93ef893557"
|
|
241
241
|
},
|
|
242
242
|
{
|
|
243
243
|
"path": "harness-test/checklist.md",
|
|
@@ -261,7 +261,7 @@
|
|
|
261
261
|
},
|
|
262
262
|
{
|
|
263
263
|
"path": "harness-test/SKILL.md",
|
|
264
|
-
"sha256": "
|
|
264
|
+
"sha256": "52221499feb2ca6ca8f7f2247a84f8f672a7d37c6b1347a22dc461232ff11daa"
|
|
265
265
|
},
|
|
266
266
|
{
|
|
267
267
|
"path": "protocols/archive-report-protocol.md",
|
|
@@ -337,7 +337,7 @@
|
|
|
337
337
|
},
|
|
338
338
|
{
|
|
339
339
|
"path": "scripts/harness_archive.py",
|
|
340
|
-
"sha256": "
|
|
340
|
+
"sha256": "cc73ae61ac8fc4da09a35a65a8fba88fe49e3bda02b8dd7879808a855bf888bd"
|
|
341
341
|
},
|
|
342
342
|
{
|
|
343
343
|
"path": "scripts/harness_change.py",
|
|
@@ -393,7 +393,7 @@
|
|
|
393
393
|
},
|
|
394
394
|
{
|
|
395
395
|
"path": "scripts/harness_knowledge_candidates.py",
|
|
396
|
-
"sha256": "
|
|
396
|
+
"sha256": "3cd0b9046821759cfc46221201d9760dc0a3b1613180a06b8ef3c821376b11c1"
|
|
397
397
|
},
|
|
398
398
|
{
|
|
399
399
|
"path": "scripts/harness_ledger.py",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
{
|
|
27
27
|
"path": ".harness-build.json",
|
|
28
|
-
"sha256": "
|
|
28
|
+
"sha256": "bd25a1b2cbe7e26c65ec27cad69c76465583847a3dcc716100334c708545a1cc"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"path": "agents/harness-evaluator.md",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
91
|
"path": "harness-archive/reference.md",
|
|
92
|
-
"sha256": "
|
|
92
|
+
"sha256": "1c28d9cc85badac2aa99f6e95d31f25dc3ea5c6f682c261b2f978cff98972e1d"
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
"path": "harness-archive/scripts/gen-manifest.ps1",
|
|
@@ -97,11 +97,11 @@
|
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
99
|
"path": "harness-archive/SKILL.md",
|
|
100
|
-
"sha256": "
|
|
100
|
+
"sha256": "9af57082a3e2dcda6fb33963756381f48b5c44d8c861a89ca3354c2709d67a23"
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
103
|
"path": "harness-archive/templates/summary-data-template.json",
|
|
104
|
-
"sha256": "
|
|
104
|
+
"sha256": "9fbe0618dcfc8c12a7062a80b78d43ce3ce3ac0732448e0c41461af46822343f"
|
|
105
105
|
},
|
|
106
106
|
{
|
|
107
107
|
"path": "harness-codebase-map/checklist.md",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
},
|
|
114
114
|
{
|
|
115
115
|
"path": "harness-codebase-map/SKILL.md",
|
|
116
|
-
"sha256": "
|
|
116
|
+
"sha256": "1ac65b2435bd9b31be595ad2571e4f30c233c1fb0a54e48ed792c00e499a8fa8"
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
"path": "harness-codebase-map/templates/ARCHITECTURE.md",
|
|
@@ -153,15 +153,15 @@
|
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
155
|
"path": "harness-execute/SKILL.md",
|
|
156
|
-
"sha256": "
|
|
156
|
+
"sha256": "ed76717932b9eff11565518419d3aac1a08c37b1c514be26c6621686dc064088"
|
|
157
157
|
},
|
|
158
158
|
{
|
|
159
159
|
"path": "harness-knowledge-ingest/SKILL.md",
|
|
160
|
-
"sha256": "
|
|
160
|
+
"sha256": "5faac1196aba982cedb8b3f2ea5d6e50c971129ac6d538727306f4c4a95cc518"
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
163
|
"path": "harness-knowledge-query/SKILL.md",
|
|
164
|
-
"sha256": "
|
|
164
|
+
"sha256": "07dec3ed6caec8f1f4474e9e450364c4086b953bbc5bb73d6167a3d304cf0a89"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
167
|
"path": "harness-plan/checklist.md",
|
|
@@ -177,15 +177,15 @@
|
|
|
177
177
|
},
|
|
178
178
|
{
|
|
179
179
|
"path": "harness-plan/SKILL.md",
|
|
180
|
-
"sha256": "
|
|
180
|
+
"sha256": "cb1819b68f23e4b9e70b5db6cefef8564c86705ffe1fde47fef4e81d989c471a"
|
|
181
181
|
},
|
|
182
182
|
{
|
|
183
183
|
"path": "harness-pull/SKILL.md",
|
|
184
|
-
"sha256": "
|
|
184
|
+
"sha256": "4fec95bac58d9a3cdf4d7e400bb854ddd6f05dab025207b9b70874c96656079c"
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
187
|
"path": "harness-push/SKILL.md",
|
|
188
|
-
"sha256": "
|
|
188
|
+
"sha256": "765013e8bc2b5b1b59632bc947188f323cc1f59fae986f1a44a328a36042dbcb"
|
|
189
189
|
},
|
|
190
190
|
{
|
|
191
191
|
"path": "harness-review/checklist.md",
|
|
@@ -201,7 +201,7 @@
|
|
|
201
201
|
},
|
|
202
202
|
{
|
|
203
203
|
"path": "harness-review/SKILL.md",
|
|
204
|
-
"sha256": "
|
|
204
|
+
"sha256": "46b355ae7cee3d349808847369cb5871111f801af0f563681b6f7eaa57f3fc78"
|
|
205
205
|
},
|
|
206
206
|
{
|
|
207
207
|
"path": "harness-run/checklist.md",
|
|
@@ -217,7 +217,7 @@
|
|
|
217
217
|
},
|
|
218
218
|
{
|
|
219
219
|
"path": "harness-run/SKILL.md",
|
|
220
|
-
"sha256": "
|
|
220
|
+
"sha256": "df0f7a5c27991a45295206b7aee1d2fda81ac1bcfc651fdd3585ee206905f621"
|
|
221
221
|
},
|
|
222
222
|
{
|
|
223
223
|
"path": "harness-submit/checklist.md",
|
|
@@ -229,7 +229,7 @@
|
|
|
229
229
|
},
|
|
230
230
|
{
|
|
231
231
|
"path": "harness-submit/SKILL.md",
|
|
232
|
-
"sha256": "
|
|
232
|
+
"sha256": "4729a6eeba8bdeb1521112e459c8037c9a6c610a08875c1de34139ddd01de7f6"
|
|
233
233
|
},
|
|
234
234
|
{
|
|
235
235
|
"path": "harness-sync/reference.md",
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
},
|
|
238
238
|
{
|
|
239
239
|
"path": "harness-sync/SKILL.md",
|
|
240
|
-
"sha256": "
|
|
240
|
+
"sha256": "dd3a27d25875420a8f28b6b3319c160bfd6b031551846cedc2c55c8a8419c0f1"
|
|
241
241
|
},
|
|
242
242
|
{
|
|
243
243
|
"path": "harness-test/checklist.md",
|
|
@@ -261,7 +261,7 @@
|
|
|
261
261
|
},
|
|
262
262
|
{
|
|
263
263
|
"path": "harness-test/SKILL.md",
|
|
264
|
-
"sha256": "
|
|
264
|
+
"sha256": "f26515ca88995fa3a903b1b525999589b470e90201e263bb44ca830cd67b5dba"
|
|
265
265
|
},
|
|
266
266
|
{
|
|
267
267
|
"path": "protocols/archive-report-protocol.md",
|
|
@@ -337,7 +337,7 @@
|
|
|
337
337
|
},
|
|
338
338
|
{
|
|
339
339
|
"path": "scripts/harness_archive.py",
|
|
340
|
-
"sha256": "
|
|
340
|
+
"sha256": "cc73ae61ac8fc4da09a35a65a8fba88fe49e3bda02b8dd7879808a855bf888bd"
|
|
341
341
|
},
|
|
342
342
|
{
|
|
343
343
|
"path": "scripts/harness_change.py",
|
|
@@ -393,7 +393,7 @@
|
|
|
393
393
|
},
|
|
394
394
|
{
|
|
395
395
|
"path": "scripts/harness_knowledge_candidates.py",
|
|
396
|
-
"sha256": "
|
|
396
|
+
"sha256": "3cd0b9046821759cfc46221201d9760dc0a3b1613180a06b8ef3c821376b11c1"
|
|
397
397
|
},
|
|
398
398
|
{
|
|
399
399
|
"path": "scripts/harness_ledger.py",
|