@hunter-harness/workflow-harness 0.2.30 → 0.2.32
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 +3 -3
- package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/harness-plan/SKILL.md +6 -6
- package/harness/bundles/general/claude-code/harness-plan/checklist.md +10 -4
- package/harness/bundles/general/claude-code/harness-plan/reference.md +17 -17
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +4 -4
- package/harness/bundles/general/claude-code/harness-run/checklist.md +2 -2
- package/harness/bundles/general/claude-code/harness-run/reference.md +3 -12
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/harness-sync/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/harness-test/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/scripts/harness_gate.py +92 -20
- package/harness/bundles/general/claude-code/scripts/harness_plan_finalize.py +461 -82
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +6 -6
- package/harness/bundles/general/codebuddy/harness-plan/checklist.md +10 -4
- package/harness/bundles/general/codebuddy/harness-plan/reference.md +17 -17
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +4 -4
- package/harness/bundles/general/codebuddy/harness-run/checklist.md +2 -2
- package/harness/bundles/general/codebuddy/harness-run/reference.md +3 -12
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-test/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/scripts/harness_gate.py +92 -20
- package/harness/bundles/general/codebuddy/scripts/harness_plan_finalize.py +461 -82
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/harness-archive/SKILL.md +3 -3
- package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +3 -3
- package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +3 -3
- package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +3 -3
- package/harness/bundles/general/codex/harness-plan/SKILL.md +6 -6
- package/harness/bundles/general/codex/harness-plan/checklist.md +10 -4
- package/harness/bundles/general/codex/harness-plan/reference.md +17 -17
- package/harness/bundles/general/codex/harness-review/SKILL.md +3 -3
- package/harness/bundles/general/codex/harness-run/SKILL.md +4 -4
- package/harness/bundles/general/codex/harness-run/checklist.md +2 -2
- package/harness/bundles/general/codex/harness-run/reference.md +3 -12
- package/harness/bundles/general/codex/harness-submit/SKILL.md +3 -3
- package/harness/bundles/general/codex/harness-sync/SKILL.md +3 -3
- package/harness/bundles/general/codex/harness-test/SKILL.md +3 -3
- package/harness/bundles/general/codex/scripts/harness_gate.py +92 -20
- package/harness/bundles/general/codex/scripts/harness_plan_finalize.py +461 -82
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +3 -3
- package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +3 -3
- package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +3 -3
- package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +3 -3
- package/harness/bundles/general/cursor/harness-plan/SKILL.md +6 -6
- package/harness/bundles/general/cursor/harness-plan/checklist.md +10 -4
- package/harness/bundles/general/cursor/harness-plan/reference.md +17 -17
- package/harness/bundles/general/cursor/harness-review/SKILL.md +3 -3
- package/harness/bundles/general/cursor/harness-run/SKILL.md +4 -4
- package/harness/bundles/general/cursor/harness-run/checklist.md +2 -2
- package/harness/bundles/general/cursor/harness-run/reference.md +3 -12
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +3 -3
- package/harness/bundles/general/cursor/harness-sync/SKILL.md +3 -3
- package/harness/bundles/general/cursor/harness-test/SKILL.md +3 -3
- package/harness/bundles/general/cursor/scripts/harness_gate.py +92 -20
- package/harness/bundles/general/cursor/scripts/harness_plan_finalize.py +461 -82
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-archive/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +6 -6
- package/harness/bundles/java/claude-code/harness-plan/checklist.md +10 -4
- package/harness/bundles/java/claude-code/harness-plan/reference.md +17 -17
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +4 -4
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/scripts/harness_gate.py +92 -20
- package/harness/bundles/java/claude-code/scripts/harness_plan_finalize.py +461 -82
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +6 -6
- package/harness/bundles/java/codebuddy/harness-plan/checklist.md +10 -4
- package/harness/bundles/java/codebuddy/harness-plan/reference.md +17 -17
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +4 -4
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/scripts/harness_gate.py +92 -20
- package/harness/bundles/java/codebuddy/scripts/harness_plan_finalize.py +461 -82
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- package/harness/bundles/java/codex/harness-apidoc/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-archive/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-plan/SKILL.md +6 -6
- package/harness/bundles/java/codex/harness-plan/checklist.md +10 -4
- package/harness/bundles/java/codex/harness-plan/reference.md +17 -17
- package/harness/bundles/java/codex/harness-review/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-run/SKILL.md +4 -4
- package/harness/bundles/java/codex/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-sync/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-test/SKILL.md +3 -3
- package/harness/bundles/java/codex/scripts/harness_gate.py +92 -20
- package/harness/bundles/java/codex/scripts/harness_plan_finalize.py +461 -82
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-archive/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +6 -6
- package/harness/bundles/java/cursor/harness-plan/checklist.md +10 -4
- package/harness/bundles/java/cursor/harness-plan/reference.md +17 -17
- package/harness/bundles/java/cursor/harness-review/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-run/SKILL.md +4 -4
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-test/SKILL.md +3 -3
- package/harness/bundles/java/cursor/scripts/harness_gate.py +92 -20
- package/harness/bundles/java/cursor/scripts/harness_plan_finalize.py +461 -82
- package/harness/manifests/general/claude-code.json +19 -19
- package/harness/manifests/general/codebuddy.json +19 -19
- package/harness/manifests/general/codex.json +19 -19
- package/harness/manifests/general/cursor.json +19 -19
- package/harness/manifests/java/claude-code.json +19 -19
- package/harness/manifests/java/codebuddy.json +19 -19
- package/harness/manifests/java/codex.json +19 -19
- package/harness/manifests/java/cursor.json +19 -19
- package/hunter-workflow-family.json +4 -4
- package/package.json +1 -1
|
@@ -33,6 +33,7 @@ import harness_change as hc # noqa: E402
|
|
|
33
33
|
import harness_events as he # noqa: E402
|
|
34
34
|
import harness_ledger as hl # noqa: E402
|
|
35
35
|
import harness_paths as hp # noqa: E402
|
|
36
|
+
import harness_plan_finalize as hpf # noqa: E402
|
|
36
37
|
import harness_workflow_policy as hwp # noqa: E402
|
|
37
38
|
import harness_test_guard as htg # noqa: E402
|
|
38
39
|
|
|
@@ -1588,10 +1589,11 @@ def _phase_event_exists(change_dir: Path, phase: str, type_: str, run_id: str) -
|
|
|
1588
1589
|
|
|
1589
1590
|
|
|
1590
1591
|
def _validate_scenario_coverage(change_dir: Path) -> dict[str, Any]:
|
|
1591
|
-
"""C9: validate all
|
|
1592
|
+
"""C9: validate all ledger-required scenarios are covered by ledger entries.
|
|
1592
1593
|
|
|
1593
1594
|
Reads meta/scenario-manifest.json and evidence/verification-ledger.json.
|
|
1594
|
-
Returns ok=True when manifest missing
|
|
1595
|
+
Returns ok=True when a legacy manifest is missing or all required scenarios
|
|
1596
|
+
are covered. A present but empty manifest is always invalid.
|
|
1595
1597
|
"""
|
|
1596
1598
|
manifest_path = change_dir / "meta" / "scenario-manifest.json"
|
|
1597
1599
|
if not manifest_path.is_file():
|
|
@@ -1604,33 +1606,57 @@ def _validate_scenario_coverage(change_dir: Path) -> dict[str, Any]:
|
|
|
1604
1606
|
"code": "SCENARIO_MANIFEST_INVALID",
|
|
1605
1607
|
"message": f"scenario-manifest.json unreadable: {exc}",
|
|
1606
1608
|
}
|
|
1607
|
-
scenarios = manifest.get("scenarios")
|
|
1608
|
-
|
|
1609
|
+
scenarios = manifest.get("scenarios") if isinstance(manifest, dict) else None
|
|
1610
|
+
if not isinstance(scenarios, list):
|
|
1611
|
+
return {
|
|
1612
|
+
"ok": False,
|
|
1613
|
+
"code": "SCENARIO_MANIFEST_INVALID",
|
|
1614
|
+
"message": "scenario-manifest.json scenarios must be a list",
|
|
1615
|
+
}
|
|
1616
|
+
if not scenarios:
|
|
1617
|
+
return {
|
|
1618
|
+
"ok": False,
|
|
1619
|
+
"code": "SCENARIO_MANIFEST_EMPTY",
|
|
1620
|
+
"message": "scenario-manifest.json must contain at least one scenario",
|
|
1621
|
+
}
|
|
1622
|
+
invalid_items = [
|
|
1623
|
+
index
|
|
1624
|
+
for index, scenario in enumerate(scenarios)
|
|
1625
|
+
if not isinstance(scenario, dict) or not str(scenario.get("id") or "").strip()
|
|
1626
|
+
]
|
|
1627
|
+
if invalid_items:
|
|
1628
|
+
return {
|
|
1629
|
+
"ok": False,
|
|
1630
|
+
"code": "SCENARIO_MANIFEST_INVALID",
|
|
1631
|
+
"message": f"scenario entries missing IDs at indexes: {invalid_items}",
|
|
1632
|
+
}
|
|
1633
|
+
required_ids = {
|
|
1609
1634
|
str(s.get("id"))
|
|
1610
1635
|
for s in scenarios
|
|
1611
1636
|
if isinstance(s, dict)
|
|
1612
|
-
and
|
|
1613
|
-
|
|
1637
|
+
and (
|
|
1638
|
+
str(s.get("priority", "")).upper() in {"P0", "P1"}
|
|
1639
|
+
or s.get("requiredEvidenceKind") == "ledger"
|
|
1640
|
+
)
|
|
1614
1641
|
}
|
|
1615
|
-
if not
|
|
1616
|
-
return {"ok": True, "code": "
|
|
1642
|
+
if not required_ids:
|
|
1643
|
+
return {"ok": True, "code": "NO_LEDGER_REQUIRED_SCENARIOS"}
|
|
1617
1644
|
|
|
1618
|
-
|
|
1619
|
-
|
|
1645
|
+
try:
|
|
1646
|
+
ledger, ledger_path = hl.load_ledger(change_dir)
|
|
1647
|
+
except (OSError, ValueError, json.JSONDecodeError) as exc:
|
|
1620
1648
|
return {
|
|
1621
1649
|
"ok": False,
|
|
1622
1650
|
"code": "SCENARIO_COVERAGE_FAILED",
|
|
1623
|
-
"message": "ledger
|
|
1624
|
-
"missing": sorted(
|
|
1651
|
+
"message": f"ledger unreadable: {exc}",
|
|
1652
|
+
"missing": sorted(required_ids),
|
|
1625
1653
|
}
|
|
1626
|
-
|
|
1627
|
-
ledger = json.loads(ledger_path.read_text(encoding="utf-8-sig"))
|
|
1628
|
-
except (OSError, json.JSONDecodeError) as exc:
|
|
1654
|
+
if ledger is None or ledger_path is None:
|
|
1629
1655
|
return {
|
|
1630
1656
|
"ok": False,
|
|
1631
1657
|
"code": "SCENARIO_COVERAGE_FAILED",
|
|
1632
|
-
"message":
|
|
1633
|
-
"missing": sorted(
|
|
1658
|
+
"message": "ledger missing; cannot verify required scenario coverage",
|
|
1659
|
+
"missing": sorted(required_ids),
|
|
1634
1660
|
}
|
|
1635
1661
|
covered: set[str] = set()
|
|
1636
1662
|
validations = ledger.get("validations") or {}
|
|
@@ -1640,15 +1666,38 @@ def _validate_scenario_coverage(change_dir: Path) -> dict[str, Any]:
|
|
|
1640
1666
|
ids = entry.get("scenarioIds")
|
|
1641
1667
|
if isinstance(ids, list):
|
|
1642
1668
|
covered.update(str(i) for i in ids)
|
|
1643
|
-
missing = sorted(
|
|
1669
|
+
missing = sorted(required_ids - covered)
|
|
1644
1670
|
if missing:
|
|
1645
1671
|
return {
|
|
1646
1672
|
"ok": False,
|
|
1647
1673
|
"code": "SCENARIO_COVERAGE_FAILED",
|
|
1648
|
-
"message":
|
|
1674
|
+
"message": (
|
|
1675
|
+
"ledger-required scenarios without ledger entry: "
|
|
1676
|
+
+ ", ".join(missing)
|
|
1677
|
+
),
|
|
1649
1678
|
"missing": missing,
|
|
1650
1679
|
}
|
|
1651
|
-
return {
|
|
1680
|
+
return {
|
|
1681
|
+
"ok": True,
|
|
1682
|
+
"code": "SCENARIO_COVERAGE_OK",
|
|
1683
|
+
"covered": sorted(covered & required_ids),
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
|
|
1687
|
+
def validate_plan_handoff(change_dir: Path) -> dict[str, Any]:
|
|
1688
|
+
"""Verify a finalized modern plan before the first run-side effect."""
|
|
1689
|
+
receipt_path = change_dir / "meta" / "plan-finalization.json"
|
|
1690
|
+
plans_root = change_dir / "plans"
|
|
1691
|
+
has_plan_artifacts = plans_root.is_dir() and any(
|
|
1692
|
+
plans_root.glob("*-plan.md")
|
|
1693
|
+
)
|
|
1694
|
+
if not receipt_path.is_file() and not has_plan_artifacts:
|
|
1695
|
+
return {
|
|
1696
|
+
"ok": True,
|
|
1697
|
+
"code": "PLAN_HANDOFF_NOT_APPLICABLE",
|
|
1698
|
+
"skipped": True,
|
|
1699
|
+
}
|
|
1700
|
+
return hpf.verify_plan(change_dir)
|
|
1652
1701
|
|
|
1653
1702
|
|
|
1654
1703
|
def cmd_begin(args: argparse.Namespace) -> int:
|
|
@@ -1663,6 +1712,28 @@ def cmd_begin(args: argparse.Namespace) -> int:
|
|
|
1663
1712
|
extra={k: v for k, v in resolved.items() if k not in {"ok", "message"}},
|
|
1664
1713
|
)
|
|
1665
1714
|
change_dir = Path(resolved["changeDir"])
|
|
1715
|
+
plan_verification: dict[str, Any] | None = None
|
|
1716
|
+
if args.phase == "run":
|
|
1717
|
+
plan_verification = validate_plan_handoff(change_dir)
|
|
1718
|
+
if not plan_verification.get("ok"):
|
|
1719
|
+
code = str(
|
|
1720
|
+
plan_verification.get("code") or "PLAN_HANDOFF_INVALID"
|
|
1721
|
+
)
|
|
1722
|
+
message = str(
|
|
1723
|
+
plan_verification.get("error")
|
|
1724
|
+
or plan_verification.get("message")
|
|
1725
|
+
or "finalized plan verification failed"
|
|
1726
|
+
)
|
|
1727
|
+
return emit_error(
|
|
1728
|
+
code,
|
|
1729
|
+
message,
|
|
1730
|
+
as_json=as_json,
|
|
1731
|
+
extra={
|
|
1732
|
+
key: value
|
|
1733
|
+
for key, value in plan_verification.items()
|
|
1734
|
+
if key not in {"ok", "code", "error", "message"}
|
|
1735
|
+
},
|
|
1736
|
+
)
|
|
1666
1737
|
concurrency_block = hc.check_concurrency_block(project, resolved["changeId"])
|
|
1667
1738
|
if concurrency_block is not None:
|
|
1668
1739
|
record_blocked_attempt(
|
|
@@ -1847,6 +1918,7 @@ def cmd_begin(args: argparse.Namespace) -> int:
|
|
|
1847
1918
|
"event": event_result,
|
|
1848
1919
|
"testGuard": guard_result,
|
|
1849
1920
|
"policySchemaVersion": policy.get("schemaVersion"),
|
|
1921
|
+
"planVerification": plan_verification,
|
|
1850
1922
|
"projection": projection,
|
|
1851
1923
|
"executionRootSource": execution_hint["source"],
|
|
1852
1924
|
}
|