Skip to content

Commit c2ea043

Browse files
authored
Merge branch 'main' into main
2 parents a5e6ca7 + 4d3dc5b commit c2ea043

36 files changed

Lines changed: 6687 additions & 453 deletions

.github/hooks/pre-push

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env bash
2+
# Claw Code local pre-push safety gate.
3+
#
4+
# Install with:
5+
# git config core.hooksPath .github/hooks
6+
#
7+
# This intentionally mirrors the CI build gate so stale field/enum references are
8+
# caught before pushing to main or PR branches.
9+
set -euo pipefail
10+
11+
repo_root="$(git rev-parse --show-toplevel 2>/dev/null)"
12+
cd "$repo_root"
13+
14+
if [[ -x scripts/roadmap-check-ids.sh ]]; then
15+
echo "pre-push: scripts/roadmap-check-ids.sh" >&2
16+
scripts/roadmap-check-ids.sh
17+
fi
18+
19+
if [[ "${SKIP_CLAW_PRE_PUSH_BUILD:-}" == "1" ]]; then
20+
echo "pre-push: SKIP_CLAW_PRE_PUSH_BUILD=1 set; skipping cargo workspace build" >&2
21+
exit 0
22+
fi
23+
24+
if [[ ! -f rust/Cargo.toml ]]; then
25+
echo "pre-push: rust/Cargo.toml not found; skipping cargo workspace build" >&2
26+
exit 0
27+
fi
28+
29+
build_cmd=(cargo build --manifest-path rust/Cargo.toml --workspace --locked)
30+
echo "pre-push: ${build_cmd[*]}" >&2
31+
"${build_cmd[@]}"

.github/workflows/rust-ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ on:
2121
- PARITY.md
2222
- PHILOSOPHY.md
2323
- ROADMAP.md
24+
- scripts/roadmap-*.sh
25+
- tests/test_roadmap_helpers.py
2426
- docs/**
2527
- rust/**
2628
pull_request:
@@ -41,6 +43,8 @@ on:
4143
- PARITY.md
4244
- PHILOSOPHY.md
4345
- ROADMAP.md
46+
- scripts/roadmap-*.sh
47+
- tests/test_roadmap_helpers.py
4448
- docs/**
4549
- rust/**
4650
workflow_dispatch:
@@ -72,6 +76,10 @@ jobs:
7276
run: python .github/scripts/check_doc_source_of_truth.py
7377
- name: Check release policy docs and local links
7478
run: python .github/scripts/check_release_readiness.py
79+
- name: Check ROADMAP ids
80+
run: scripts/roadmap-check-ids.sh
81+
- name: Check ROADMAP helper behavior
82+
run: python -m unittest discover -s tests -p test_roadmap_helpers.py
7583

7684
fmt:
7785
name: cargo fmt

.omx/cc2/board.json

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
"duplicate_roadmap_heading_lines": [],
44
"roadmap_actions_mapped": 542,
55
"roadmap_actions_total": 542,
6-
"roadmap_headings_mapped": 124,
7-
"roadmap_headings_total": 124,
6+
"roadmap_headings_mapped": 127,
7+
"roadmap_headings_total": 127,
88
"unmapped_roadmap_heading_lines": []
99
},
10-
"generated_at": "2026-05-14T08:13:45+00:00",
10+
"generated_at": "2026-05-25T04:30:33+00:00",
1111
"generation_policy": {
1212
"release_buckets": [
1313
"2.x_intake",
@@ -14823,6 +14823,69 @@
1482314823
"status": "context",
1482414824
"title": "Parity source metadata: openai/codex",
1482514825
"verification_required": "none_context_only"
14826+
},
14827+
{
14828+
"category": "boot",
14829+
"deferral_rationale": "",
14830+
"dependencies": [
14831+
"stream_0_governance"
14832+
],
14833+
"id": "CC2-RM-H0125-pinpoint-693-claw-analog-bootstrap-plan",
14834+
"lifecycle_status": "done_verify",
14835+
"owner_lane": "stream_1_worker_boot_session_control",
14836+
"release_bucket": "alpha_blocker",
14837+
"source_anchor": "ROADMAP.md:L7528",
14838+
"source_context": "Clawable Coding Harness Roadmap > Pinpoint follow-up intake",
14839+
"source_level": 2,
14840+
"source_line": 7528,
14841+
"source_ordinal": null,
14842+
"source_path": "ROADMAP.md",
14843+
"source_type": "roadmap_heading",
14844+
"status": "done_verify",
14845+
"title": "Pinpoint #693. `claw-analog` bootstrap-plan phase parser silently falls back to `\"unknown\"` \u2014 `lib.rs:1114` uses `.unwrap_or(\"unknown\")` for phase field; unrecognized phases emit opaque kind instead of typed error",
14846+
"verification_required": "targeted_regression_or_acceptance_test_required"
14847+
},
14848+
{
14849+
"category": "branch_recovery",
14850+
"deferral_rationale": "",
14851+
"dependencies": [
14852+
"stream_0_governance"
14853+
],
14854+
"id": "CC2-RM-H0126-pinpoint-694-no-pre-push-cargo-build-gat",
14855+
"lifecycle_status": "done_verify",
14856+
"owner_lane": "stream_3_branch_test_recovery",
14857+
"release_bucket": "alpha_blocker",
14858+
"source_anchor": "ROADMAP.md:L7538",
14859+
"source_context": "Clawable Coding Harness Roadmap > Pinpoint follow-up intake",
14860+
"source_level": 2,
14861+
"source_line": 7538,
14862+
"source_ordinal": null,
14863+
"source_path": "ROADMAP.md",
14864+
"source_type": "roadmap_heading",
14865+
"status": "done_verify",
14866+
"title": "Pinpoint #694. No pre-push `cargo build` gate \u2014 stale field refs (`retry_after`, `Team` variant, `config_load_error_kind`) broke main build undetected until CI",
14867+
"verification_required": "git_fixture_or_recovery_recipe_test"
14868+
},
14869+
{
14870+
"category": "boot",
14871+
"deferral_rationale": "",
14872+
"dependencies": [
14873+
"stream_0_governance"
14874+
],
14875+
"id": "CC2-RM-H0127-pinpoint-695-agent-starts-in-stale-wrong",
14876+
"lifecycle_status": "done_verify",
14877+
"owner_lane": "stream_1_worker_boot_session_control",
14878+
"release_bucket": "alpha_blocker",
14879+
"source_anchor": "ROADMAP.md:L7548",
14880+
"source_context": "Clawable Coding Harness Roadmap > Pinpoint follow-up intake",
14881+
"source_level": 2,
14882+
"source_line": 7548,
14883+
"source_ordinal": null,
14884+
"source_path": "ROADMAP.md",
14885+
"source_type": "roadmap_heading",
14886+
"status": "done_verify",
14887+
"title": "Pinpoint #695. Agent starts in stale/wrong worktree and burns a full turn before noticing \u2014 no pre-flight check for \"file exists on current branch\" or \"this .git is writable from sandbox\"",
14888+
"verification_required": "worker_boot_state_machine_or_cli_json_contract_test"
1482614889
}
1482714890
],
1482814891
"schema_version": "cc2.board.v1",
@@ -14839,7 +14902,7 @@
1483914902
"root": "/Users/bellman/Documents/Workspace/claw-code/.omx/research"
1484014903
},
1484114904
"roadmap": {
14842-
"heading_count": 124,
14905+
"heading_count": 127,
1484314906
"ordered_action_count": 542,
1484414907
"path": "ROADMAP.md",
1484514908
"sha256_prefix": "2aba3315e52f3079"
@@ -14850,15 +14913,15 @@
1485014913
"adoption_overlay": 357,
1485114914
"parity_overlay": 20,
1485214915
"stream_0_governance": 221,
14853-
"stream_1_worker_boot_session_control": 15,
14916+
"stream_1_worker_boot_session_control": 17,
1485414917
"stream_2_event_reporting_contracts": 73,
14855-
"stream_3_branch_test_recovery": 16,
14918+
"stream_3_branch_test_recovery": 17,
1485614919
"stream_4_claws_first_execution": 5,
1485714920
"stream_5_plugin_mcp_lifecycle": 22
1485814921
},
1485914922
"by_release_bucket": {
1486014923
"2.x_intake": 30,
14861-
"alpha_blocker": 240,
14924+
"alpha_blocker": 243,
1486214925
"beta_adoption": 417,
1486314926
"context": 15,
1486414927
"ga_ecosystem": 22,
@@ -14870,13 +14933,13 @@
1487014933
"latest_open_issue": 30,
1487114934
"parity_repo_context": 2,
1487214935
"roadmap_action": 542,
14873-
"roadmap_heading": 124
14936+
"roadmap_heading": 127
1487414937
},
1487514938
"by_status": {
1487614939
"active": 73,
1487714940
"context": 15,
1487814941
"deferred_with_rationale": 9,
14879-
"done_verify": 313,
14942+
"done_verify": 316,
1488014943
"open": 285,
1488114944
"rejected_not_claw": 2,
1488214945
"stale_done": 31,

.omx/cc2/board.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
# Claw Code 2.0 Canonical Board
22

3-
Generated from board schema: `2026-05-14T08:13:45+00:00`
3+
Generated from board schema: `2026-05-25T04:30:33+00:00`
44
Schema version: `cc2.board.v1`
55
Ultragoal mutation policy: `.omx/ultragoal` is leader-owned and was not modified by this rendering task.
66

77
## Evidence Freeze
88

99
| Source | Frozen evidence |
1010
| --- | --- |
11-
| Roadmap | `ROADMAP.md` sha256 prefix `2aba3315e52f3079`; 124 headings; 542 ordered actions |
11+
| Roadmap | `ROADMAP.md` sha256 prefix `2aba3315e52f3079`; 127 headings; 542 ordered actions |
1212
| Approved plan | `.omx/plans/claw-code-2-0-adaptive-plan.md` sha256 prefix `e7ef6faf23bfc16b` |
1313
| Research bundle | root `/Users/bellman/Documents/Workspace/claw-code/.omx/research`; latest open issues 30; issue corpus 1000; codex/opencode clone metadata included |
1414

1515
## Roadmap Coverage Summary
1616

1717
| Coverage gate | Mapped | Total | Status |
1818
| --- | --- | --- | --- |
19-
| ROADMAP headings | 124 | 124 | PASS |
19+
| ROADMAP headings | 127 | 127 | PASS |
2020
| ROADMAP ordered actions | 542 | 542 | PASS |
2121
| Duplicate heading lines | 0 | 0 | PASS |
2222

23-
Total canonical board items: **729**
23+
Total canonical board items: **732**
2424

2525
## Lifecycle Enum Reference
2626

@@ -29,7 +29,7 @@ Total canonical board items: **729**
2929
| `active` | 73 | Current Claw Code 2.0 implementation surface that should remain visible on the board. |
3030
| `context` | 15 | Context-only heading or evidence anchor; not an implementation work item. |
3131
| `deferred_with_rationale` | 9 | Intentionally deferred; rationale must be present in the board item. |
32-
| `done_verify` | 313 | Marked as done upstream but retained for verification against current CC2 behavior. |
32+
| `done_verify` | 316 | Marked as done upstream but retained for verification against current CC2 behavior. |
3333
| `open` | 285 | Actionable unresolved work that needs implementation or acceptance evidence. |
3434
| `rejected_not_claw` | 2 | Excluded because it is not Claw Code product work. |
3535
| `stale_done` | 31 | Historically completed or merged work that may be stale and needs freshness checks before relying on it. |
@@ -40,7 +40,7 @@ Total canonical board items: **729**
4040
| Bucket | Count | Meaning |
4141
| --- | --- | --- |
4242
| `2.x_intake` | 30 | Post-2.0 intake or follow-up candidate retained for sequencing. |
43-
| `alpha_blocker` | 240 | Must be resolved before alpha-quality autonomous coding lanes are dependable. |
43+
| `alpha_blocker` | 243 | Must be resolved before alpha-quality autonomous coding lanes are dependable. |
4444
| `beta_adoption` | 417 | Important for broader dogfood/adoption once alpha blockers are controlled. |
4545
| `context` | 15 | Non-actionable roadmap context. |
4646
| `ga_ecosystem` | 22 | Required for mature plugin/MCP/provider ecosystem behavior. |
@@ -54,9 +54,9 @@ Total canonical board items: **729**
5454
| Adoption overlay — user-visible parity and release polish | 357 | 329 | `deferred_with_rationale` 3, `done_verify` 237, `open` 92, `rejected_not_claw` 2, `stale_done` 23 |
5555
| Parity overlay — opencode/codex comparison context | 20 | 16 | `context` 2, `deferred_with_rationale` 1, `done_verify` 5, `open` 11, `stale_done` 1 |
5656
| Stream 0 — Governance, intake, and cross-cutting roadmap triage | 221 | 198 | `active` 6, `context` 13, `deferred_with_rationale` 4, `done_verify` 45, `open` 147, `stale_done` 5, `superseded` 1 |
57-
| Stream 1 — Worker boot and session control | 15 | 14 | `active` 8, `deferred_with_rationale` 1, `open` 6 |
57+
| Stream 1 — Worker boot and session control | 17 | 16 | `active` 8, `deferred_with_rationale` 1, `done_verify` 2, `open` 6 |
5858
| Stream 2 — Event/reporting contracts | 73 | 73 | `active` 45, `done_verify` 20, `open` 8 |
59-
| Stream 3 — Branch/test recovery | 16 | 14 | `active` 6, `done_verify` 1, `open` 7, `stale_done` 2 |
59+
| Stream 3 — Branch/test recovery | 17 | 15 | `active` 6, `done_verify` 2, `open` 7, `stale_done` 2 |
6060
| Stream 4 — Claws-first task execution | 5 | 5 | `active` 4, `done_verify` 1 |
6161
| Stream 5 — Plugin/MCP lifecycle | 22 | 22 | `active` 4, `done_verify` 4, `open` 14 |
6262

@@ -68,7 +68,7 @@ Total canonical board items: **729**
6868
| `latest_open_issue` | 30 |
6969
| `parity_repo_context` | 2 |
7070
| `roadmap_action` | 542 |
71-
| `roadmap_heading` | 124 |
71+
| `roadmap_heading` | 127 |
7272

7373
## Board Items by Stream
7474

@@ -704,6 +704,8 @@ Total canonical board items: **729**
704704
| `CC2-RM-A0363-surface-inconsistency-cluster-of-3-after` | **Surface inconsistency (cluster of 3)**: after #143 Phase 1, the behavior matrix is: | `ROADMAP.md:L5515` / `roadmap_action` | `alpha_blocker` | `open` | `plugin_mcp_lifecycle_contract_test` | `stream_1_worker_boot_session_control` | — |
705705
| `CC2-RM-A0391-remove-the-error-prefix-from-format-unkn` | Remove the "error:" prefix from format_unknown_verb_option (already added by top-level handler) | `ROADMAP.md:L5916` / `roadmap_action` | `alpha_blocker` | `open` | `worker_boot_state_machine_or_cli_json_contract_test` | none | — |
706706
| `CC2-RM-A0512-system-prompt-output-format-json-exposes` | **`system-prompt --output-format json` exposes `"__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__"` as a literal element in the `sections` array — an internal split delimiter leaked into the public structured output** — dogfooded 2026-04-30 by Jobdori on `e939777f`. Running `claw system-prompt --output-format json` returns `{"kind":"system-prompt","message":"<full prose>","sections":["You are an interactive agent...", "# System\n...", "# Doing tasks\n...", "# Executing actions with care\n...", "__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__", "# Environment context\n...", "# Project context\n...", "# Claude instructions\n...", "# Runtime config\n..."]}`. The `sections` array has 9 elements; element index 4 is the raw string `"__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__"`. This internal sentinel marks the boundary between the static and dynamic sections of the compiled system prompt, used during assembly to split the prompt at injection time. It appears in the public JSON output verbatim as a first-class section, indistinguishable from real sections by type alone. Automation that iterates `sections[]` must special-case this sentinel or it will process an internal implementation string as if it were a real system prompt section. **Required fix shape:** (a) strip `"__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__"` and any similar internal delimiters from the `sections` array before serializing to JSON; (b) if the static/dynamic boundary is semantically meaningful for callers, expose it as a structured metadata field such as `boundary_index:4` or as a `section_type:"static"\|"dynamic"` field on each section entry, not as a raw sentinel string in the array; (c) rename the `sections` type from `string[]` to `[{id, type, content}]` to enable this without breaking the boundary signal; (d) add regression coverage proving the `system-prompt --output-format json` output's `sections` array contains no elements whose value equals `"__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__"` or matches `/__[A-Z_]+__/`. **Why this matters:** internal sentinel strings in public JSON are a contract liability — they couple the wire format to internal implementation details. Any refactor that renames or removes the sentinel breaks callers that don't special-case it, and automation that doesn't know to filter it will miscount, misparse, or misrender the system prompt. Source: Jobdori live dogfood, `e939777f`, 2026-04-30. | `ROADMAP.md:L6333` / `roadmap_action` | `beta_adoption` | `open` | `worker_boot_state_machine_or_cli_json_contract_test` | none | — |
707+
| `CC2-RM-H0125-pinpoint-693-claw-analog-bootstrap-plan` | Pinpoint #693. `claw-analog` bootstrap-plan phase parser silently falls back to `"unknown"` — `lib.rs:1114` uses `.unwrap_or("unknown")` for phase field; unrecognized phases emit opaque kind instead of typed error | `ROADMAP.md:L7528` / `roadmap_heading` | `alpha_blocker` | `done_verify` | `targeted_regression_or_acceptance_test_required` | `stream_0_governance` | — |
708+
| `CC2-RM-H0127-pinpoint-695-agent-starts-in-stale-wrong` | Pinpoint #695. Agent starts in stale/wrong worktree and burns a full turn before noticing — no pre-flight check for "file exists on current branch" or "this .git is writable from sandbox" | `ROADMAP.md:L7548` / `roadmap_heading` | `alpha_blocker` | `done_verify` | `worker_boot_state_machine_or_cli_json_contract_test` | `stream_0_governance` | — |
707709

708710
### Stream 2 — Event/reporting contracts
709711

@@ -803,6 +805,7 @@ Total canonical board items: **729**
803805
| `CC2-RM-A0410-remediation-registry-a-function-remediat` | **Remediation registry:** A function `remediation_for(kind: &str, operation: &str) -> Remediation` that maps `(error_kind, operation_context)` pairs to stable remediation structs: | `ROADMAP.md:L6041` / `roadmap_action` | `alpha_blocker` | `open` | `targeted_regression_or_acceptance_test_required` | `stream_2_event_reporting_contracts` | — |
804806
| `CC2-RM-A0411-stable-hint-outputs-per-class-each-error` | **Stable hint outputs per class:** Each `error_kind` maps to exactly one remediation shape. No more prose splitting. | `ROADMAP.md:L6049` / `roadmap_action` | `alpha_blocker` | `open` | `targeted_regression_or_acceptance_test_required` | `stream_2_event_reporting_contracts` | — |
805807
| `CC2-RM-A0412-golden-fixture-tests-test-each-kind-oper` | **Golden fixture tests:** Test each `(kind, operation)` pair against expected remediation output as golden fixtures instead of the current `split_error_hint()` string hacks. | `ROADMAP.md:L6050` / `roadmap_action` | `alpha_blocker` | `open` | `targeted_regression_or_acceptance_test_required` | `stream_2_event_reporting_contracts` | — |
808+
| `CC2-RM-H0126-pinpoint-694-no-pre-push-cargo-build-gat` | Pinpoint #694. No pre-push `cargo build` gate — stale field refs (`retry_after`, `Team` variant, `config_load_error_kind`) broke main build undetected until CI | `ROADMAP.md:L7538` / `roadmap_heading` | `alpha_blocker` | `done_verify` | `git_fixture_or_recovery_recipe_test` | `stream_0_governance` | — |
806809

807810
### Stream 4 — Claws-first task execution
808811

.omx/cc2/render_board_md.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,15 @@
5555

5656

5757
def load_board(path: Path) -> dict[str, Any]:
58-
with path.open() as f:
59-
board = json.load(f)
58+
try:
59+
with path.open() as f:
60+
board = json.load(f)
61+
except FileNotFoundError:
62+
raise ValueError(f"board not found at {path}") from None
63+
except IsADirectoryError:
64+
raise ValueError(f"board path is a directory: {path}") from None
65+
except json.JSONDecodeError as exc:
66+
raise ValueError(f"invalid board JSON at {path}: {exc}") from None
6067
if not isinstance(board, dict):
6168
raise ValueError("board JSON root must be an object")
6269
items = board.get("items")
@@ -226,22 +233,34 @@ def main() -> int:
226233
parser.add_argument("--check", action="store_true", help="fail if board_md is not up to date")
227234
args = parser.parse_args()
228235

229-
board = load_board(args.board_json)
236+
try:
237+
board = load_board(args.board_json)
238+
except ValueError as exc:
239+
print(f"ERROR: {exc}", file=sys.stderr)
240+
return 1
230241
errors = validate_board(board)
231242
if errors:
232243
for error in errors:
233244
print(f"ERROR: {error}", file=sys.stderr)
234245
return 1
235246
rendered = render(board)
236247
if args.check:
237-
existing = args.board_md.read_text() if args.board_md.exists() else ""
248+
try:
249+
existing = args.board_md.read_text() if args.board_md.exists() else ""
250+
except IsADirectoryError:
251+
print(f"ERROR: board markdown path is a directory: {args.board_md}", file=sys.stderr)
252+
return 1
238253
if existing != rendered:
239254
print(f"ERROR: {args.board_md} is not up to date", file=sys.stderr)
240255
return 1
241256
print(f"PASS: {args.board_md} is up to date and roadmap coverage is complete")
242257
return 0
243258
args.board_md.parent.mkdir(parents=True, exist_ok=True)
244-
args.board_md.write_text(rendered)
259+
try:
260+
args.board_md.write_text(rendered)
261+
except IsADirectoryError:
262+
print(f"ERROR: board markdown path is a directory: {args.board_md}", file=sys.stderr)
263+
return 1
245264
print(f"wrote {args.board_md}")
246265
return 0
247266

0 commit comments

Comments
 (0)