feat(meta): extract executor registry, wire executeIntent, ADR-001 amendment (PR-A)#106
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
chittycommand | 747a995 | Jun 04 2026, 01:00 PM |
|
Warning Review limit reached
More reviews will be available in 54 minutes and 45 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (25)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
|
To use Codex here, create a Codex account and connect to github. |
Code review findings (automated)Critical
Important
Suggestions
Confirmed OK
Recommendation: Block on #1 and #5 (cascade-risk bugs for #107/#108). #1 is a correctness lie. #5 will surface as flaky 500s once a second caller exists. |
…icals; importants deferred)
FIX 1 (cascade-risk critical): dispatch's replay short-circuit matched on
intent_id alone, ORDER BY executed_at DESC LIMIT 1. Any intent that ever
produced a terminal cc_actions_log row would short-circuit forever, no
matter what idempotency_key the new attempt computed — making per-attempt
retries unreachable. Reordered to (a) compute attempt+key first, then
(b) lookup by (intent_id, idempotency_key) which is the canonical
per-attempt invariant the partial unique index backs.
FIX 2 (cascade-risk critical): both refusal paths in dispatch wrote audit
+ called failIntent, then returned without `replayed: true`, so
executeIntent's `!result.replayed` guard called failIntent a SECOND time.
The DB no-ops the second call (status guard), but the semantic is wrong
and the error_message could be clobbered on adjacent paths. Both refusal
returns now set replayed:true; executeIntent's guard skips correctly.
Updated existing executor.spec.ts: the second-invocation block encoded
the pre-fix bug (asserted same-intent re-call replays). Under the new
contract, a second executeIntent against the same intent is a new
attempt with a new key → executor re-runs (idempotent for
update-obligation-status), audit count goes 1→2, attempt sequence [1,2].
Added tests/meta/executor-pr106-criticals.spec.ts:
- FIX 1 regression: hand-insert a terminal row with a sentinel key
('a'*64) for an intent, then executeIntent — key mismatch must NOT
short-circuit, executor must run, obligation must transition.
- FIX 2 regression: stale snapshot + unroutable CHITTYTRUST_URL (RFC 5737
192.0.2.1) forces real fetch failure → sovereignty 'blocked' → refusal
path. Asserts result.replayed === true (the canonical FIX 2 signal)
and exactly one sovereignty_refusal audit row.
No mocks. Real Neon only — skipped without DATABASE_URL.
Validated the FIX 1 SELECT shape against a real Neon branch
(cool-bar-13270800 / pr-106-criticals-validation, since deleted): the
key-matched query returned the seeded row for matching key and empty
for non-matching key.
Deferred to follow-up PR (intentionally out of scope here):
- FIX 3: race-safety on concurrent dispatchers (writeAuditRowOrReplay)
- FIX 4: schema predicate gap (status enum vs literal IN-clause)
- FIX 5: cold-start registry import on direct dispatch entry
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
To use Codex here, create a Codex account and connect to github. |
PR #106 — 2 cascade-risk criticals fixed (5cc20f2)Scope intentionally tight: ONLY the 2 criticals. The 3 importants (race-safety, schema-predicate, cold-start registry) are deferred to a follow-up PR so this can land without scope drift cascading into #107/#108. FIX 1 — replay short-circuit by
|
…tch → heartbeat) (#107) Stacked on #106. Replaces the injected-executor abstraction in daemon/loop.ts with a direct call to meta/intent.ts::executeIntent, closing the meta-orchestrator loop. Status transitions, audit-row writes, and the second sovereignty gate are all owned by executeIntent → dispatch; the loop's responsibility is leader lifecycle, intent claiming, heartbeats, and outcome classification. Four outcomes are handled distinctly: - ok=true (executed) → bump processed counter, reset error backoff - ok=true (replayed) → bump replayed counter, no backoff, no double-count - ok=false (refused) → bump refused counter, no backoff (steady-state) - ok=false (exec error) → bump errored counter, bounded exp backoff Sovereignty refusals are identified by canonical error prefixes emitted by meta/executors/dispatch.ts ("sovereignty re-reckon:" / "sovereignty snapshot stale ..."). Refusals are NOT treated as transient faults — they are valid outcomes and do not trigger backoff. The loop honors options.signal via AbortController throughout, including inside the sleep helper, so SIGTERM from daemon/runtime/entrypoint.ts (PR #105) unwinds cleanly through releaseLeadership. tests/daemon/loop.spec.ts — real Neon integration. Seeds two pending intents against the update_obligation_status executor, runs runLeaderLoop with maxIntents=2, asserts: - both intents reach status='done' - each produces exactly one cc_actions_log row (attempt=1, key set, status='completed') - cc_obligations rows actually moved to 'deferred' - cc_node_leases shows leadership released on clean exit - log stream contains intent_heartbeat_before / intent_heartbeat_after pairs Out of scope (not in this PR): - new executors (mercury, etc.) - production deploy - multi-node coordination beyond single-node leader - schema additions on cc_intents / cc_actions_log Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
To use Codex here, create a Codex account and connect to github. |
…l consumer (#109) * feat(daemon): loop body wires executeIntent end-to-end (claim → dispatch → heartbeat) Stacked on #106. Replaces the injected-executor abstraction in daemon/loop.ts with a direct call to meta/intent.ts::executeIntent, closing the meta-orchestrator loop. Status transitions, audit-row writes, and the second sovereignty gate are all owned by executeIntent → dispatch; the loop's responsibility is leader lifecycle, intent claiming, heartbeats, and outcome classification. Four outcomes are handled distinctly: - ok=true (executed) → bump processed counter, reset error backoff - ok=true (replayed) → bump replayed counter, no backoff, no double-count - ok=false (refused) → bump refused counter, no backoff (steady-state) - ok=false (exec error) → bump errored counter, bounded exp backoff Sovereignty refusals are identified by canonical error prefixes emitted by meta/executors/dispatch.ts ("sovereignty re-reckon:" / "sovereignty snapshot stale ..."). Refusals are NOT treated as transient faults — they are valid outcomes and do not trigger backoff. The loop honors options.signal via AbortController throughout, including inside the sleep helper, so SIGTERM from daemon/runtime/entrypoint.ts (PR #105) unwinds cleanly through releaseLeadership. tests/daemon/loop.spec.ts — real Neon integration. Seeds two pending intents against the update_obligation_status executor, runs runLeaderLoop with maxIntents=2, asserts: - both intents reach status='done' - each produces exactly one cc_actions_log row (attempt=1, key set, status='completed') - cc_obligations rows actually moved to 'deferred' - cc_node_leases shows leadership released on clean exit - log stream contains intent_heartbeat_before / intent_heartbeat_after pairs Out of scope (not in this PR): - new executors (mercury, etc.) - production deploy - multi-node coordination beyond single-node leader - schema additions on cc_intents / cc_actions_log Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(health,wrangler): real-dependency /health probe + chittytrack tail consumer The previous /health returned a static {status:"ok",...} regardless of whether the worker could reach its real dependencies — a direct violation of the chittyentity CLAUDE.md "No Mocks, Fake Data, or Placeholder Endpoints" binding rule ("every endpoint must return real results against a real datastore on the day it is committed"). This change replaces /health with a real probe that executes against the worker's actual dependencies: * db — SELECT 1 via Neon HTTP driver. Critical: failure -> 503. * chittyconnect — GET ${CHITTYCONNECT_URL}/health. Degraded if unreachable. * daemon — newest cc_node_leases.heartbeat_at, stale if older than 2x daemon/loop.ts default heartbeatMs (10000ms -> 20000ms cutoff). Missing table -> not_provisioned (degraded, NOT down) so deploys against bases without #101 don't 503. Per-dep timeout 2000ms; total probe bounded ≤ 5000ms via Promise.all. Runs unauthenticated (no auth middleware on /health). The probe handler is extracted to src/routes/health.ts so it can be integration-tested in pure Node — importing src/index.ts directly drags in `cloudflare:` modules (Agents SDK / DOs) that only resolve under workerd. Integration test exercises the handler against a real Neon branch (no mocks), validates DB probe ok and shape of all three probes, and asserts 503 + status=down when DB is unreachable. wrangler.jsonc already declares `tail_consumers: [{service: chittytrack}]` (present on the base branch) — no change required there. Verified against Neon branch br-spring-queen-akggkmso of project cool-bar-13270800 (ChittyCommand). Sample real response: { "status": "degraded", "service": "chittycommand", "version": "0.1.0", "timestamp": "2026-06-04T05:27:16.111Z", "probes": { "db": { "status": "ok", "latency_ms": 226 }, "chittyconnect": { "status": "degraded", "latency_ms": 0, "error": "CHITTYCONNECT_URL not configured" }, "daemon": { "status": "not_provisioned", "newest_heartbeat_age_ms": null, "error": "relation \"cc_node_leases\" does not exist" } } } Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(health): query active leases by heartbeat_at, not released_at Addresses Codex P2 on PR #109. The cc_node_leases schema in src/db/schema.ts has no released_at column — release is represented by NULLing heartbeat_at/lease_expires_at in daemon/leader.ts. The previous WHERE released_at IS NULL clause raised 'column released_at does not exist', which the catch block then mis-classified as 'not_provisioned', so /health would never report ok/stale based on real heartbeats. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: chitcommit <noreply@chitty.cc>
|
|
To use Codex here, create a Codex account and connect to github. |
…rface (#110) * docs(charter,chitty,claude): reclassify Tier 5 → Tier 2 platform with Tier-5 surface; add meta endpoints and dependencies Stacked follow-on to PR #106 (ADR-001 + executor registry). Documentation-only PR that brings the compliance triad and `/api/v1/status` in line with the ADR-001 amendment that landed on `feat/meta-executors-registry`. CHARTER.md / CHITTY.md / CLAUDE.md - Canonical phrasing: "Tier 2 (Platform) with Tier-5 dashboard surface" everywhere a tier is declared. - RY (Authority) row rewritten to reflect sovereignty enforcement + intent execution + multi-source ingest. No longer a pure consumer. - API contract gains the one real new endpoint introduced by #106: POST /api/v1/intents/:id/execute. Per the global no-fake-endpoints rule, the planned intent CRUD (POST /api/v1/intents, GET .../:id, GET ..., GET /api/v1/executors) is NOT documented here because it isn't implemented; it will be added when the routes are. - New Executor Registry table with canonical URI chittycanon://core/services/chittycommand/executors/{intent_type}. Lists the one executor that actually self-registers today (update_obligation_status). mercury_payment is flagged as a tracked future executor with REAL-MONEY constraints (fresh autonomous sovereignty, USD 500 per-intent cap) and explicitly NOT documented as registered. - New Cluster Runtime section: daemon is launchd/systemd, NOT a Worker; per-node L-type ChittyIDs register as sub-channels via agent.chitty.cc/api/v1/channels, NOT in the main ChittyRegister payload. - Dependencies expanded: ChittyTrust, ChittyID, chittyagent-orchestrator, chittyagent-tasks, chittyagent-ch1tty added. ChittyConnect entry expanded to call out ContextConsciousness + MemoryCloude (forever context) and sensitive-intent secret brokerage. - Compliance section flags the ChittyID re-mint as required operator action (T → P-Synthetic) and explicitly defers /health real-probes and tail_consumers wiring to separate PRs. - MCP tool count reconciled to 50 (CLAUDE.md was already correct; CHARTER/ CHITTY updated from stale "48"). src/index.ts - /api/v1/status returns tier: 2 plus tierSurface phrasing and a meta.endpoints array listing the registered intent-execute route. No other route, middleware, or handler touched. src/routes/meta.ts - /api/v1/canon returns tier: 2 + tierSurface so the public canon view matches /status and the docs. Same handler signature; no behavior change. Not in this PR (deferred): - Real-dependency /health probes (separate PR). - tail_consumers wiring to chittytrack (separate observability PR). - ChittyRegister payload submission (operator action; blocked on re-mint). - Re-mint of service ChittyID as P-Synthetic (operator action). - Intent CRUD endpoints and /api/v1/executors enumeration (future PRs). Compliance coverage: - Addresses: tier reclassification, RY language, meta endpoint surface, executor URI registry, dependency expansion, cluster sub-channel declaration (items 1, 4, 5, 7, 8 of the registration-readiness audit). - Remaining (out of scope): registration submission (item 2, operational), real /health (item 3, separate PR), tail_consumers (item 6, separate PR), P-type ChittyID re-mint (item 9, operator action). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(charter): clarify Worker vs daemon runtime split in Classification Addresses Codex P2 on PR #110: the previous wording said the Tier-2 platform and Tier-5 surface 'both run from the same worker', which contradicts the Cluster Runtime section stating daemon/ runs as a supervised launchd/systemd process, not as a Worker. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(registration): draft chittycommand Tier-2 registration payload + submission runbook (#111) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: chitcommit <noreply@chitty.cc>
|
|
To use Codex here, create a Codex account and connect to github. |
…endment
PR-A: foundation for the meta-orchestrator execution layer.
- meta/executors/{types,registry,dispatch,update-obligation-status,index}.ts:
canonical executor registry addressable as
chittycanon://core/services/chittycommand/executors/{intent_type}.
ActionAgent (chat) and the meta-daemon (autonomous) are siblings consuming
the registry; neither dispatches the other.
- meta/intent.ts: new executeIntent(intentId) — atomic single-id claim →
dispatch → status transition. Idempotent on replay via dispatch's audit-row
lookup.
- meta/executors/dispatch.ts: re-reckons sovereignty if the snapshot on the
intent is older than SOVEREIGNTY_FRESHNESS_MS (default 5 min); writes the
cc_actions_log row populated with intent_id, attempt, idempotency_key.
- migrations/0004_chief_skin.sql: additive columns on cc_actions_log
(intent_id uuid FK ON DELETE SET NULL, attempt int default 1,
idempotency_key text) + partial unique index (intent_id, idempotency_key)
WHERE both NOT NULL + index (intent_id, executed_at DESC).
- src/agents/tools/actions.ts: update_obligation_status now delegates to the
registry's pure runner. ActionAgent chat path unchanged behaviorally.
- src/routes/meta.ts: POST /api/v1/intents/:id/execute.
- tests/meta/executor.spec.ts: real-Neon round trip — claim, dispatch,
audit row, replay-is-noop. Skips without DATABASE_URL.
- docs/architecture/ADR-001: Consequences §2 amended per chittycanon and
chittyschema review verdicts.
Reviewer verdicts encoded:
schema-overlord: additive columns on cc_actions_log (no new table).
canon-cardinal: Option 2 (sibling consumers of registry) is canonical.
ecosystem: Intent in meta/intent.ts is already a dispatcher; register
handlers per intent_type, no new ActionSpec abstraction.
Validated on Neon branch br-restless-credit-akyt3mak: migration applied,
columns + indexes confirmed, integration test green (real SQL).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…icals; importants deferred)
FIX 1 (cascade-risk critical): dispatch's replay short-circuit matched on
intent_id alone, ORDER BY executed_at DESC LIMIT 1. Any intent that ever
produced a terminal cc_actions_log row would short-circuit forever, no
matter what idempotency_key the new attempt computed — making per-attempt
retries unreachable. Reordered to (a) compute attempt+key first, then
(b) lookup by (intent_id, idempotency_key) which is the canonical
per-attempt invariant the partial unique index backs.
FIX 2 (cascade-risk critical): both refusal paths in dispatch wrote audit
+ called failIntent, then returned without `replayed: true`, so
executeIntent's `!result.replayed` guard called failIntent a SECOND time.
The DB no-ops the second call (status guard), but the semantic is wrong
and the error_message could be clobbered on adjacent paths. Both refusal
returns now set replayed:true; executeIntent's guard skips correctly.
Updated existing executor.spec.ts: the second-invocation block encoded
the pre-fix bug (asserted same-intent re-call replays). Under the new
contract, a second executeIntent against the same intent is a new
attempt with a new key → executor re-runs (idempotent for
update-obligation-status), audit count goes 1→2, attempt sequence [1,2].
Added tests/meta/executor-pr106-criticals.spec.ts:
- FIX 1 regression: hand-insert a terminal row with a sentinel key
('a'*64) for an intent, then executeIntent — key mismatch must NOT
short-circuit, executor must run, obligation must transition.
- FIX 2 regression: stale snapshot + unroutable CHITTYTRUST_URL (RFC 5737
192.0.2.1) forces real fetch failure → sovereignty 'blocked' → refusal
path. Asserts result.replayed === true (the canonical FIX 2 signal)
and exactly one sovereignty_refusal audit row.
No mocks. Real Neon only — skipped without DATABASE_URL.
Validated the FIX 1 SELECT shape against a real Neon branch
(cool-bar-13270800 / pr-106-criticals-validation, since deleted): the
key-matched query returned the seeded row for matching key and empty
for non-matching key.
Deferred to follow-up PR (intentionally out of scope here):
- FIX 3: race-safety on concurrent dispatchers (writeAuditRowOrReplay)
- FIX 4: schema predicate gap (status enum vs literal IN-clause)
- FIX 5: cold-start registry import on direct dispatch entry
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tch → heartbeat) (#107) Stacked on #106. Replaces the injected-executor abstraction in daemon/loop.ts with a direct call to meta/intent.ts::executeIntent, closing the meta-orchestrator loop. Status transitions, audit-row writes, and the second sovereignty gate are all owned by executeIntent → dispatch; the loop's responsibility is leader lifecycle, intent claiming, heartbeats, and outcome classification. Four outcomes are handled distinctly: - ok=true (executed) → bump processed counter, reset error backoff - ok=true (replayed) → bump replayed counter, no backoff, no double-count - ok=false (refused) → bump refused counter, no backoff (steady-state) - ok=false (exec error) → bump errored counter, bounded exp backoff Sovereignty refusals are identified by canonical error prefixes emitted by meta/executors/dispatch.ts ("sovereignty re-reckon:" / "sovereignty snapshot stale ..."). Refusals are NOT treated as transient faults — they are valid outcomes and do not trigger backoff. The loop honors options.signal via AbortController throughout, including inside the sleep helper, so SIGTERM from daemon/runtime/entrypoint.ts (PR #105) unwinds cleanly through releaseLeadership. tests/daemon/loop.spec.ts — real Neon integration. Seeds two pending intents against the update_obligation_status executor, runs runLeaderLoop with maxIntents=2, asserts: - both intents reach status='done' - each produces exactly one cc_actions_log row (attempt=1, key set, status='completed') - cc_obligations rows actually moved to 'deferred' - cc_node_leases shows leadership released on clean exit - log stream contains intent_heartbeat_before / intent_heartbeat_after pairs Out of scope (not in this PR): - new executors (mercury, etc.) - production deploy - multi-node coordination beyond single-node leader - schema additions on cc_intents / cc_actions_log Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…l consumer (#109) * feat(daemon): loop body wires executeIntent end-to-end (claim → dispatch → heartbeat) Stacked on #106. Replaces the injected-executor abstraction in daemon/loop.ts with a direct call to meta/intent.ts::executeIntent, closing the meta-orchestrator loop. Status transitions, audit-row writes, and the second sovereignty gate are all owned by executeIntent → dispatch; the loop's responsibility is leader lifecycle, intent claiming, heartbeats, and outcome classification. Four outcomes are handled distinctly: - ok=true (executed) → bump processed counter, reset error backoff - ok=true (replayed) → bump replayed counter, no backoff, no double-count - ok=false (refused) → bump refused counter, no backoff (steady-state) - ok=false (exec error) → bump errored counter, bounded exp backoff Sovereignty refusals are identified by canonical error prefixes emitted by meta/executors/dispatch.ts ("sovereignty re-reckon:" / "sovereignty snapshot stale ..."). Refusals are NOT treated as transient faults — they are valid outcomes and do not trigger backoff. The loop honors options.signal via AbortController throughout, including inside the sleep helper, so SIGTERM from daemon/runtime/entrypoint.ts (PR #105) unwinds cleanly through releaseLeadership. tests/daemon/loop.spec.ts — real Neon integration. Seeds two pending intents against the update_obligation_status executor, runs runLeaderLoop with maxIntents=2, asserts: - both intents reach status='done' - each produces exactly one cc_actions_log row (attempt=1, key set, status='completed') - cc_obligations rows actually moved to 'deferred' - cc_node_leases shows leadership released on clean exit - log stream contains intent_heartbeat_before / intent_heartbeat_after pairs Out of scope (not in this PR): - new executors (mercury, etc.) - production deploy - multi-node coordination beyond single-node leader - schema additions on cc_intents / cc_actions_log Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(health,wrangler): real-dependency /health probe + chittytrack tail consumer The previous /health returned a static {status:"ok",...} regardless of whether the worker could reach its real dependencies — a direct violation of the chittyentity CLAUDE.md "No Mocks, Fake Data, or Placeholder Endpoints" binding rule ("every endpoint must return real results against a real datastore on the day it is committed"). This change replaces /health with a real probe that executes against the worker's actual dependencies: * db — SELECT 1 via Neon HTTP driver. Critical: failure -> 503. * chittyconnect — GET ${CHITTYCONNECT_URL}/health. Degraded if unreachable. * daemon — newest cc_node_leases.heartbeat_at, stale if older than 2x daemon/loop.ts default heartbeatMs (10000ms -> 20000ms cutoff). Missing table -> not_provisioned (degraded, NOT down) so deploys against bases without #101 don't 503. Per-dep timeout 2000ms; total probe bounded ≤ 5000ms via Promise.all. Runs unauthenticated (no auth middleware on /health). The probe handler is extracted to src/routes/health.ts so it can be integration-tested in pure Node — importing src/index.ts directly drags in `cloudflare:` modules (Agents SDK / DOs) that only resolve under workerd. Integration test exercises the handler against a real Neon branch (no mocks), validates DB probe ok and shape of all three probes, and asserts 503 + status=down when DB is unreachable. wrangler.jsonc already declares `tail_consumers: [{service: chittytrack}]` (present on the base branch) — no change required there. Verified against Neon branch br-spring-queen-akggkmso of project cool-bar-13270800 (ChittyCommand). Sample real response: { "status": "degraded", "service": "chittycommand", "version": "0.1.0", "timestamp": "2026-06-04T05:27:16.111Z", "probes": { "db": { "status": "ok", "latency_ms": 226 }, "chittyconnect": { "status": "degraded", "latency_ms": 0, "error": "CHITTYCONNECT_URL not configured" }, "daemon": { "status": "not_provisioned", "newest_heartbeat_age_ms": null, "error": "relation \"cc_node_leases\" does not exist" } } } Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(health): query active leases by heartbeat_at, not released_at Addresses Codex P2 on PR #109. The cc_node_leases schema in src/db/schema.ts has no released_at column — release is represented by NULLing heartbeat_at/lease_expires_at in daemon/leader.ts. The previous WHERE released_at IS NULL clause raised 'column released_at does not exist', which the catch block then mis-classified as 'not_provisioned', so /health would never report ok/stale based on real heartbeats. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: chitcommit <noreply@chitty.cc>
…rface (#110) * docs(charter,chitty,claude): reclassify Tier 5 → Tier 2 platform with Tier-5 surface; add meta endpoints and dependencies Stacked follow-on to PR #106 (ADR-001 + executor registry). Documentation-only PR that brings the compliance triad and `/api/v1/status` in line with the ADR-001 amendment that landed on `feat/meta-executors-registry`. CHARTER.md / CHITTY.md / CLAUDE.md - Canonical phrasing: "Tier 2 (Platform) with Tier-5 dashboard surface" everywhere a tier is declared. - RY (Authority) row rewritten to reflect sovereignty enforcement + intent execution + multi-source ingest. No longer a pure consumer. - API contract gains the one real new endpoint introduced by #106: POST /api/v1/intents/:id/execute. Per the global no-fake-endpoints rule, the planned intent CRUD (POST /api/v1/intents, GET .../:id, GET ..., GET /api/v1/executors) is NOT documented here because it isn't implemented; it will be added when the routes are. - New Executor Registry table with canonical URI chittycanon://core/services/chittycommand/executors/{intent_type}. Lists the one executor that actually self-registers today (update_obligation_status). mercury_payment is flagged as a tracked future executor with REAL-MONEY constraints (fresh autonomous sovereignty, USD 500 per-intent cap) and explicitly NOT documented as registered. - New Cluster Runtime section: daemon is launchd/systemd, NOT a Worker; per-node L-type ChittyIDs register as sub-channels via agent.chitty.cc/api/v1/channels, NOT in the main ChittyRegister payload. - Dependencies expanded: ChittyTrust, ChittyID, chittyagent-orchestrator, chittyagent-tasks, chittyagent-ch1tty added. ChittyConnect entry expanded to call out ContextConsciousness + MemoryCloude (forever context) and sensitive-intent secret brokerage. - Compliance section flags the ChittyID re-mint as required operator action (T → P-Synthetic) and explicitly defers /health real-probes and tail_consumers wiring to separate PRs. - MCP tool count reconciled to 50 (CLAUDE.md was already correct; CHARTER/ CHITTY updated from stale "48"). src/index.ts - /api/v1/status returns tier: 2 plus tierSurface phrasing and a meta.endpoints array listing the registered intent-execute route. No other route, middleware, or handler touched. src/routes/meta.ts - /api/v1/canon returns tier: 2 + tierSurface so the public canon view matches /status and the docs. Same handler signature; no behavior change. Not in this PR (deferred): - Real-dependency /health probes (separate PR). - tail_consumers wiring to chittytrack (separate observability PR). - ChittyRegister payload submission (operator action; blocked on re-mint). - Re-mint of service ChittyID as P-Synthetic (operator action). - Intent CRUD endpoints and /api/v1/executors enumeration (future PRs). Compliance coverage: - Addresses: tier reclassification, RY language, meta endpoint surface, executor URI registry, dependency expansion, cluster sub-channel declaration (items 1, 4, 5, 7, 8 of the registration-readiness audit). - Remaining (out of scope): registration submission (item 2, operational), real /health (item 3, separate PR), tail_consumers (item 6, separate PR), P-type ChittyID re-mint (item 9, operator action). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(charter): clarify Worker vs daemon runtime split in Classification Addresses Codex P2 on PR #110: the previous wording said the Tier-2 platform and Tier-5 surface 'both run from the same worker', which contradicts the Cluster Runtime section stating daemon/ runs as a supervised launchd/systemd process, not as a Worker. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(registration): draft chittycommand Tier-2 registration payload + submission runbook (#111) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: chitcommit <noreply@chitty.cc>
…after rebase Resolves the 0004 collision with main's 0004_premium_toad_men (Roux privilege/space). drizzle db:generate regenerated as 0005_sour_dreadnoughts (statement-identical to chief_skin) with a cumulative snapshot, so prod drizzle-kit migrate (no already-exists tolerance) stays clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
747a995 to
fc60bfc
Compare
|
|
To use Codex here, create a Codex account and connect to github. |
…mpotency REAL MONEY PATH. Stacked on #106 (feat/meta-executors-registry). Adds `meta/executors/mercury-payment.ts` — concrete executor for the mercury_payment intent type, plus a shared pure runner that ActionAgent's chat tool (`execute_payment`) now delegates to so chat + autonomous surfaces share one implementation. Refusal gates (executor returns ok=false, dispatcher writes a 'payment_refusal' row to cc_actions_log; Mercury is NOT called): - sovereignty_not_autonomous — decision !== 'autonomous' - sovereignty_stale — snapshot older than MERCURY_SOVEREIGNTY_FRESHNESS_MS (60s, tighter than dispatch's default 5min) - amount_cap_exceeded — payload.amount_cents > MERCURY_AUTONOMOUS_AMOUNT_CAP_USD * 100 - invalid_payload — zod schema rejected the intent payload - missing_token — KV mercury:token:{account_slug} absent - mercury_api_failure — Mercury HTTP returned null Idempotency uses the dispatcher's content-addressable key (sha256(intent.id:attempt:intent_type)) as supplied via ctx.idempotencyKey. Because intent.id is immutable and attempt is deterministic from prior audit rows, this is functionally equivalent to a payload-derived key for replay protection. The Mercury client receives the same key as its own idempotencyKey so Mercury de-dupes on it too. Files: - meta/executors/mercury-payment.ts (new) - meta/executors/index.ts (barrel: side-effect import) - src/agents/tools/actions.ts (execute_payment delegates to runMercuryPayment) - src/index.ts (Env: MERCURY_AUTONOMOUS_AMOUNT_CAP_USD) - tests/meta/executors/mercury-payment.spec.ts (3 DB-only refusal cases) - docs/runbooks/mercury-payment-executor.md (operator runbook) Does NOT modify meta/executors/{dispatch,registry,types}.ts from #106. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… build Replaying #105 onto current main (executor registry from #106) broke the daemon build two ways. Fix both so #105 ships a daemon that builds on the VM. 1. entrypoint.ts passed an `executor` callback to runLeaderLoop — removed in #106 when the loop began dispatching through the canonical executor registry (executeIntent). Drop the stub: an empty registry routes every claimed intent through dispatch's "no executor registered" throw → failIntent → `failed`, never silent `done`, preserving the PR #105 Codex-P1 safety property without a callback. 2. The executor registry (meta/executors/{types,dispatch,update-obligation- status}.ts) hard-imported the Workers `Env` from src/index, neither available nor compilable in the daemon's NodeNext + node-types build. Per ADR-001 the registry is consumed by BOTH the Worker and the daemon, so it must not depend on Workers-only types. Introduce a minimal structural `ExecutorEnv { DATABASE_URL?, HYPERDRIVE? }` (the only env the registry reads; getSql already cast to exactly this). Worker `Env` stays structurally assignable — ActionAgent callers unchanged. No index signature: keeps typo-safety on env reads for the real-money mercury path. Also add the explicit `/index.js` extension to meta/intent.ts's dynamic `import('./executors')` (required under NodeNext; accepted by the Worker's Bundler resolution). Verified: `npm run typecheck` (Worker, Bundler) and `npm run build:daemon` (NodeNext) both exit 0. Follow-up (needs `workflow` scope, separate push): add `tsc -p daemon/runtime/tsconfig.daemon.json --noEmit` as a CI step so the daemon build is gated — catches the #108 ripple (mercury also imports Workers `Env`) at PR time instead of VM install. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Context
Builds on merged foundation PRs #101 (
meta/,daemon/, intent ladder, sovereignty gate) and #103 (Codex P2 fixes). Implements the executor extraction called for by the ADR-001 follow-up review.ADR-001 (
docs/architecture/ADR-001-meta-orchestrator-extension.md) was merged in #101; this PR amends its Consequences §2 to record the executor-registry decision.Reviewer verdicts (the spec this PR implements)
intent_executionstable — three additive columns oncc_actions_log(intent_id,attempt,idempotency_key) plus a partial unique index and a(intent_id, executed_at DESC)index.meta/intent.tsis already a meta-dispatcher — register handlers perintentType, no new ActionSpec abstraction.What's in this PR
docs/architecture/ADR-001-meta-orchestrator-extension.md— Consequences §2 replaced verbatim per the chittycanon-code-cardinal paragraph; added## ADR-001 amendments (chronological)with 2026-06-04 entry.meta/executors/— new directory:types.ts—ExecutorContext,ExecutorResult,IntentExecutor,SOVEREIGNTY_FRESHNESS_MS(5 min default).registry.ts—registerExecutor,getExecutor,listExecutors; duplicate registration is an error.dispatch.ts— single entry point: replay short-circuit (terminal prior audit row), attempt + idempotency key derivation, sovereignty re-reckon if snapshot stale (the second of the two gate call points), executor invocation, audit row write.update-obligation-status.ts— first concrete executor; exports a purerunUpdateObligationStatus(args, sql)runner + a registeredIntentExecutor.index.ts— barrel that side-effect-imports the executor module so registration runs.meta/intent.ts— addedexecuteIntent(env, intentId, options). Existing exports unchanged.src/agents/tools/actions.ts—update_obligation_statustool now delegates torunUpdateObligationStatus(shared with the executor); chat path behavior unchanged.execute_payment/send_dispute_email/list_mercury_recipients/get_action_logleft untouched.src/routes/meta.ts— addedPOST /api/v1/intents/:id/executeusing the samemetaRoutesauth surface as/whoami.migrations/0004_chief_skin.sql(drizzle-generated) — adds three columns + two indexes oncc_actions_log. Drizzle correctly preserved theWHERE intent_id IS NOT NULL AND idempotency_key IS NOT NULLclause on the partial unique index.tests/meta/executor.spec.ts— real-Neon integration test. Skips on missingDATABASE_URL. Inserts a realcc_obligationsrow, creates Goal + Plan + Intent (intent_type='update_obligation_status'), runsexecuteIntenttwice. Asserts: intent → done; exactly onecc_actions_logrow withintent_idset,attempt=1,idempotency_keynon-null; second call replays (no new row).Real-SQL evidence (Neon branch
br-restless-credit-akyt3makon projectcool-bar-13270800)After applying the migration:
The partial
WHEREclause surviveddrizzle-kit generateand Postgres accepted it.Sample execution trace (vitest run against
br-restless-credit-akyt3mak)Per-step behavior the test verifies:
createIntent->status='pending'(sovereignty pre-seeded autonomous so dispatch does not re-reckon).executeIntent->ok=true,replayed=false, sha256 idempotency key,actionLogIdset;cc_intents.status='done';cc_obligations.status='deferred'; one row incc_actions_logwithattempt=1,intent_id=<intent.id>,idempotency_key=<sha256>,action_type='status_change',status='completed'.executeIntent->ok=true,replayed=true, same idempotency key andactionLogId; still exactly one row incc_actions_log.Process
npm run typecheck: clean.SKIP_INTEGRATION=1 npm test: 15 passed, 12 skipped (no regressions; preexisting skipped specs unchanged).What is NOT in this PR (deferred)
src/agents/tools/actions.tsfor now.send_dispute_emailqueue/send flow).daemon/loop.tscallingexecuteIntent(the daemon still uses its own executor callback signature; rewiring is a follow-up).Generated with Claude Code (https://claude.com/claude-code)