diff --git a/Tools/card_activation.py b/Tools/card_activation.py index 3b8aac6..fed1bb0 100644 --- a/Tools/card_activation.py +++ b/Tools/card_activation.py @@ -31,15 +31,71 @@ # manifest at admission, delivers one file per tool result inside a protocol # byte budget, and leaves `machine-delivery-complete` to be earned by the # Assignment delivery gate rather than asserted here. -ACTIVATION_PROTOCOL = "card-first-readback-v3" +# v4 keeps every v3 commitment and moves one thing: *when* a frozen piece +# travels. v3 owed the whole task's route union before `running`, so a +# single-page corrective batch paid for the governance route it never +# entered. v4 freezes the same identities at the same moment -- plus the +# phase each belongs to and the environment they were resolved under -- and +# delivers one phase at a time, each phase gate still an exact set equality. +ACTIVATION_PROTOCOL = "card-first-phased-readback-v4" +V3_ACTIVATION_PROTOCOL = "card-first-readback-v3" V2_ACTIVATION_PROTOCOL = "card-first-readback-v2" LEGACY_ACTIVATION_PROTOCOL = "card-first-readback-v1" SUPPORTED_ACTIVATION_PROTOCOLS = frozenset(( - LEGACY_ACTIVATION_PROTOCOL, V2_ACTIVATION_PROTOCOL, ACTIVATION_PROTOCOL)) + LEGACY_ACTIVATION_PROTOCOL, V2_ACTIVATION_PROTOCOL, + V3_ACTIVATION_PROTOCOL, ACTIVATION_PROTOCOL)) EMBEDDED_PAYLOAD_PROTOCOLS = frozenset(( LEGACY_ACTIVATION_PROTOCOL, V2_ACTIVATION_PROTOCOL)) +# Protocols that carry a frozen piece manifest and deliver it afterwards. +PIECE_DELIVERY_PROTOCOLS = frozenset(( + V3_ACTIVATION_PROTOCOL, ACTIVATION_PROTOCOL)) +# Protocols that additionally partition that manifest into phases. +PHASED_PROTOCOLS = frozenset((ACTIVATION_PROTOCOL,)) PIECE_PROTOCOL = "activation-piece-v1" PIECE_ACK_PROTOCOL = "activation-piece-ack-v1" +PHASE_PLAN_PROTOCOL = "phase-plan-v1" +PHASE_DELIVERY_PROTOCOL = "activation-phase-v1" +PHASE_ACK_PROTOCOL = "activation-phase-ack-v1" +# The resolver identity travels in the frozen environment: a later phase is +# materialized by whatever build is running then, so replay needs to know +# which rule set produced the plan it is replaying. +PHASE_RESOLVER_VERSION = "phase-resolver-1.0.0" + +# Phase closed set. Two layers: three batch phases every batch walks, and +# two task-level conditional phases only a real transition enters. +PHASE_BATCH_PREFLIGHT = "batch-preflight" +PHASE_BATCH_RUNNING = "batch-running" +PHASE_BATCH_GATE = "batch-gate" +PHASE_GOVERNANCE = "governance" +PHASE_TASK_COMPLETION = "task-completion" +PHASE_ORDER = ( + PHASE_BATCH_PREFLIGHT, PHASE_BATCH_RUNNING, PHASE_BATCH_GATE, + PHASE_GOVERNANCE, PHASE_TASK_COMPLETION, +) +PHASES = frozenset(PHASE_ORDER) +# A conditional phase is materialized only when its predicate holds; its +# pieces are frozen at admission either way, so entering one later proves +# what it always would have been rather than resolving it afresh. +CONDITIONAL_PHASES = frozenset((PHASE_GOVERNANCE, PHASE_TASK_COMPLETION)) +# A standard phase must fit one part. Needing two is not a transport +# accident to route around; it means the phase set was cut too wide. +STANDARD_PHASES = frozenset((PHASE_BATCH_PREFLIGHT, PHASE_BATCH_GATE)) +PHASE_TRIGGERS = { + PHASE_BATCH_PREFLIGHT: "batch admitted (queued -> open)", + PHASE_BATCH_RUNNING: "route or read-back condition declared during work", + PHASE_BATCH_GATE: "first judgment or merge-ready request", + PHASE_GOVERNANCE: "in-batch Standards governance transition", + PHASE_TASK_COMPLETION: "completion-candidate task transition", +} +# Routes whose phase is fixed by what the route is for, not by the batch. +# R01 is every task's common boundary; the other three are the routes their +# own Cards say ordinary work must not enter implicitly. +ROUTE_PHASE_OVERRIDES = { + "R01": PHASE_BATCH_PREFLIGHT, + "R08": PHASE_TASK_COMPLETION, + "R09": PHASE_GOVERNANCE, + "R12": PHASE_BATCH_GATE, +} # One delivered piece must fit one tool result. The measured object is the # canonical serialization of the whole delivery, not the source file: the # 2026-08-22 host measurement saw 50,495 bytes of Card source arrive as a @@ -66,7 +122,15 @@ "activation_bundle_manifest", "delivery_mode", "delivery_assurance", "execution_context_id", ) +PHASED_ACTIVATION_CONTEXT_FIELDS = ( + "activation_protocol", "task_contract_sha256", "reading_plan_sha256", + "readback_plan_sha256", "review_requirement_set_sha256", + "phase_plan_sha256", "card_bundle_sha256", + "activation_bundle_manifest", "delivery_mode", "delivery_assurance", + "execution_context_id", +) ACTIVATION_BUNDLE_FIELDS = ACTIVATION_CONTEXT_FIELDS[:7] +PHASED_ACTIVATION_BUNDLE_FIELDS = PHASED_ACTIVATION_CONTEXT_FIELDS[:8] def activation_context_fields(context_or_protocol): @@ -76,7 +140,19 @@ def activation_context_fields(context_or_protocol): protocol = context_or_protocol.get("activation_protocol") if protocol == LEGACY_ACTIVATION_PROTOCOL: return LEGACY_ACTIVATION_CONTEXT_FIELDS + if protocol in PHASED_PROTOCOLS: + return PHASED_ACTIVATION_CONTEXT_FIELDS return ACTIVATION_CONTEXT_FIELDS + + +def activation_bundle_fields(context_or_protocol): + """Return the delivery-independent commitment fields for one era.""" + protocol = context_or_protocol + if isinstance(context_or_protocol, dict): + protocol = context_or_protocol.get("activation_protocol") + if protocol in PHASED_PROTOCOLS: + return PHASED_ACTIVATION_BUNDLE_FIELDS + return ACTIVATION_BUNDLE_FIELDS RUNTIME_STATE_BINDING_FIELDS = ( "required_queue_sha256", "coverage_ledger_sha256", "progress_ledger_sha256", "queue_revision", "queue_state_revision", @@ -329,17 +405,92 @@ def _piece_envelope_bytes(piece): return len(kblib.canonical_json_bytes(piece)) -def _piece_records(cards, startup): +def work_spec_route_narrowing(root, item): + """Return the routes one batch's Work Spec declares it actually needs. + + A batch that says nothing keeps the whole non-conditional route set: an + absent declaration is silence, never a claim that fewer routes suffice. + Declaring the field is how a batch buys a smaller startup, and the + declaration is itself frozen -- the Work Spec hash is already bound by + the Queue, so narrowing cannot drift underneath the plan. + """ + if not isinstance(item, dict): + return None + relative = item.get("work_spec_path") + expected_sha = item.get("work_spec_sha256") + if not isinstance(relative, str) or not relative: + return None + snapshot = kblib.repository_target_snapshot( + root, relative, suffixes=(".yaml",)) + if not snapshot.exists: + raise ActivationError("work spec %s is missing" % relative) + if isinstance(expected_sha, str) and expected_sha and \ + snapshot.sha256 != expected_sha: + raise ActivationError( + "work spec %s drifted from the Queue binding" % relative) + try: + document = kblib.parse_yaml_subset(snapshot.read_text()) + except (OSError, UnicodeError, ValueError) as exc: + raise ActivationError("work spec %s is unreadable: %s" % + (relative, exc)) + if not isinstance(document, dict): + raise ActivationError("work spec %s must be a mapping" % relative) + declared = document.get("required_route_ids") + if declared is None: + return None + routes = _strings(declared, "%s required_route_ids" % relative) + if not routes: + raise ActivationError( + "%s declares an empty required_route_ids; omit the field instead " + "of claiming a batch needs no work route" % relative) + return sorted(set(routes)) + + +def resolve_route_phases(routes, *, narrowing=None): + """Assign every selected route to exactly one phase. + + Three routes carry their own phase because their Cards already say so: + R09 and R08 are entered by a governance or completion transition, R12 by + a targeted-audit predicate. R01 is the common boundary every phase + presumes. Everything else is work: it starts in preflight unless the + batch narrowed itself, and a narrowed-away route stays available on + demand during `batch-running` rather than disappearing. + """ + narrowed = narrowing is not None + keep = set(narrowing or ()) + assignment = {} + for route_id in routes: + override = ROUTE_PHASE_OVERRIDES.get(route_id) + if override is not None: + assignment[route_id] = override + continue + if narrowed and route_id not in keep: + assignment[route_id] = PHASE_BATCH_RUNNING + else: + assignment[route_id] = PHASE_BATCH_PREFLIGHT + return assignment + + +def _piece_records(cards, startup, phase_of=None): """Freeze one addressable record per deliverable file. A piece is always a whole file. Splitting one file across results would break the only verification the receiving end can perform: the frozen SHA binds the complete file, a model cannot rehash fragments, and no party could then prove a reassembly was faithful. + + Under a phased protocol each record also carries the phase that will + deliver it, decided here at admission so no later reader has to re-derive + it from the route table. """ + def _phase(route_id, default=PHASE_BATCH_PREFLIGHT): + if phase_of is None: + return None + return phase_of.get(route_id, default) + pieces = [] for card in cards: - pieces.append({ + record = { "piece_id": "card:%s" % card["route_id"], "kind": "card", "path": card["path"], @@ -352,9 +503,13 @@ def _piece_records(cards, startup): "compiled_source_hash": card["compiled_source_hash"], "readback_policy": card["readback_policy"], "readback_sources": list(card["readback_sources"]), - }) + } + phase = _phase(card["route_id"]) + if phase is not None: + record["phase"] = phase + pieces.append(record) for row in startup: - pieces.append({ + record = { "piece_id": "readback:%s" % row["rule_id"], "kind": "activation-readback", "path": row["path"], @@ -362,7 +517,13 @@ def _piece_records(cards, startup): "bytes": len(row["content"].encode("utf-8")), "route_id": row["route_id"], "rule_id": row["rule_id"], - }) + } + # A read-back travels with the Card that declared it; the Card Index + # belongs to no route, so it waits for the dispute that needs it. + phase = _phase(row["route_id"], PHASE_BATCH_RUNNING) + if phase is not None: + record["phase"] = phase + pieces.append(record) pieces.sort(key=lambda row: row["piece_id"]) identifiers = [row["piece_id"] for row in pieces] if len(identifiers) != len(set(identifiers)): @@ -565,7 +726,20 @@ def build_activation_context(root, progress, item, *, runtime_state, kblib.canonical_json_bytes(readback_plan)) review_records = expand_batch_review_requirements(profile_contract, item) review_set_sha = review_requirement_set_sha256(review_records) - pieces = _piece_records(cards, startup) + narrowing = work_spec_route_narrowing(root, item) + if narrowing is not None: + unknown_narrowed = sorted(set(narrowing) - set(routes)) + if unknown_narrowed: + raise ActivationError( + "work spec narrows to route(s) the contract did not select: " + "%s" % ", ".join(unknown_narrowed)) + phase_of = resolve_route_phases(routes, narrowing=narrowing) + for route_id in sorted(profile_routes): + phase_of.setdefault( + route_id, + PHASE_BATCH_RUNNING if narrowing is not None + else PHASE_BATCH_PREFLIGHT) + pieces = _piece_records(cards, startup, phase_of) manifest = { "activation_protocol": ACTIVATION_PROTOCOL, "task_id": progress.get("task_id"), @@ -589,26 +763,39 @@ def build_activation_context(root, progress, item, *, runtime_state, "requirements": review_records, }, } - # Fail closed at admission rather than at delivery: a manifest that - # cannot be delivered inside the budget is a governance problem for the - # oversized leaf, not a transport accident to discover mid-batch. - oversized = [] - # The stand-ins are length-exact: the real delivery carries a 71-character - # bundle hash, a 32-character nonce and a 32-character attempt id, so - # measuring with None here would under-report the envelope and let a piece - # on the boundary pass admission and fail delivery. - sha_placeholder = "sha256:" + ("0" * 64) - for record, text in zip(pieces, _piece_texts(cards, startup, pieces)): - envelope = _piece_envelope_bytes( - _piece_delivery_payload(manifest, record, text, nonce="0" * 32, - delivery_attempt_id="0" * 32, - card_bundle_sha256=sha_placeholder)) - if envelope > MAX_ACTIVATION_PIECE_ENVELOPE_BYTES: - oversized.append("%s (%d bytes)" % (record["piece_id"], envelope)) - if oversized: - raise ActivationError( - "activation piece(s) exceed the %d-byte delivery budget: %s" % - (MAX_ACTIVATION_PIECE_ENVELOPE_BYTES, ", ".join(oversized))) + # Freeze what resolved this plan next to the plan itself. A later phase + # is materialized by a later run, so replay has to be able to see the + # Standards, Profile, resolver and Work Spec the membership was computed + # under -- otherwise "the same phase" silently means two things. + environment = { + "standards_version": contract.get("standards_version"), + "selected_profile_manifest": contract.get( + "selected_profile_manifest"), + "profile_snapshot_sha256": runtime_bindings.get( + "profile_snapshot_sha256"), + "profile_contract_fingerprint": runtime_bindings.get( + "profile_contract_fingerprint"), + "profile_load_inputs_sha256": runtime_bindings.get( + "profile_load_inputs_sha256"), + "resolver_version": PHASE_RESOLVER_VERSION, + "card_index_sha256": registry_sha, + "task_contract_sha256": contract_sha, + "work_spec_path": item.get("work_spec_path"), + "work_spec_sha256": item.get("work_spec_sha256"), + } + # Packing measures the real serialization, so it also performs v3's + # fail-closed budget check: an oversized leaf raises here, at its own + # admission boundary, instead of surfacing as a transport accident. + texts_by_id = dict(zip( + [row["piece_id"] for row in pieces], + _piece_texts(cards, startup, pieces))) + phase_plan = _build_phase_plan(manifest, pieces, texts_by_id, phase_of, + environment=environment, + narrowing=narrowing) + phase_plan_sha = kblib.sha256_bytes( + kblib.canonical_json_bytes(phase_plan)) + manifest["phase_plan"] = phase_plan + manifest["phase_plan_sha256"] = phase_plan_sha bundle_sha = kblib.sha256_bytes(kblib.canonical_json_bytes(manifest)) return { "activation_protocol": ACTIVATION_PROTOCOL, @@ -616,6 +803,7 @@ def build_activation_context(root, progress, item, *, runtime_state, "reading_plan_sha256": reading_plan_sha, "readback_plan_sha256": readback_plan_sha, "review_requirement_set_sha256": review_set_sha, + "phase_plan_sha256": phase_plan_sha, "card_bundle_sha256": bundle_sha, "activation_bundle_manifest": manifest, **_delivery_binding(execution_context_id, @@ -660,6 +848,181 @@ def _piece_delivery_payload(manifest, record, text, *, nonce, } +def _phase_delivery_payload(manifest, phase_id, part_index, part_count, + records, texts, *, nonce, delivery_attempt_id, + card_bundle_sha256=None, phase_plan_sha256=None): + """Assemble one phase part exactly as the host will receive it. + + The structure is v3's single-piece delivery with one field widened: the + part carries a list of whole files instead of one, and the nonce still + sits last. The proof is therefore the same proof -- the nonce shows the + part reached this context, the conformant Adapter shows a within-budget + result is not truncated, and each file keeps its own frozen SHA so the + grouping never becomes a way to smuggle an unverified body. + """ + return { + "phase_protocol": PHASE_DELIVERY_PROTOCOL, + "card_bundle_sha256": card_bundle_sha256, + "phase_plan_sha256": phase_plan_sha256, + "batch_id": manifest.get("batch_id"), + "task_id": manifest.get("task_id"), + "phase_id": phase_id, + "part_index": part_index, + "part_count": part_count, + "delivery_attempt_id": delivery_attempt_id, + "pieces": [ + { + "piece_id": record["piece_id"], + "kind": record["kind"], + "path": record["path"], + "sha256": record["sha256"], + "bytes": record["bytes"], + "content": text, + } + for record, text in zip(records, texts) + ], + "delivery_nonce": nonce, + } + + +def _pack_phase_parts(manifest, phase_id, records, texts_by_id): + """Greedily pack one phase into the fewest budgeted parts. + + Packing happens at admission, with length-exact placeholders, so the + part boundaries are frozen with everything else: two contexts delivering + the same phase deliver the same parts, and a phase whose standard form + needs more than one part is visible as a plan defect before any work + starts rather than as a delivery surprise. + """ + placeholder_sha = "sha256:" + ("0" * 64) + + def _measure(rows): + return _piece_envelope_bytes(_phase_delivery_payload( + manifest, phase_id, 0, 1, rows, + [texts_by_id[row["piece_id"]] for row in rows], + nonce="0" * 32, delivery_attempt_id="0" * 32, + card_bundle_sha256=placeholder_sha, + phase_plan_sha256=placeholder_sha)) + + # Two separable judgements, in this order. First: can each file be + # delivered at all? A piece is never split across parts, so a file that + # cannot fit a part alone can never be delivered -- that is the oversized + # leaf's own governance problem and it fails closed here, exactly as it + # did in v3. Deciding this before packing is what keeps an undeliverable + # leaf from being reported later as a phase that was merely cut too wide. + oversized = [] + for record in records: + envelope = _measure([record]) + if envelope > MAX_ACTIVATION_PIECE_ENVELOPE_BYTES: + oversized.append("%s (%d bytes)" % (record["piece_id"], envelope)) + if oversized: + raise ActivationError( + "activation piece(s) exceed the %d-byte delivery budget: %s" % + (MAX_ACTIVATION_PIECE_ENVELOPE_BYTES, ", ".join(oversized))) + + # Second: pack the deliverable files into as few parts as the budget + # allows. Every singleton is now known to fit, so a part is never empty + # and the loop always makes progress. + parts = [] + current = [] + for record in records: + if current and _measure(current + [record]) > \ + MAX_ACTIVATION_PIECE_ENVELOPE_BYTES: + parts.append(current) + current = [record] + else: + current = current + [record] + if current: + parts.append(current) + return [ + { + "part_index": index, + "piece_ids": [row["piece_id"] for row in rows], + "envelope_bytes": _measure(rows), + } + for index, rows in enumerate(parts) + ] + + +def _build_phase_plan(manifest, pieces, texts_by_id, phase_of, *, + environment, narrowing): + """Freeze the phase closed set, its membership, and what resolved it.""" + by_phase = {phase_id: [] for phase_id in PHASE_ORDER} + for record in pieces: + phase_id = record.get("phase") + if phase_id not in by_phase: + raise ActivationError( + "activation piece %s carries an unregistered phase %r" % + (record.get("piece_id"), phase_id)) + by_phase[phase_id].append(record) + phases = [] + for phase_id in PHASE_ORDER: + records = by_phase[phase_id] + parts = _pack_phase_parts(manifest, phase_id, records, texts_by_id) + route_ids = sorted({row["route_id"] for row in records + if isinstance(row.get("route_id"), str)}) + if phase_id in STANDARD_PHASES and len(parts) > 1: + raise ActivationError( + "standard phase %s needs %d parts; a standard phase that does " + "not fit one delivery was cut too wide" % + (phase_id, len(parts))) + phases.append({ + "phase_id": phase_id, + "conditional": phase_id in CONDITIONAL_PHASES, + "standard": phase_id in STANDARD_PHASES, + "trigger": PHASE_TRIGGERS[phase_id], + "route_ids": route_ids, + "piece_ids": [row["piece_id"] for row in records], + "piece_count": len(records), + "parts": parts, + "part_count": len(parts), + }) + return { + "protocol": PHASE_PLAN_PROTOCOL, + "phases": phases, + "route_phases": dict(sorted(phase_of.items())), + "work_route_ids": list(narrowing) if narrowing is not None else None, + "narrowed_by_work_spec": narrowing is not None, + "environment": environment, + } + + +def phase_record(activation_context, phase_id): + """Return one frozen phase record, or None when the era has no plan.""" + manifest = (activation_context or {}).get("activation_bundle_manifest") + plan = (manifest or {}).get("phase_plan") + if not isinstance(plan, dict): + return None + for row in plan.get("phases") or []: + if isinstance(row, dict) and row.get("phase_id") == phase_id: + return row + return None + + +def phase_piece_ids(activation_context, phase_id): + """Return the exact piece identity set one phase must deliver.""" + record = phase_record(activation_context, phase_id) + if record is None: + return [] + return sorted( + piece_id for piece_id in record.get("piece_ids") or [] + if isinstance(piece_id, str)) + + +def expected_delivery_attempt_id(card_bundle_sha256, execution_context_id): + """Derive the one attempt id a given bundle and context can produce. + + This is the authoritative pointer, and it needs no stored field: an ack + chain belongs to the current attempt exactly when its recorded id equals + the value this function derives from the current activation's bundle and + the acting context. A complete chain from a superseded bundle or from + somebody else's context therefore fails the same equality, which is what + stops a stale-but-self-consistent chain from being reused. + """ + return kblib.sha256_bytes(kblib.canonical_json_bytes([ + card_bundle_sha256, execution_context_id]))[7:39] + + def activation_context_errors(context): """Validate the self-contained shape and byte commitments of a context.""" errors = [] @@ -716,6 +1079,11 @@ def activation_context_errors(context): errors.append( "review_requirement_set_sha256 does not bind the " "frozen requirement expansion") + if protocol in PHASED_PROTOCOLS: + errors.extend(_phase_plan_errors(context, manifest)) + elif "phase_plan_sha256" in context or "phase_plan" in manifest: + errors.append( + "a %s activation must not carry a phase plan" % protocol) expected_bundle_sha = kblib.sha256_bytes( kblib.canonical_json_bytes(manifest)) if context.get("card_bundle_sha256") != expected_bundle_sha: @@ -736,17 +1104,22 @@ def activation_context_errors(context): elif manifest.get("readback_plan_sha256") != kblib.sha256_bytes( kblib.canonical_json_bytes(plan)): errors.append("readback_plan_sha256 does not bind readback_plan") - if protocol == ACTIVATION_PROTOCOL: + # The question here is which era's shape the bundle has, not whether it + # is the newest protocol: v3 and v4 both freeze a piece manifest and + # embed nothing, so testing against the current constant would silently + # re-file every sealed v3 receipt under the embedded-payload rules the + # moment a v4 lands. + if protocol in PIECE_DELIVERY_PROTOCOLS: errors.extend(_piece_manifest_errors(manifest)) for field in ("cards", "startup_readbacks"): if field in manifest: errors.append( "a %s bundle must not embed %s; content travels as " - "budgeted pieces" % (ACTIVATION_PROTOCOL, field)) + "budgeted pieces" % (protocol, field)) if "activation_delivery_payload" in context: errors.append( "a %s admission must not carry an embedded delivery payload" % - ACTIVATION_PROTOCOL) + protocol) else: cards = manifest.get("cards") if not isinstance(cards, list) or not cards: @@ -797,7 +1170,7 @@ def activation_context_errors(context): assurance = context.get("delivery_assurance") mode = context.get("delivery_mode") context_id = context.get("execution_context_id") - if protocol == ACTIVATION_PROTOCOL: + if protocol in PIECE_DELIVERY_PROTOCOLS: if assurance == "host-bound": if mode != "host-context-injection" or not isinstance( context_id, str) or not context_id: @@ -810,8 +1183,7 @@ def activation_context_errors(context): else: errors.append( "a %s admission records host-bound or prepared; delivery " - "completion is earned by the Assignment delivery gate" % - ACTIVATION_PROTOCOL) + "completion is earned by the phase delivery gate" % protocol) elif assurance == "machine-delivered": if mode != "host-context-injection" or not isinstance( context_id, str) or not context_id: @@ -824,9 +1196,96 @@ def activation_context_errors(context): return errors +def _phase_plan_errors(context, manifest): + """Validate that a phased bundle freezes a complete, exact phase plan.""" + errors = [] + plan = manifest.get("phase_plan") + plan_sha = context.get("phase_plan_sha256") + if not isinstance(plan, dict): + return ["activation bundle must freeze a phase_plan"] + if plan.get("protocol") != PHASE_PLAN_PROTOCOL: + errors.append("phase_plan protocol is invalid") + recomputed = kblib.sha256_bytes(kblib.canonical_json_bytes(plan)) + if not isinstance(plan_sha, str) or not SHA256_RE.fullmatch( + plan_sha or ""): + errors.append("phase_plan_sha256 must be a sha256 value") + elif plan_sha != recomputed or manifest.get( + "phase_plan_sha256") != recomputed: + errors.append("phase_plan_sha256 does not bind the frozen phase plan") + environment = plan.get("environment") + if not isinstance(environment, dict): + errors.append("phase_plan must freeze its resolving environment") + else: + for field in ("standards_version", "selected_profile_manifest", + "profile_snapshot_sha256", + "profile_contract_fingerprint", "resolver_version", + "card_index_sha256", "task_contract_sha256"): + if not isinstance(environment.get(field), str) or not \ + environment.get(field): + errors.append( + "phase_plan environment lacks %s" % field) + phases = plan.get("phases") + if not isinstance(phases, list) or [ + row.get("phase_id") if isinstance(row, dict) else None + for row in phases] != list(PHASE_ORDER): + return errors + [ + "phase_plan must carry the closed phase set in canonical order"] + planned = [] + for row in phases: + phase_id = row.get("phase_id") + piece_ids = row.get("piece_ids") + if not isinstance(piece_ids, list): + errors.append("phase %s has no piece list" % phase_id) + continue + planned.extend(piece_ids) + if row.get("piece_count") != len(piece_ids): + errors.append("phase %s piece_count is inconsistent" % phase_id) + if row.get("conditional") is not (phase_id in CONDITIONAL_PHASES): + errors.append("phase %s misdeclares its conditionality" % phase_id) + parts = row.get("parts") + if not isinstance(parts, list) or row.get("part_count") != len(parts): + errors.append("phase %s part_count is inconsistent" % phase_id) + continue + if phase_id in STANDARD_PHASES and len(parts) > 1: + errors.append( + "standard phase %s is split across %d parts" % + (phase_id, len(parts))) + packed = [] + for index, part in enumerate(parts): + if not isinstance(part, dict) or part.get("part_index") != index: + errors.append("phase %s part %d is malformed" % + (phase_id, index)) + continue + part_ids = part.get("piece_ids") + if not isinstance(part_ids, list) or not part_ids: + errors.append("phase %s part %d carries no piece" % + (phase_id, index)) + continue + envelope = part.get("envelope_bytes") + if not isinstance(envelope, int) or isinstance(envelope, bool) \ + or envelope > MAX_ACTIVATION_PIECE_ENVELOPE_BYTES: + errors.append( + "phase %s part %d exceeds or omits the delivery budget" % + (phase_id, index)) + packed.extend(part_ids) + if packed != piece_ids: + errors.append( + "phase %s parts do not partition its piece list exactly" % + phase_id) + frozen_ids = [row.get("piece_id") for row in manifest.get("pieces") or [] + if isinstance(row, dict)] + if sorted(planned) != sorted(frozen_ids): + errors.append( + "phase plan membership is not exactly the frozen piece set") + if len(planned) != len(set(planned)): + errors.append("a frozen piece is planned into more than one phase") + return errors + + def _piece_manifest_errors(manifest): """Validate the frozen piece set of a v3 bundle.""" errors = [] + phased = manifest.get("activation_protocol") in PHASED_PROTOCOLS pieces = manifest.get("pieces") if not isinstance(pieces, list) or not pieces: return ["activation bundle must freeze at least one piece"] @@ -858,6 +1317,12 @@ def _piece_manifest_errors(manifest): row.get("bytes"), int): errors.append("activation piece %s manifest is malformed" % piece_id) + if phased and row.get("phase") not in PHASES: + errors.append("activation piece %s carries no registered phase" % + piece_id) + elif not phased and "phase" in row: + errors.append("activation piece %s carries a phase in a " + "pre-phase era" % piece_id) if row.get("kind") == "card": routes.append(row.get("route_id")) if row.get("source_hash") != row.get("compiled_source_hash"): @@ -879,7 +1344,8 @@ def activation_receipt_binding(context): def activation_bundle_binding(context): """Return the delivery-independent frozen Bundle commitment.""" - return {field: context.get(field) for field in ACTIVATION_BUNDLE_FIELDS} + return {field: context.get(field) + for field in activation_bundle_fields(context)} def _delivery_material_manifest(context): @@ -981,9 +1447,11 @@ def build_activation_piece(root, activation_context, piece_id, *, if errors: raise ActivationError("activation context is invalid: %s" % "; ".join(errors)) - if activation_context.get("activation_protocol") != ACTIVATION_PROTOCOL: + protocol = activation_context.get("activation_protocol") + if protocol not in PIECE_DELIVERY_PROTOCOLS: raise ActivationError( - "piece delivery requires a %s activation" % ACTIVATION_PROTOCOL) + "piece delivery requires one of %s" % + ", ".join(sorted(PIECE_DELIVERY_PROTOCOLS))) manifest = activation_context["activation_bundle_manifest"] records = [row for row in manifest.get("pieces") or [] if isinstance(row, dict) and row.get("piece_id") == piece_id] @@ -1029,6 +1497,152 @@ def build_activation_piece(root, activation_context, piece_id, *, } +def build_phase_delivery(root, activation_context, phase_id, part_index=0, *, + execution_context_id=None, + delivery_attempt_id=None, nonce=None): + """Deliver one frozen phase part as its own budgeted tool result.""" + errors = activation_context_errors(activation_context) + if errors: + raise ActivationError("activation context is invalid: %s" % + "; ".join(errors)) + if activation_context.get("activation_protocol") not in PHASED_PROTOCOLS: + raise ActivationError( + "phase delivery requires a %s activation" % ACTIVATION_PROTOCOL) + if phase_id not in PHASES: + raise ActivationError("phase %r is not a registered phase" % phase_id) + record = phase_record(activation_context, phase_id) + if record is None: + raise ActivationError("activation freezes no plan for phase %s" % + phase_id) + parts = record.get("parts") or [] + if not parts: + raise ActivationError( + "phase %s freezes no deliverable part; it carries no piece" % + phase_id) + if not isinstance(part_index, int) or isinstance(part_index, bool) or \ + part_index < 0 or part_index >= len(parts): + raise ActivationError( + "phase %s has %d part(s); part %r does not exist" % + (phase_id, len(parts), part_index)) + part = parts[part_index] + manifest = activation_context["activation_bundle_manifest"] + frozen = {row.get("piece_id"): row for row in manifest.get("pieces") or [] + if isinstance(row, dict)} + records = [] + texts = [] + for piece_id in part.get("piece_ids") or []: + frozen_record = frozen.get(piece_id) + if not isinstance(frozen_record, dict): + raise ActivationError( + "phase %s part %d names unfrozen piece %s" % + (phase_id, part_index, piece_id)) + # Re-prove every file against current bytes, exactly as v3 does per + # piece: grouping files into one result must not weaken the per-file + # drift check that makes the frozen SHA meaningful. + snapshot, text = _snapshot_text(root, frozen_record["path"]) + if snapshot.sha256 != frozen_record["sha256"]: + raise ActivationError( + "activation piece %s drifted since admission (%s)" % + (piece_id, frozen_record["path"])) + records.append(frozen_record) + texts.append(text) + attempt = delivery_attempt_id or expected_delivery_attempt_id( + activation_context["card_bundle_sha256"], + execution_context_id or os.environ.get(EXECUTION_CONTEXT_ENV)) + payload = _phase_delivery_payload( + manifest, phase_id, part_index, len(parts), records, texts, + nonce=nonce or _mint_nonce(), delivery_attempt_id=attempt, + card_bundle_sha256=activation_context["card_bundle_sha256"], + phase_plan_sha256=activation_context.get("phase_plan_sha256")) + envelope = _piece_envelope_bytes(payload) + if envelope > MAX_ACTIVATION_PIECE_ENVELOPE_BYTES: + raise ActivationError( + "phase %s part %d serializes to %d bytes, over the %d-byte " + "delivery budget" % + (phase_id, part_index, envelope, + MAX_ACTIVATION_PIECE_ENVELOPE_BYTES)) + return { + "phase_protocol": PHASE_DELIVERY_PROTOCOL, + "card_bundle_sha256": activation_context["card_bundle_sha256"], + "phase_plan_sha256": activation_context.get("phase_plan_sha256"), + "phase_id": phase_id, + "part_index": part_index, + "part_count": len(parts), + "phase_piece_ids": list(part.get("piece_ids") or []), + "phase_envelope_bytes": envelope, + "delivery_attempt_id": attempt, + "delivery_nonce": payload["delivery_nonce"], + "activation_phase_payload": payload, + **_delivery_binding(execution_context_id, + protocol=ACTIVATION_PROTOCOL), + } + + +def build_phase_ack(delivery_receipt, nonce, *, execution_context_id=None): + """Turn one returned phase nonce into same-context delivery evidence. + + Same three-part model as a single piece: this is the third part only. + It shows the part reached this context; it never shows the bodies ahead + of the nonce were read. + """ + if not isinstance(delivery_receipt, dict): + raise ActivationError("phase ack requires one delivery receipt") + if delivery_receipt.get("phase_protocol") != PHASE_DELIVERY_PROTOCOL: + raise ActivationError("phase ack requires a %s delivery" % + PHASE_DELIVERY_PROTOCOL) + expected = delivery_receipt.get("delivery_nonce") + if not isinstance(expected, str) or not expected or nonce != expected: + raise ActivationError( + "phase ack nonce does not match delivery %s part %s" % + (delivery_receipt.get("phase_id"), + delivery_receipt.get("part_index"))) + bound = delivery_receipt.get("execution_context_id") + current = execution_context_id + if current is None: + current = os.environ.get(EXECUTION_CONTEXT_ENV) + if bound != current: + raise ActivationError( + "phase ack must return to the delivering execution context") + return { + "phase_ack_protocol": PHASE_ACK_PROTOCOL, + "card_bundle_sha256": delivery_receipt.get("card_bundle_sha256"), + "phase_plan_sha256": delivery_receipt.get("phase_plan_sha256"), + "phase_id": delivery_receipt.get("phase_id"), + "part_index": delivery_receipt.get("part_index"), + "part_count": delivery_receipt.get("part_count"), + "phase_piece_ids": list(delivery_receipt.get("phase_piece_ids") or []), + "delivery_attempt_id": delivery_receipt.get("delivery_attempt_id"), + "acked_nonce": nonce, + "delivery_receipt_id": delivery_receipt.get("receipt_id"), + **_delivery_binding(execution_context_id, + protocol=ACTIVATION_PROTOCOL), + } + + +PHASE_RECEIPT_FIELDS = ( + "phase_protocol", "card_bundle_sha256", "phase_plan_sha256", "phase_id", + "part_index", "part_count", "phase_piece_ids", "phase_envelope_bytes", + "delivery_attempt_id", "delivery_nonce", + "delivery_mode", "delivery_assurance", "execution_context_id", +) +PHASE_ACK_RECEIPT_FIELDS = ( + "phase_ack_protocol", "card_bundle_sha256", "phase_plan_sha256", + "phase_id", "part_index", "part_count", "phase_piece_ids", + "delivery_attempt_id", "acked_nonce", "delivery_receipt_id", + "delivery_mode", "delivery_assurance", "execution_context_id", +) + + +def phase_receipt_binding(context): + """Return the closed phase-delivery fields persisted in receipt JSONL.""" + return {field: context.get(field) for field in PHASE_RECEIPT_FIELDS} + + +def phase_ack_receipt_binding(context): + """Return the closed phase ack fields persisted in receipt JSONL.""" + return {field: context.get(field) for field in PHASE_ACK_RECEIPT_FIELDS} + + def _mint_nonce(): return os.urandom(16).hex() diff --git a/Tools/check_queue.py b/Tools/check_queue.py index 4d2592f..8b04d55 100644 --- a/Tools/check_queue.py +++ b/Tools/check_queue.py @@ -5952,6 +5952,148 @@ def substantive_review_errors(result, item): return errors +def activation_phase_delivery_errors(result, item, phase_id, *, + actor_context_id=None): + """Prove one phase's frozen set reached the context that is acting now. + + Three separate things have to hold, and the reason each is here is a + distinct failure it rules out: + + * the ack set covers every part of the phase -- a partial delivery would + otherwise let an action proceed on a Card it never received; + * every ack carries the attempt id derived from the *current* activation + bundle -- a complete chain from a superseded bundle is internally + consistent and still worthless, so consistency alone cannot be the + test; + * when the caller is the actor (a judgment, a governance write), the + attempt id must derive from the actor's own context -- borrowing + somebody else's ack chain would prove that a different context read + the Card. + + An integrator checking history at a queue edge is not the actor: it + passes no ``actor_context_id`` and the second condition alone applies. + An activation that never bound a host context is `prepared`/`degraded` + and stays exempt (v3 D7): it may proceed, but nothing it produces may + claim machine-enforced delivery. + """ + errors = [] + if not isinstance(item, dict): + return ["phase delivery check requires one Queue item"] + catalog = current_receipt_catalog(result) + entry = catalog.get(item.get("activation_receipt")) + activation = entry[1] if isinstance(entry, tuple) else entry + if not isinstance(activation, dict): + return errors + if activation.get("activation_protocol") not in \ + card_activation.PHASED_PROTOCOLS: + # Pre-phase eras owe their own era's obligation, replayed as written. + return errors + if activation.get("delivery_assurance") != "host-bound": + return errors + context = card_activation.context_from_receipt(activation) + expected_ids = set(card_activation.phase_piece_ids(context, phase_id)) + if not expected_ids: + return errors + record = card_activation.phase_record(context, phase_id) or {} + part_count = record.get("part_count") + bundle_sha = activation.get("card_bundle_sha256") + acked_ids = set() + acked_parts = set() + attempts = set() + for candidate in catalog.values(): + receipt = candidate[1] if isinstance(candidate, tuple) else candidate + if not isinstance(receipt, dict): + continue + if receipt.get("phase_ack_protocol") != \ + card_activation.PHASE_ACK_PROTOCOL: + continue + if receipt.get("phase_id") != phase_id: + continue + if receipt.get("card_bundle_sha256") != bundle_sha: + continue + if receipt.get("result") not in (None, "pass"): + continue + if receipt.get("invalidated_by") is not None: + continue + acked_ids.update( + piece_id for piece_id in receipt.get("phase_piece_ids") or [] + if isinstance(piece_id, str)) + acked_parts.add(receipt.get("part_index")) + attempts.add(receipt.get("delivery_attempt_id")) + missing = sorted(expected_ids - acked_ids) + if missing: + errors.append( + "phase %s is not delivered to this activation: %d of %d frozen " + "piece(s) have no current ack (%s)" % + (phase_id, len(missing), len(expected_ids), + ", ".join(missing[:4]) + ("..." if len(missing) > 4 else ""))) + return errors + if isinstance(part_count, int) and len(acked_parts) != part_count: + errors.append( + "phase %s acknowledges %d of %d frozen part(s)" % + (phase_id, len(acked_parts), part_count)) + if actor_context_id: + expected_attempt = card_activation.expected_delivery_attempt_id( + bundle_sha, actor_context_id) + foreign = sorted(str(value) for value in attempts + if value != expected_attempt) + if foreign: + errors.append( + "phase %s was delivered to another execution context; this " + "actor holds no delivery evidence of its own (attempt %s)" % + (phase_id, ", ".join(foreign[:2]))) + elif len(attempts) > 1: + errors.append( + "phase %s mixes %d delivery attempts; one phase is earned by one " + "attempt" % (phase_id, len(attempts))) + return errors + + +CONTROL_PLANE_PREFIXES = ("kernel/", "profiles/", "Tools/") + + +def batch_touches_control_plane(item): + """Say whether one batch's own manifest edits the control plane. + + This is the governance predicate, and it is deliberately about the + objects a batch changes rather than about which tool it runs. A tool + name can be avoided -- a file is editable without any writer -- while a + batch that carries `kernel/`, `profiles/` or `Tools/` in its manifest is + doing governance whatever it invokes, and it still has to reach + merge-ready through the one edge no editor can route around. + """ + if not isinstance(item, dict): + return False + for path in item.get("manifest") or []: + if isinstance(path, str) and path.startswith(CONTROL_PLANE_PREFIXES): + return True + return False + + +def task_phase_delivery_errors(result, phase_id, *, actor_context_id=None): + """Check one phase across every batch that still carries an activation. + + Some phases are entered by a task-level act rather than a batch one: a + completion-candidate transition, a Standards governance write. Those + acts have no batch of their own, and a phase plan is frozen per batch, + so the honest scope is every batch currently holding an activation. + When none does the obligation has no carrier and this returns nothing -- + the gate declines to invent evidence it has no place to look for, which + is the same reason K13/20 refuses to treat an admission receipt as + delivery. + """ + errors = [] + for item in (result.get("queue") or {}).get("required_queue") or []: + if not isinstance(item, dict): + continue + if item.get("state") not in ("open", "merge-ready"): + continue + for message in activation_phase_delivery_errors( + result, item, phase_id, actor_context_id=actor_context_id): + errors.append("%s: %s" % (item.get("id"), message)) + return errors + + def judgment_record_set_sha256(records): """Hash the exact actual judgment set the batch-review wrapper binds.""" identity = sorted( @@ -15210,6 +15352,8 @@ def make_check_receipt(result, outcome, details, mode, readback_context=None, piece_context=None, piece_ack_context=None, + phase_context=None, + phase_ack_context=None, resume_activation_contexts=None): """Build the canonical receipt for one already-evaluated Queue result. @@ -15255,6 +15399,12 @@ def make_check_receipt(result, outcome, details, mode, if mode.startswith("ack-activation-piece:") and piece_ack_context: receipt.update(card_activation.piece_ack_receipt_binding( piece_ack_context)) + if mode.startswith("deliver-phase:") and phase_context: + receipt.update(card_activation.phase_receipt_binding( + phase_context)) + if mode.startswith("ack-activation-phase:") and phase_ack_context: + receipt.update(card_activation.phase_ack_receipt_binding( + phase_ack_context)) if mode.startswith("deliver-readback:") and readback_context: receipt.update(card_activation.readback_receipt_binding( readback_context)) @@ -15358,7 +15508,8 @@ def _emit_json_receipts(receipts): def _delivery_result(receipt, activation_context=None, readback_context=None, - piece_context=None, resume_activation_contexts=None): + piece_context=None, phase_context=None, + resume_activation_contexts=None): """Attach transient bytes to the tool result, never the receipt register.""" emitted = dict(receipt) if activation_context and "activation_delivery_payload" in \ @@ -15368,6 +15519,9 @@ def _delivery_result(receipt, activation_context=None, readback_context=None, if readback_context: emitted["readback_delivery_payload"] = readback_context.get( "readback_delivery_payload") + if phase_context: + emitted["activation_phase_payload"] = phase_context.get( + "activation_phase_payload") if piece_context: emitted["activation_piece_payload"] = piece_context.get( "activation_piece_payload") @@ -15395,7 +15549,8 @@ def _write_receipt(root, relative_path, result, outcome, details, mode, standards_revalidation_context=None, hub_page_candidates=None, activation_context=None, readback_context=None, piece_context=None, - piece_ack_context=None, resume_activation_contexts=None, + piece_ack_context=None, phase_context=None, + phase_ack_context=None, resume_activation_contexts=None, build_unwritten=False): """Append the small receipt and return its delivery-enriched tool result. @@ -15419,11 +15574,13 @@ def _write_receipt(root, relative_path, result, outcome, details, mode, readback_context=readback_context, piece_context=piece_context, piece_ack_context=piece_ack_context, + phase_context=phase_context, + phase_ack_context=phase_ack_context, resume_activation_contexts=resume_activation_contexts, ) return _delivery_result( receipt, activation_context, readback_context, piece_context, - resume_activation_contexts) + phase_context, resume_activation_contexts) path = kblib.managed_repository_path( root, relative_path, ".cambium/receipts", suffixes=(".jsonl",), must_exist=False, @@ -15439,12 +15596,14 @@ def _write_receipt(root, relative_path, result, outcome, details, mode, readback_context=readback_context, piece_context=piece_context, piece_ack_context=piece_ack_context, + phase_context=phase_context, + phase_ack_context=phase_ack_context, resume_activation_contexts=resume_activation_contexts, ) kblib.write_receipts(path, [receipt]) return _delivery_result( receipt, activation_context, readback_context, piece_context, - resume_activation_contexts) + phase_context, resume_activation_contexts) def _maintenance_gate_inventory(result): @@ -16271,9 +16430,32 @@ def main(argv=None): "--ack-activation-piece", metavar="BATCH_ID", help="return one delivered piece nonce as same-context delivery " "evidence") + group.add_argument( + "--deliver-phase", metavar="BATCH_ID", + help="deliver one frozen activation phase part of BATCH_ID inside " + "the protocol delivery budget") + group.add_argument( + "--ack-activation-phase", metavar="BATCH_ID", + help="return one delivered phase part nonce as same-context delivery " + "evidence") parser.add_argument( "--readback-rule", metavar="RULE_ID", help="registered rule selected with --deliver-readback") + parser.add_argument( + "--phase", metavar="PHASE_ID", + help="frozen activation phase selected with --deliver-phase or " + "--ack-activation-phase") + parser.add_argument( + "--phase-part", metavar="INDEX", type=int, default=0, + help="part index inside the selected phase (default 0)") + parser.add_argument( + "--phase-nonce", metavar="NONCE", + help="nonce returned from the delivered phase part, supplied to " + "--ack-activation-phase") + parser.add_argument( + "--phase-delivery-receipt", metavar="RECEIPT_ID", + help="delivery receipt the acknowledged phase nonce came from, " + "supplied to --ack-activation-phase") parser.add_argument( "--piece", metavar="PIECE_ID", help="frozen activation piece selected with " @@ -16335,6 +16517,8 @@ def _run(args, produced): readback_context = None piece_context = None piece_ack_context = None + phase_context = None + phase_ack_context = None resume_activation_contexts = [] if args.confirmation_receipt and not args.require_ready: @@ -16363,6 +16547,28 @@ def _run(args, produced): if value and not args.ack_activation_piece: errors.append("%s is only valid with --ack-activation-piece" % flag) + if args.phase and not (args.deliver_phase or args.ack_activation_phase): + errors.append("--phase is only valid with --deliver-phase or " + "--ack-activation-phase") + if args.deliver_phase and not args.phase: + errors.append("--deliver-phase requires --phase") + if args.ack_activation_phase and not ( + args.phase and args.phase_nonce and args.phase_delivery_receipt): + errors.append( + "--ack-activation-phase requires --phase, --phase-nonce and " + "--phase-delivery-receipt") + for flag, value in (("--phase-nonce", args.phase_nonce), + ("--phase-delivery-receipt", + args.phase_delivery_receipt)): + if value and not args.ack_activation_phase: + errors.append("%s is only valid with --ack-activation-phase" % + flag) + if args.phase_part and not (args.deliver_phase or + args.ack_activation_phase): + errors.append("--phase-part is only valid with --deliver-phase or " + "--ack-activation-phase") + if args.phase_part < 0: + errors.append("--phase-part must not be negative") maintenance_evidence = ( args.budget_manifest_receipt, args.ledger_advance_receipt, args.watermark_advance_receipt, @@ -16551,6 +16757,67 @@ def _run(args, produced): except (OSError, UnicodeError, ValueError) as exc: errors.append("cannot acknowledge activation piece: %s" % exc) + elif not errors and (args.deliver_phase or args.ack_activation_phase): + batch_id = args.deliver_phase or args.ack_activation_phase + item = result.get("items_by_id", {}).get(batch_id) + activation_receipt = None + if item is None: + errors.append("requested batch %s does not exist" % batch_id) + elif item.get("state") not in ("open", "merge-ready"): + errors.append( + "activation phase delivery requires an open or merge-ready " + "batch; %s is %s" % (batch_id, item.get("state"))) + else: + catalog = result.get( + "current_receipt_catalog", result.get("receipt_catalog", {})) + entry = catalog.get(item.get("activation_receipt")) + activation_receipt = entry[1] if entry is not None else None + if (not isinstance(activation_receipt, dict) or + activation_receipt.get("tool") != TOOL or + activation_receipt.get("tool_version") != TOOL_VERSION): + errors.append( + "batch %s has no current Card-first activation receipt; " + "reopen it before phase delivery" % batch_id) + activation_receipt = None + if activation_receipt is not None and args.deliver_phase: + try: + phase_context = card_activation.build_phase_delivery( + result["root"], + card_activation.context_from_receipt(activation_receipt), + args.phase, args.phase_part) + except (OSError, UnicodeError, ValueError) as exc: + errors.append("cannot deliver activation phase: %s" % exc) + elif activation_receipt is not None: + catalog = result.get( + "current_receipt_catalog", result.get("receipt_catalog", {})) + delivery_entry = catalog.get(args.phase_delivery_receipt) + delivery = delivery_entry[1] if delivery_entry is not None else None + if not isinstance(delivery, dict): + errors.append( + "phase delivery receipt %s is absent from the current " + "catalog" % args.phase_delivery_receipt) + elif delivery.get("phase_id") != args.phase: + errors.append( + "phase delivery receipt %s does not deliver %s" % + (args.phase_delivery_receipt, args.phase)) + elif delivery.get("part_index") != args.phase_part: + errors.append( + "phase delivery receipt %s delivers part %s, not %s" % + (args.phase_delivery_receipt, delivery.get("part_index"), + args.phase_part)) + elif delivery.get("card_bundle_sha256") != activation_receipt.get( + "card_bundle_sha256"): + errors.append( + "phase delivery receipt %s belongs to another activation " + "bundle" % args.phase_delivery_receipt) + else: + try: + phase_ack_context = card_activation.build_phase_ack( + dict(delivery, receipt_id=args.phase_delivery_receipt), + args.phase_nonce) + except (OSError, UnicodeError, ValueError) as exc: + errors.append("cannot acknowledge activation phase: %s" % + exc) elif not errors and args.require_maintenance_complete: maintenance_errors, maintenance_context = \ _maintenance_completion_gate_errors( @@ -16710,11 +16977,17 @@ def _run(args, produced): ("ack-activation-piece:%s:%s" % ( args.ack_activation_piece, args.piece) if args.ack_activation_piece else + ("deliver-phase:%s:%s:%d" % ( + args.deliver_phase, args.phase, args.phase_part) + if args.deliver_phase else + ("ack-activation-phase:%s:%s:%d" % ( + args.ack_activation_phase, args.phase, args.phase_part) + if args.ack_activation_phase else ("require-complete" if args.require_complete else ("require-maintenance-complete" if args.require_maintenance_complete else ("resume-status" if args.resume_status else - "consistency")))))))) + "consistency")))))))))) try: receipt = _write_receipt( args.root, args.receipts, result, outcome, details, mode, @@ -16727,6 +17000,8 @@ def _run(args, produced): readback_context=readback_context, piece_context=piece_context, piece_ack_context=piece_ack_context, + phase_context=phase_context, + phase_ack_context=phase_ack_context, resume_activation_contexts=resume_activation_contexts, build_unwritten=produced is not None, ) diff --git a/Tools/compiled/cli-contract.yaml b/Tools/compiled/cli-contract.yaml index 85e92e9..cbcb2ea 100644 --- a/Tools/compiled/cli-contract.yaml +++ b/Tools/compiled/cli-contract.yaml @@ -66,7 +66,7 @@ source_files: - Tools/stamp_cards.py - Tools/update_queue.py - Tools/update_task.py -source_hash: sha256:4f4385918e933e211b3676c0f85df847388ee7318fb76f208eae061ec40a476f +source_hash: sha256:290d21438a77d803aec886b7596dc5f2c34c1aa5d61068907ed12dbc12892067 receipt_shape: base_fields: - receipt_id @@ -1752,7 +1752,7 @@ tools: receipt_extensions_extraction: partial - tool: check_queue module: Tools/check_queue.py - source_hash: sha256:4ec7f2dc3727c35688ec89105a396d4421ae52568b14e8b7db7c373b870f7904 + source_hash: sha256:3467bec37aa3c7be3cb6df0e7d5f5400d6cbde8a2da3b96cc38fdc44b416a2e0 description: Validate canonical Required Queue state arguments: - dest: root @@ -1853,6 +1853,28 @@ tools: action: store type: null help: return one delivered piece nonce as same-context delivery evidence + - dest: deliver_phase + option_strings: + - --deliver-phase + required: false + default: null + default_type: NoneType + choices: null + nargs: null + action: store + type: null + help: deliver one frozen activation phase part of BATCH_ID inside the protocol delivery budget + - dest: ack_activation_phase + option_strings: + - --ack-activation-phase + required: false + default: null + default_type: NoneType + choices: null + nargs: null + action: store + type: null + help: return one delivered phase part nonce as same-context delivery evidence - dest: readback_rule option_strings: - --readback-rule @@ -1864,6 +1886,50 @@ tools: action: store type: null help: registered rule selected with --deliver-readback + - dest: phase + option_strings: + - --phase + required: false + default: null + default_type: NoneType + choices: null + nargs: null + action: store + type: null + help: frozen activation phase selected with --deliver-phase or --ack-activation-phase + - dest: phase_part + option_strings: + - --phase-part + required: false + default: 0 + default_type: int + choices: null + nargs: null + action: store + type: int + help: part index inside the selected phase (default 0) + - dest: phase_nonce + option_strings: + - --phase-nonce + required: false + default: null + default_type: NoneType + choices: null + nargs: null + action: store + type: null + help: nonce returned from the delivered phase part, supplied to --ack-activation-phase + - dest: phase_delivery_receipt + option_strings: + - --phase-delivery-receipt + required: false + default: null + default_type: NoneType + choices: null + nargs: null + action: store + type: null + help: delivery receipt the acknowledged phase nonce came from, supplied to --ack-activation-phase - dest: piece option_strings: - --piece @@ -1985,6 +2051,8 @@ tools: - deliver_readback - deliver_activation_piece - ack_activation_piece + - deliver_phase + - ack_activation_phase receipt_extensions: - activation_context - active_card_context_deliveries @@ -2007,6 +2075,8 @@ tools: - pending_amendments - pending_delta_applies - pending_guidance + - phase_ack_context + - phase_context - piece_ack_context - piece_context - progress_ledger_sha256 @@ -3045,7 +3115,7 @@ tools: receipt_extensions_extraction: complete - tool: record_batch_judgment module: Tools/record_batch_judgment.py - source_hash: sha256:ae6b734b1de1712e9967265217112a9aaf4db0941ff761c3ab464acc78ec345f + source_hash: sha256:33d65be54777d0f6b4abf2f9b1d76ac0bbea5eb51d416f6782fb5111c529b7e2 description: Record one snapshot-bound Batch Review judgment arguments: - dest: root @@ -4275,7 +4345,7 @@ tools: receipt_extensions_extraction: complete - tool: update_queue module: Tools/update_queue.py - source_hash: sha256:f691748b42ac0252cc7ecf948af01f593845242e2dc28f2ad462977f426a564f + source_hash: sha256:87aa7219da2ff93d1024062b0e605e0a308f63342a92b9beb49ccd0268ff2a01 description: Apply one Required Queue transition arguments: - dest: root @@ -4541,7 +4611,7 @@ tools: receipt_extensions_extraction: partial - tool: update_task module: Tools/update_task.py - source_hash: sha256:1078591b16b485f34184d41e486e033ccb56bdc1ae8e8aa146baaff2f61c6767 + source_hash: sha256:35bd0045eb56f50de497e61df1f7aa481178a3bf831b18f72d829b873232bdfe description: Apply one canonical task-state transition arguments: - dest: root diff --git a/Tools/compiled/host-configs/claude-code.mcp.json b/Tools/compiled/host-configs/claude-code.mcp.json index 40cb372..4fcd4b1 100644 --- a/Tools/compiled/host-configs/claude-code.mcp.json +++ b/Tools/compiled/host-configs/claude-code.mcp.json @@ -1 +1 @@ -{"mcpServers":{"cambium":{"args":["/Tools/mcp_server.py"],"command":"python3","cwd":"","env":{"CAMBIUM_INTERFACE_SOURCE_HASH":"sha256:2683bec5afe71533a7a8df5253ecd5e0fbc9160297e5ae2a88c717882191a82f","CAMBIUM_WORKSPACE_ROOT":""}}}} +{"mcpServers":{"cambium":{"args":["/Tools/mcp_server.py"],"command":"python3","cwd":"","env":{"CAMBIUM_INTERFACE_SOURCE_HASH":"sha256:10e4dff1f12e27076ec5b4c701aab0239bb15464f67230e7ee1359301c41f605","CAMBIUM_WORKSPACE_ROOT":""}}}} diff --git a/Tools/compiled/host-configs/codex.config.toml b/Tools/compiled/host-configs/codex.config.toml index 7715ed7..ea36cea 100644 --- a/Tools/compiled/host-configs/codex.config.toml +++ b/Tools/compiled/host-configs/codex.config.toml @@ -5,7 +5,7 @@ # server name: cambium # server entry point: Tools/mcp_server.py (under the distribution root) # source: Tools/compiled/mcp-tools.json -# source_hash: sha256:2683bec5afe71533a7a8df5253ecd5e0fbc9160297e5ae2a88c717882191a82f +# source_hash: sha256:10e4dff1f12e27076ec5b4c701aab0239bb15464f67230e7ee1359301c41f605 # regenerate: python3 Tools/render_host_configs.py . # verify: python3 Tools/render_host_configs.py . --check # @@ -35,5 +35,5 @@ command = "python3" cwd = "" [mcp_servers.cambium.env] -CAMBIUM_INTERFACE_SOURCE_HASH = "sha256:2683bec5afe71533a7a8df5253ecd5e0fbc9160297e5ae2a88c717882191a82f" +CAMBIUM_INTERFACE_SOURCE_HASH = "sha256:10e4dff1f12e27076ec5b4c701aab0239bb15464f67230e7ee1359301c41f605" CAMBIUM_WORKSPACE_ROOT = "" diff --git a/Tools/compiled/host-configs/dsh-profile-patch.yaml b/Tools/compiled/host-configs/dsh-profile-patch.yaml index 974d827..879aec6 100644 --- a/Tools/compiled/host-configs/dsh-profile-patch.yaml +++ b/Tools/compiled/host-configs/dsh-profile-patch.yaml @@ -5,7 +5,7 @@ # server name: cambium # server entry point: Tools/mcp_server.py (under the distribution root) # source: Tools/compiled/mcp-tools.json -# source_hash: sha256:2683bec5afe71533a7a8df5253ecd5e0fbc9160297e5ae2a88c717882191a82f +# source_hash: sha256:10e4dff1f12e27076ec5b4c701aab0239bb15464f67230e7ee1359301c41f605 # regenerate: python3 Tools/render_host_configs.py . # verify: python3 Tools/render_host_configs.py . --check # diff --git a/Tools/compiled/host-configs/dsh.env b/Tools/compiled/host-configs/dsh.env index 3cff541..1fbb611 100644 --- a/Tools/compiled/host-configs/dsh.env +++ b/Tools/compiled/host-configs/dsh.env @@ -4,7 +4,7 @@ # carries: binding # server name: cambium # source: Tools/compiled/mcp-tools.json -# source_hash: sha256:2683bec5afe71533a7a8df5253ecd5e0fbc9160297e5ae2a88c717882191a82f +# source_hash: sha256:10e4dff1f12e27076ec5b4c701aab0239bb15464f67230e7ee1359301c41f605 # regenerate: python3 Tools/render_host_configs.py . # verify: python3 Tools/render_host_configs.py . --check # @@ -21,5 +21,5 @@ # valid absolute path on any of these hosts, so an un-substituted copy # fails at launch instead of resolving to something. -CAMBIUM_INTERFACE_SOURCE_HASH="sha256:2683bec5afe71533a7a8df5253ecd5e0fbc9160297e5ae2a88c717882191a82f" +CAMBIUM_INTERFACE_SOURCE_HASH="sha256:10e4dff1f12e27076ec5b4c701aab0239bb15464f67230e7ee1359301c41f605" CAMBIUM_WORKSPACE_ROOT="" diff --git a/Tools/compiled/host-configs/kimi-code.mcp.json b/Tools/compiled/host-configs/kimi-code.mcp.json index 40cb372..4fcd4b1 100644 --- a/Tools/compiled/host-configs/kimi-code.mcp.json +++ b/Tools/compiled/host-configs/kimi-code.mcp.json @@ -1 +1 @@ -{"mcpServers":{"cambium":{"args":["/Tools/mcp_server.py"],"command":"python3","cwd":"","env":{"CAMBIUM_INTERFACE_SOURCE_HASH":"sha256:2683bec5afe71533a7a8df5253ecd5e0fbc9160297e5ae2a88c717882191a82f","CAMBIUM_WORKSPACE_ROOT":""}}}} +{"mcpServers":{"cambium":{"args":["/Tools/mcp_server.py"],"command":"python3","cwd":"","env":{"CAMBIUM_INTERFACE_SOURCE_HASH":"sha256:10e4dff1f12e27076ec5b4c701aab0239bb15464f67230e7ee1359301c41f605","CAMBIUM_WORKSPACE_ROOT":""}}}} diff --git a/Tools/compiled/mcp-tools.json b/Tools/compiled/mcp-tools.json index 081f26f..d6d03a2 100644 --- a/Tools/compiled/mcp-tools.json +++ b/Tools/compiled/mcp-tools.json @@ -1 +1 @@ -{"artifact":"agent-interface-projection","form":"mcp","generated":{"not_a_revision_basis":"This file is downstream of each tool's own argparse declaration and is never the basis for revising one. To change what an agent may call, change the tool's argparse block, recompile Tools/compiled/cli-contract.yaml, then regenerate this file.","notice":"Generated artifact -- do not edit. Every value here is projected from Tools/compiled/cli-contract.yaml by Tools/render_interface_projection.py; a hand edit is reported by --check as a HOLD.","regenerate":"python3 Tools/render_interface_projection.py .","verify":"python3 Tools/render_interface_projection.py . --check"},"generator":"Tools/render_interface_projection.py","generator_version":"1.0.0","schema_version":1,"source":"Tools/compiled/cli-contract.yaml","source_artifact":"cli-invocation-contract","source_hash":"sha256:0aaadf4b4e1b0fa897f376aef84cdfe6e0fb0f35a9d5081ac6230aea34ecbb3c","source_manifest_hash":"sha256:4f4385918e933e211b3676c0f85df847388ee7318fb76f208eae061ec40a476f","source_schema_version":1,"tool_count":46,"tools":[{"description":"Adopt one approved Standards/Profile revision","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply a Standards adoption","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the transaction; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"plan":{"description":".cambium/deltas/standards-adoptions/*.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"default":".cambium/receipts/standards-adoptions.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan"],"type":"object"},"name":"adopt_standards"},{"description":"Apply one approved cross-Ledger Amendment transaction","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply an Amendment transaction","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the transaction; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"expected_coverage_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Coverage; planning is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-coverage-sha256"]}},"expected_progress_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Progress; planning is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-progress-sha256"]}},"expected_queue_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Queue; planning is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-queue-sha256"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"plan":{"description":".cambium/deltas/amendments/*.yaml plan","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"default":".cambium/receipts/amendments.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan","expected_coverage_sha256","expected_progress_sha256","expected_queue_sha256"],"type":"object"},"name":"apply_amendment"},{"description":"Amend the frozen Task Contract from one confirmed plan.","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply a contract amendment","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the transaction; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"plan":{"description":"repository-relative path under .cambium/deltas/contract-amendments","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"default":".cambium/receipts/contract-amendments.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan"],"type":"object"},"name":"apply_contract_amendment"},{"description":"Deterministic Coverage Delta application","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply canonical Coverage","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the merged Coverage; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"delta":{"description":"batch Coverage delta to apply; canonical mode requires exactly .cambium/deltas/.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"expected_coverage_sha256":{"description":"compare-and-swap guard for canonical --apply: sha256: the caller read from the current Coverage; the write is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-coverage-sha256"]}},"expected_queue_sha256":{"description":"compare-and-swap guard for canonical --apply: sha256: the caller read from the current Queue; the write is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-queue-sha256"]}},"force":{"default":false,"description":"legacy mode only: keep pages whose ledger batch/next_batch does not match the delta batch","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--force"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"ledger":{"description":"Coverage ledger to merge into; canonical mode requires exactly .cambium/state/coverage_ledger.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"preflight":{"default":false,"description":"plan canonical Coverage and routed-gap settlement without writes; allows an open batch","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--preflight"]}},"receipts":{"description":"receipt JSONL destination; canonical mode defaults to a new .cambium/receipts/.jsonl and refuses an existing path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root (canonical mode)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--root"]}}},"required":["ledger","delta"],"type":"object"},"name":"apply_delta","x-cambium-mutually-exclusive":[{"dests":["apply","preflight"],"required":false}]},{"description":"Apply one receipt-backed Profile metadata transition","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may write","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"commit owner state and page projection","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"expected_coverage_sha256":{"description":"Coverage fingerprint observed by the caller","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-coverage-sha256"]}},"expected_page_sha256":{"description":"target page fingerprint observed by the caller","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-page-sha256"]}},"gate_id":{"description":"exact typed Profile Extension Gate ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--gate-id"]}},"gate_receipt":{"description":"current producer receipt ID for this Gate","type":"string","x-cambium-cli":{"action":"store","option_strings":["--gate-receipt"]}},"json":{"default":false,"description":"write the applied receipt as one JSON array","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"page":{"description":"repository-relative Markdown target","type":"string","x-cambium-cli":{"action":"store","option_strings":["--page"]}},"receipts":{"description":"fresh JSONL path under .cambium/receipts; default is .jsonl","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"value":{"description":"requested registered completion value","type":"string","x-cambium-cli":{"action":"store","option_strings":["--value"]}}},"required":["root","gate_id","page","value","gate_receipt"],"type":"object"},"name":"apply_metadata_transition"},{"description":"Apply one no-runtime R09 Profile adoption (initial adoption or pre-runtime profile revision) from a restricted-YAML plan","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"perform the transaction; without it the complete planned change is reported and nothing is written","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"emit the plan/result as one JSON document","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"plan":{"description":"root-relative adoption plan (schemas/profile_adoption_plan.template.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"description":"must be the canonical Standards history stream .cambium/receipts/standards-adoptions.jsonl","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"repository root (no task runtime may exist; governance state may exist)","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan"],"type":"object"},"name":"apply_profile_adoption"},{"description":"Materialize a task runtime from one confirmed plan.","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"write the transaction; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"plan":{"description":"repository-relative path under .cambium/deltas/task-plans","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"default":".cambium/receipts/task-plans.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan"],"type":"object"},"name":"apply_task_plan"},{"description":"Run and publish the K12/09 batch-close evidence bundle","inputSchema":{"additionalProperties":false,"properties":{"accept_candidate_id":{"default":[],"description":"accept this exact current candidate for this close only","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--accept-candidate-id"]}},"accept_candidate_type":{"default":[],"description":"accept every current candidate of this exact tool:check type for this close only","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--accept-candidate-type"]}},"accept_while_unchanged_id":{"default":[],"description":"accept this exact current candidate and permit reuse while its observation is unchanged","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--accept-while-unchanged-id"]}},"accept_while_unchanged_type":{"default":[],"description":"expand this current exact type set and permit those rows to be reused while unchanged","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--accept-while-unchanged-type"]}},"batch":{"description":"merge-ready batch ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--batch"]}},"integrator":{"description":"declared integrator label recorded in the evidence","type":"string","x-cambium-cli":{"action":"store","option_strings":["--integrator"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"default":".cambium/receipts/batch-close.jsonl","description":"repository-relative close evidence JSONL","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"review_attestation":{"description":"reviewer's explicit global-review statement","type":"string","x-cambium-cli":{"action":"store","option_strings":["--review-attestation"]}},"reviewer":{"description":"declared reviewer label (must differ from integrator)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--reviewer"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","batch","integrator","reviewer","review_attestation"],"type":"object"},"name":"check_batch_close"},{"description":"Validate page boundary blocks against the K08/09 page boundary contract (gate: boundary-contract; advisory by default).","inputSchema":{"additionalProperties":false,"properties":{"contract":{"default":"Tools/page_contract.yaml","description":"compiled contract path (default Tools/page_contract.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--contract"]}},"exclude":{"default":[],"description":"subpath to exclude; repeatable","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile":{"description":"profile directory override; default is the selected_profile_manifest of the active Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"only scan .md files under this subpath (directory or single page)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"strict":{"default":false,"description":"treat violations as failures except the B4 migration-tolerated case; the mode a governance decision promotes to a gate","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--strict"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"check_boundary_contract"},{"description":"Validate explicit Corpus Planning artifacts","inputSchema":{"additionalProperties":false,"properties":{"json":{"default":false,"description":"write only the deterministic normalized result JSON to stdout","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile":{"description":"repository-relative Profile manifest or Profile directory; default: selected Profile in Progress Ledger","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"receipts":{"description":"append JSONL receipts here","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"check_corpus_plan"},{"description":"Closed-world freshness / review_by candidate check","inputSchema":{"additionalProperties":false,"properties":{"as_of":{"description":"reference date YYYY-MM-DD for overdue computation (default: today)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--as-of"]}},"defaults":{"description":"optional domain -> volatility mapping file (restricted YAML subset); an active page with no explicit or defaulted volatility is a candidate","type":"string","x-cambium-cli":{"action":"store","option_strings":["--defaults"]}},"exclude":{"default":[],"description":"skip files whose path contains this component (repeatable; default: none)","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable report to stderr; receipts written, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"only scan .md files under this subpath","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"check_freshness"},{"description":"Wiki link missing/ambiguous/heading check","inputSchema":{"additionalProperties":false,"properties":{"exclude":{"default":[],"description":"path component to exclude (repeatable); files whose path contains the component are neither scanned for outgoing links nor used in basename disambiguation, but exact full-path links into them still resolve (excluded means not audited, not nonexistent)","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"only scan .md files under this subpath (the index still covers the whole vault)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"check_links"},{"description":"MOC Module Index consistency candidate detection","inputSchema":{"additionalProperties":false,"properties":{"exclude":{"default":[],"description":"path component to exclude (repeatable); no semantic directory name is excluded by default","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable report to stderr; receipts written, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"description":"JSONL path to append a machine-readable receipt to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"scan root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"check_moc"},{"description":"Validate pages against the compiled frontmatter page contract (gate: page-contract; advisory by default).","inputSchema":{"additionalProperties":false,"properties":{"contract":{"default":"Tools/page_contract.yaml","description":"compiled contract path (default Tools/page_contract.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--contract"]}},"exclude":{"default":[],"description":"subpath to exclude; repeatable","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile":{"description":"profile directory override; default is the selected_profile_manifest of the active Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"only scan .md files under this subpath (directory or single page)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"strict":{"default":false,"description":"treat violations as failures; the mode a governance decision promotes to a gate","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--strict"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"check_page_contract"},{"description":"Profile manifest completeness and unfilled-template check","inputSchema":{"additionalProperties":false,"properties":{"defaults":{"description":"machine-readable profile-form placeholder registry (default: Tools/schemas/execution_defaults.template.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--defaults"]}},"execution_defaults":{"description":"kernel execution-default override registry (default: kernel/K00 Standards Control/execution-defaults-base.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--execution-defaults"]}},"interface":{"description":"normative slot interface file (default: profiles/README.md under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--interface"]}},"json":{"default":false,"description":"write one deterministic JSON object (tool, root, result, findings each carrying a closed mechanical/semantic-unresolved category) to stdout instead of the human summary; receipts and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile_dir":{"description":"the profile directory to check (e.g. profiles/)","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"default":".","description":"vault root that vault-relative bindings resolve against (default: this script's repository root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--root"]}}},"required":["profile_dir"],"type":"object"},"name":"check_profile"},{"description":"Terminal Proof completeness and zero-condition check","inputSchema":{"additionalProperties":false,"properties":{"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"ledger":{"description":"Coverage Ledger YAML; with --root this must be exactly .cambium/state/coverage_ledger.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":["--ledger"]}},"progress_ledger":{"description":"Progress Ledger YAML; required with --root and must be exactly .cambium/state/progress_ledger.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":["--progress-ledger"]}},"proof":{"description":"path to the terminal proof YAML file","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"vault root; when given, path-valued proof fields must exist and selected routes, Cards, and kernel Read Sets must agree with the canonical route indexes","type":"string","x-cambium-cli":{"action":"store","option_strings":["--root"]}},"template":{"default":"Tools/schemas/terminal_proof.template.yaml","description":"field-list template (default Tools/schemas/terminal_proof.template.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--template"]}}},"required":["proof"],"type":"object"},"name":"check_proof"},{"description":"Validate canonical Required Queue state","inputSchema":{"additionalProperties":false,"properties":{"ack_activation_piece":{"description":"return one delivered piece nonce as same-context delivery evidence","type":"string","x-cambium-cli":{"action":"store","option_strings":["--ack-activation-piece"]}},"boundary_gate_receipt":{"default":[],"description":"current gate evidence supplied to --require-revalidation","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--boundary-gate-receipt"]}},"budget_manifest_receipt":{"description":"closed budget-manifest receipt ID supplied to --require-maintenance-complete","type":"string","x-cambium-cli":{"action":"store","option_strings":["--budget-manifest-receipt"]}},"confirmation_receipt":{"description":"confirmation evidence supplied to --require-ready","type":"string","x-cambium-cli":{"action":"store","option_strings":["--confirmation-receipt"]}},"deliver_activation_piece":{"description":"deliver one frozen activation piece of BATCH_ID inside the protocol delivery budget","type":"string","x-cambium-cli":{"action":"store","option_strings":["--deliver-activation-piece"]}},"deliver_readback":{"description":"deliver one registered conditional Card read-back source for an already-open batch","type":"string","x-cambium-cli":{"action":"store","option_strings":["--deliver-readback"]}},"json":{"default":false,"description":"write this run's receipt object to stdout as one canonical JSON array and move the human report to stderr; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"ledger_advance_receipt":{"description":"Coverage Ledger advance receipt ID supplied to --require-maintenance-complete","type":"string","x-cambium-cli":{"action":"store","option_strings":["--ledger-advance-receipt"]}},"piece":{"description":"frozen activation piece selected with --deliver-activation-piece or --ack-activation-piece","type":"string","x-cambium-cli":{"action":"store","option_strings":["--piece"]}},"piece_delivery_receipt":{"description":"delivery receipt the acknowledged nonce came from, supplied to --ack-activation-piece","type":"string","x-cambium-cli":{"action":"store","option_strings":["--piece-delivery-receipt"]}},"piece_nonce":{"description":"nonce returned from the delivered piece, supplied to --ack-activation-piece","type":"string","x-cambium-cli":{"action":"store","option_strings":["--piece-nonce"]}},"readback_rule":{"description":"registered rule selected with --deliver-readback","type":"string","x-cambium-cli":{"action":"store","option_strings":["--readback-rule"]}},"receipts":{"description":"repository-relative JSONL receipt path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"require_complete":{"default":false,"description":"build completion gate: prove no Required work remains","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--require-complete"]}},"require_maintenance_complete":{"default":false,"description":"maintenance completion gate: prove one bounded maintenance run is complete","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--require-maintenance-complete"]}},"require_ready":{"description":"prove BATCH_ID is queued and ready to activate","type":"string","x-cambium-cli":{"action":"store","option_strings":["--require-ready"]}},"require_revalidation":{"description":"prove BATCH_ID may produce its Standards revalidation aggregate","type":"string","x-cambium-cli":{"action":"store","option_strings":["--require-revalidation"]}},"resume_status":{"default":false,"description":"show interruption-safe task and batch resume state","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--resume-status"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"watermark_advance_receipt":{"description":"watermark advance receipt ID supplied to --require-maintenance-complete","type":"string","x-cambium-cli":{"action":"store","option_strings":["--watermark-advance-receipt"]}}},"required":["root"],"type":"object"},"name":"check_queue","x-cambium-mutually-exclusive":[{"dests":["require_ready","require_revalidation","require_complete","require_maintenance_complete","resume_status","deliver_readback","deliver_activation_piece","ack_activation_piece"],"required":false}]},{"description":"Find profile-configured residual content outside accepted roots.","inputSchema":{"additionalProperties":false,"properties":{"config":{"description":"profile-owned restricted YAML scan configuration","type":"string","x-cambium-cli":{"action":"store","option_strings":["--config"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human summary to stderr; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"positive_controls_only":{"default":false,"description":"execute the registered controls through the production classifier without scanning repository content","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--positive-controls-only"]}},"receipts":{"description":"optional JSONL receipt path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scan_id":{"description":"stable ID from the selected profile's scan registry","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scan-id"]}},"time_limit":{"default":55.0,"description":"hard evidence-production budget in seconds (greater than 0 and at most 55)","type":"number","x-cambium-cli":{"action":"store","option_strings":["--time-limit"],"type":"float"}},"vault_root":{"description":"knowledge-vault root to scan","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root","scan_id","config"],"type":"object"},"name":"check_residual_content"},{"description":"Validate the selected profile's Structure Registry against the vault (gate: structure-registry).","inputSchema":{"additionalProperties":false,"properties":{"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile":{"description":"profile directory override; default is the selected_profile_manifest of the active Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"check_structure"},{"description":"Frontmatter controlled-vocabulary check","inputSchema":{"additionalProperties":false,"properties":{"exclude":{"default":[],"description":"subpath to exclude (repeatable; e.g. the compiled kernel/Cards artifacts, whose frontmatter is not governed by the K08 module's knowledge-page schema)","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human summary to stderr; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"policy_fingerprint":{"description":"effective-policy fingerprint (kblib.effective_priority_policy) the quotas were resolved from; recorded on the priority-quota-compliance receipt so its consumers can bind the policy identity, never re-derive it","type":"string","x-cambium-cli":{"action":"store","option_strings":["--policy-fingerprint"]}},"quota_p0":{"default":15.0,"description":"P0 priority quota in percent (default 15; kernel default; the selected profile manifest or task contract may override)","type":"number","x-cambium-cli":{"action":"store","option_strings":["--quota-p0"],"type":"float"}},"quota_p1":{"default":35.0,"description":"P1 priority quota in percent (default 35; kernel default; the selected profile manifest or task contract may override)","type":"number","x-cambium-cli":{"action":"store","option_strings":["--quota-p1"],"type":"float"}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"only scan .md files under this subpath","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"vocab":{"description":"path to vocab.yaml (defaults to vocab.yaml next to this script)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--vocab"]}}},"required":["vault_root"],"type":"object"},"name":"check_vocab"},{"description":"Compile the machine-readable CLI invocation contract from every Tools/*.py argparse declaration.","inputSchema":{"additionalProperties":false,"properties":{"check":{"default":false,"description":"recompute and compare against the existing output; exit 0 when byte-identical, 2 when it is stale or hand-edited","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"output":{"description":"artifact path to write or verify (default: /Tools/compiled/cli-contract.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"root":{"description":"repository root whose Tools/ directory is compiled","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"compile_cli_contract"},{"description":"Compile Required Queue from explicit Coverage assignments","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply a Queue write or replan","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"amendment_id":{"description":"registered Amendment id authorizing the replan; required with --apply-replan","type":"string","x-cambium-cli":{"action":"store","option_strings":["--amendment-id"]}},"apply":{"default":false,"description":"materialize an initially empty Queue","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"apply_replan":{"default":false,"description":"apply a controlled structural diff to a non-empty Queue","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply-replan"]}},"coverage_proposal":{"description":"repository-contained .cambium/deltas/replans/*.coverage.yaml input","type":"string","x-cambium-cli":{"action":"store","option_strings":["--coverage-proposal"]}},"expected_coverage_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Coverage; the replan is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-coverage-sha256"]}},"expected_progress_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Progress; the replan is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-progress-sha256"]}},"expected_queue_revision":{"description":"compare-and-swap guard: the queue_revision the caller read from the current Queue; the write is refused when the live value differs","type":"integer","x-cambium-cli":{"action":"store","option_strings":["--expected-queue-revision"],"type":"int"}},"expected_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Queue; the write is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-sha256"]}},"expected_state_revision":{"description":"compare-and-swap guard: the state_revision the caller read from the current Queue; the replan is refused when the live value differs","type":"integer","x-cambium-cli":{"action":"store","option_strings":["--expected-state-revision"],"type":"int"}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"output":{"description":"repository-relative proposal path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"receipts":{"default":".cambium/receipts/queue-structure.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"replan_diff":{"description":"existing .cambium/tmp/*.yaml diff to consume","type":"string","x-cambium-cli":{"action":"store","option_strings":["--replan-diff"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"compile_queue","x-cambium-mutually-exclusive":[{"dests":["apply","apply_replan"],"required":false}]},{"description":"Compose the effective frontmatter page contract from the kernel bases and the selected profile's Metadata Contract.","inputSchema":{"additionalProperties":false,"properties":{"base":{"description":"applicability base to compile from (default: kernel/K08 Metadata and Status/applicability-base.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--base"]}},"check":{"default":false,"description":"recompute and compare against the existing output; exit 0 when byte-identical, 2 otherwise","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"output":{"description":"compiled page contract to write, or to compare against under --check (default: Tools/page_contract.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"profile":{"description":"profile directory for a validation run; the vault selection stays with K00/03","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"relationships":{"description":"relationship base to compile from (default: kernel/K08 Metadata and Status/relationship-base.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--relationships"]}},"root":{"default":".","description":"vault root (default: this repository)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--root"]}},"sources_role":{"description":"sources-role base to compile from (default: kernel/K07 Sources and Accuracy/sources-role-base.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--sources-role"]}}},"type":"object"},"name":"compose_page_contract"},{"description":"Deterministically compose the vocabulary artifact from the kernel base and the selected profile's extensions.","inputSchema":{"additionalProperties":false,"properties":{"base":{"default":"kernel/K08 Metadata and Status/vocabulary-base.yaml","description":"the kernel vocabulary base the extensions are appended to (default: kernel/K08 Metadata and Status/vocabulary-base.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--base"]}},"check":{"default":false,"description":"recompute and compare against the existing output; exit 0 when values and provenance are identical, 2 otherwise","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"extensions":{"description":"the active profile's vocabulary-extensions.yaml. Canonical adopter Standards state selects the path; when this flag is present it must name that same path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--extensions"]}},"output":{"default":"Tools/vocab.yaml","description":"composed vocabulary artifact to write, or to compare against under --check (default: Tools/vocab.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}}},"type":"object"},"name":"compose_vocab"},{"description":"Cross-file duplicate paragraph candidate detection (for maintenance runs and governance tasks)","inputSchema":{"additionalProperties":false,"properties":{"exclude":{"description":"skip files whose path contains this component (repeatable; default: legacy)","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable report to stderr; receipts written, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to (shared convention, Tools/schemas/receipt.template.jsonl)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"subpath (relative to vault, or absolute): only report similar pairs with at least one side under it","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"vault":{"default":".","description":"vault root directory (default: current directory)","type":"string","x-cambium-cli":{"action":"store","nargs":"?","option_strings":[]}}},"type":"object"},"name":"duplicate_check"},{"description":"Initialize empty Cambium runtime state","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"materialize .cambium/; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"at":{"description":"initial Coverage timestamp (default: current UTC)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--at"]}},"completion_semantics":{"description":"build requires completion-candidate plus Terminal Proof; maintenance closes directly through the bounded maintenance completion gate","enum":["build","maintenance"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--completion-semantics"]}},"concurrency_cap":{"description":"explicit task-contract override of K13/10's concurrency cap; omit it to take the selected profile manifest's registered override, or the kernel default 3 when the manifest registers none","type":"integer","x-cambium-cli":{"action":"store","option_strings":["--concurrency-cap"],"type":"int"}},"contract_version":{"default":"c1","description":"non-empty task-contract version recorded on the Progress Ledger contract","type":"string","x-cambium-cli":{"action":"store","option_strings":["--contract-version"]}},"exclusions":{"default":[],"description":"explicit out-of-scope item; repeatable","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"objective":{"description":"non-empty statement of the task outcome","type":"string","x-cambium-cli":{"action":"store","option_strings":["--objective"]}},"profile_manifest":{"description":"repository-relative selected profile manifest; must equal the selected_profile_manifest of the canonical adopter Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile-manifest"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"scope_version":{"description":"non-empty scope identity stamped on the Queue, Coverage Ledger and task contract","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope-version"]}},"standards_version":{"description":"Standards version this runtime adopts; must equal the approved standards_version of the canonical adopter Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--standards-version"]}},"task_id":{"description":"non-empty task identity stamped on the Queue, Coverage Ledger and Progress Ledger","type":"string","x-cambium-cli":{"action":"store","option_strings":["--task-id"]}}},"required":["root","task_id","objective","scope_version","standards_version","profile_manifest","completion_semantics"],"type":"object"},"name":"init_state"},{"description":"Compile and load Cambium's closed metadata-execution authority contract. This module is deliberately the single authority boundary between metadata declarations and executable writers. A field rule is executable only when an installed writer capability declares the same ``(field, transition, adapter)`` operation, and every installed writer operation must be authorized by exactly one rule. Unknown keys, unknown adapters, orphan implementations, and partial evidence bindings fail closed.","inputSchema":{"additionalProperties":false,"properties":{"authority":{"default":"kernel/K08 Metadata and Status/metadata-authority-base.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":["--authority"]}},"capabilities":{"default":"Tools/operation-capabilities.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":["--capabilities"]}},"check":{"default":false,"type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"output":{"default":"Tools/compiled/metadata-execution-contract.json","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"root":{"default":".","type":"string","x-cambium-cli":{"action":"store","option_strings":["--root"]}}},"type":"object"},"name":"metadata_execution_contract"},{"description":"Migrate existing runtime identity to Standards state","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"write state; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"migrate_standards_state"},{"description":"Read-only onboarding status projector: derives the adoption/onboarding state of one root and exactly one next_action token; writes nothing and owns no ledger","inputSchema":{"additionalProperties":false,"properties":{"json":{"default":false,"description":"emit the status view as one deterministic JSON object instead of the human summary","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile_id":{"description":"target one candidate profile directory name under profiles/ for the full profile-load evaluation (defaults to the single candidate when exactly one exists)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile-id"]}},"root":{"description":"the adopting repository root to project","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"profile_onboarding_status"},{"description":"Project metadata-contract owner state onto page frontmatter","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"take the runtime writer lock and publish the projection; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"page":{"description":"limit to these repository-relative pages (repeatable); default is every Ledger page","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--page"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"project_page_state"},{"description":"Record one snapshot-bound Batch Review judgment","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"append the evidence; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"batch":{"description":"exact open Queue batch ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--batch"]}},"json":{"default":false,"description":"write the applied receipt as one JSON array","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"judgment_item":{"description":"registered Batch Review Requirement Judgment Item ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--judgment-item"]}},"receipts":{"default":".cambium/receipts/batch-judgments.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"reviewer_role":{"description":"declared pass-authority Profile role ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--reviewer-role"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"statement":{"description":"bounded judgment statement (the concrete verdict, not \"reviewed\")","type":"string","x-cambium-cli":{"action":"store","option_strings":["--statement"]}},"target":{"description":"manifest page path, or the batch ID for a batch-selector requirement","type":"string","x-cambium-cli":{"action":"store","option_strings":["--target"]}}},"required":["root","batch","judgment_item","target","reviewer_role","statement"],"type":"object"},"name":"record_batch_judgment"},{"description":"Record a Profile-authorized Corpus Planning semantic decision as machine-readable JSONL","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"description":"declared authority Role ID; required with --apply and must equal the Profile/plan binding","type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"append the structural and semantic receipts; default is dry-run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"plan":{"description":"closed restricted-YAML acceptance decision plan; one .yaml file directly under .cambium/deltas/corpus-plan-acceptances/","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"default":".cambium/receipts/corpus-plan-acceptance.jsonl","description":"repository-relative JSONL path the receipts are appended to (default: .cambium/receipts/corpus-plan-acceptance.jsonl)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan"],"type":"object"},"name":"record_corpus_acceptance"},{"description":"Record snapshot-bound manual Extension Gate evidence","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"description":"declared pass-authority Profile role ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"append the evidence; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"gate_id":{"description":"exact typed Profile Extension Gate ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--gate-id"]}},"json":{"default":false,"description":"write the applied receipt as one JSON array","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"page":{"description":"repository-relative Markdown target","type":"string","x-cambium-cli":{"action":"store","option_strings":["--page"]}},"receipts":{"default":".cambium/receipts/gate-attestations.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"statement":{"description":"bounded manual attestation statement","type":"string","x-cambium-cli":{"action":"store","option_strings":["--statement"]}},"value":{"description":"requested registered completion value","type":"string","x-cambium-cli":{"action":"store","option_strings":["--value"]}}},"required":["root","gate_id","page","value","actor_role","statement"],"type":"object"},"name":"record_gate_attestation"},{"description":"Run a registered scan and record a deterministic Extension Gate result","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"run and append the bound Gate result","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"gate_id":{"description":"exact deterministic typed Profile Gate ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--gate-id"]}},"json":{"default":false,"description":"write the applied receipt as one JSON array","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"page":{"description":"repository-relative Markdown target","type":"string","x-cambium-cli":{"action":"store","option_strings":["--page"]}},"receipts":{"default":".cambium/receipts/gate-results.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","gate_id","page"],"type":"object"},"name":"record_gate_result"},{"description":"Register one approved current-protocol Amendment","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may register or withdraw an Amendment","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"amendment_id":{"description":"id for a queue-replan registration; cross-Ledger operations derive it from --plan instead","type":"string","x-cambium-cli":{"action":"store","option_strings":["--amendment-id"]}},"apply":{"default":false,"description":"write the registration; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"approval_reference":{"description":"explicit-user approval reference; required when --decision-mode is explicit-user","type":"string","x-cambium-cli":{"action":"store","option_strings":["--approval-reference"]}},"coverage_proposal":{"description":".cambium/deltas/replans/*.coverage.yaml proposal","type":"string","x-cambium-cli":{"action":"store","option_strings":["--coverage-proposal"]}},"date":{"description":"YYYY-MM-DD; must equal the UTC registration date","type":"string","x-cambium-cli":{"action":"store","option_strings":["--date"]}},"decision_mode":{"default":"auto","description":"derive delegated authority by default; explicit-user requires --approval-reference","enum":["auto","contract-delegated","explicit-user"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--decision-mode"]}},"expected_coverage_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Coverage; registration is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-coverage-sha256"]}},"expected_progress_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Progress; registration is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-progress-sha256"]}},"expected_queue_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Queue; registration is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-queue-sha256"]}},"json":{"default":false,"description":"write the published receipt to stdout as one canonical JSON array and move the human report to stderr; a dry run publishes no receipt and so writes nothing there; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"operation":{"description":"Amendment operation being registered","enum":["cancel-batch","gap-routing-reconciliation","property-state-migration","queue-replan","scope-replan"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--operation"]}},"plan":{"description":".cambium/deltas/amendments/*.yaml plan","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"reason":{"description":"nonempty withdrawal reason recorded on the row and its receipt","type":"string","x-cambium-cli":{"action":"store","option_strings":["--reason"]}},"receipts":{"default":".cambium/receipts/amendments.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"summary":{"description":"non-empty one-line rationale recorded on the row","type":"string","x-cambium-cli":{"action":"store","option_strings":["--summary"]}},"withdraw":{"description":"retire the named pending registration instead of registering one (K13/06 withdrawal); requires --reason","type":"string","x-cambium-cli":{"action":"store","option_strings":["--withdraw"]}}},"required":["root","expected_coverage_sha256","expected_progress_sha256","expected_queue_sha256"],"type":"object"},"name":"register_amendment"},{"description":"Render the K08/09 boundary projection blocks from page `boundary` frontmatter.","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"rewrite the stale owned blocks atomically; omit to only report what would render","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"check":{"default":false,"description":"exit 2 when any owned block is stale; the default report never fails on staleness","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"contract":{"default":"Tools/page_contract.yaml","description":"compiled contract path (default Tools/page_contract.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--contract"]}},"profile":{"description":"profile directory override; default is the selected_profile_manifest of the active Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"scope":{"description":"only scan .md files under this subpath","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"render_boundary_projection"},{"description":"Render the Cambium MCP server's registration and corpus binding into the configuration file each supported host reads.","inputSchema":{"additionalProperties":false,"properties":{"check":{"default":false,"description":"re-render and compare against the existing products; exit 0 when byte-identical, 2 when one is stale or hand-edited","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"distribution_root":{"description":"absolute path of the Cambium checkout the server is launched from; substituted for (default: leave the placeholder)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--distribution-root"]}},"host":{"description":"render only this host's product (default: every host)","enum":["claude-code","codex","dsh-env","dsh-profile-patch","kimi-code"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--host"]}},"output_dir":{"description":"directory to write or verify the products in (default: /Tools/compiled/host-configs)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output-dir"]}},"projection":{"description":"compiled interface projection to bind to (default: /Tools/compiled/mcp-tools.json)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--projection"]}},"root":{"description":"repository root holding the compiled interface projection","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"sources":{"default":false,"description":"print the declaration source of every rendered field and exit without reading or writing any product","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--sources"]}},"workspace_root":{"description":"absolute path of the corpus repository this registration is bound to; substituted for (default: leave the placeholder)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--workspace-root"]}}},"required":["root"],"type":"object"},"name":"render_host_configs","x-cambium-mutually-exclusive":[{"dests":["check","sources"],"required":false}]},{"description":"Project the compiled CLI invocation contract into the agent-facing interface forms registered in this tool.","inputSchema":{"additionalProperties":false,"properties":{"check":{"default":false,"description":"recompute and compare against the existing artifacts; exit 0 when byte-identical, 2 when one is stale or hand-edited","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"contract":{"description":"compiled CLI contract to project (default: /Tools/compiled/cli-contract.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--contract"]}},"form":{"description":"project only this form (default: every registered form)","enum":["mcp"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--form"]}},"output":{"description":"artifact path to write or verify; requires --form, because one path cannot hold two forms","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"root":{"description":"repository root holding the compiled CLI contract","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"sources":{"default":false,"description":"print the declaration source of every projected field and exit without reading or writing any artifact","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--sources"]}}},"required":["root"],"type":"object"},"name":"render_interface_projection","x-cambium-mutually-exclusive":[{"dests":["check","sources"],"required":false}]},{"description":"Render Required Queue human report","inputSchema":{"additionalProperties":false,"properties":{"check":{"default":false,"description":"compare existing report instead of writing","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"output":{"default":".cambium/reports/required_queue.md","description":"repository-relative report path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"stdout":{"default":false,"description":"print the report to stdout and write nothing","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--stdout"]}}},"required":["root"],"type":"object"},"name":"render_queue"},{"description":"Render derived Structure Registry coverage projections (K01/05 derived roles).","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"rewrite the stale owned blocks atomically; omit to only report what would render","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"check":{"default":false,"description":"exit 2 when any owned block is stale or missing; the default report never fails on staleness","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"profile":{"description":"profile directory override; default is the selected_profile_manifest of the active Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"render_structure_projection"},{"description":"Run the adopter verification set derived from the K00/12 Stable Gate ID Registry (deterministic, not-batch-scoped producers).","inputSchema":{"additionalProperties":false,"properties":{"exclude":{"default":[],"description":"path prefix passed through to scanners that accept it (repeatable)","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"list":{"default":false,"description":"print the derived set and each command without running anything","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--list"]}},"profile":{"description":"profile directory override; default is the live runtime's selected_profile_manifest","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"root":{"description":"repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"run_gates"},{"description":"Scaffold a candidate profile from profiles/_template using the exact-copy whitelist in profiles/template-files.yaml","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"create the candidate; without it the plan is reported and nothing is written","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"emit the plan/result as one JSON document","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile_id":{"description":"candidate profile slug matching [a-z0-9][a-z0-9_-]* (equals the directory name)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile-id"]}},"root":{"description":"repository root containing profiles/","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","profile_id"],"type":"object"},"name":"scaffold_profile"},{"description":"Seal verified frozen receipt history (K12/07). --apply is a maintenance-window operation: run it only with no other Cambium or adopter writer, checker or receipt appender active against this repository.","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"write the seal, or with --reconcile finish the interrupted one; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable report to stderr; receipts written, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"default":".cambium/receipts/seal-receipts.jsonl","description":"repository-relative JSONL path for this tool's own seal receipts, which never seal (default: .cambium/receipts/seal-receipts.jsonl)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"reconcile":{"default":false,"description":"finish an interrupted seal over the publication paths this tool implements; other interruptions fail closed and are resolved by the runbook in Tools/README.md","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--reconcile"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"verify":{"default":false,"description":"re-prove every sealed segment, projection and seal-receipt binding, then exit","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--verify"]}}},"required":["root"],"type":"object"},"name":"seal_receipts"},{"description":"Stamp kernel Runtime Cards","inputSchema":{"additionalProperties":false,"properties":{"acknowledge_compiled":{"default":false,"description":"after semantic regeneration/review, advance compiled_source_hash to the exact current source digest","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--acknowledge-compiled"]}},"cards_dir":{"default":"kernel/Cards","description":"Card directory relative to (default: kernel/Cards)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--cards-dir"]}},"check":{"default":false,"description":"verify only; never write","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"root":{"description":"repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"set_version":{"description":"also set every card's compiled_from value","type":"string","x-cambium-cli":{"action":"store","option_strings":["--set-version"]}}},"required":["root"],"type":"object"},"name":"stamp_cards"},{"description":"Apply one Required Queue transition","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; Queue transition planning and apply both require integrator","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the transition; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"at":{"description":"transition timestamp; defaults to now in UTC","type":"string","x-cambium-cli":{"action":"store","option_strings":["--at"]}},"batch_receipt":{"default":[],"description":"batch-review gate receipt id for open -> merge-ready; exactly one is accepted","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--batch-receipt"]}},"close_gate_receipt":{"description":"check_batch_close receipt id required by the closed transition","type":"string","x-cambium-cli":{"action":"store","option_strings":["--close-gate-receipt"]}},"confirmation_receipt":{"description":"confirmation receipt id required by queued -> open when the batch is confirmation_required","type":"string","x-cambium-cli":{"action":"store","option_strings":["--confirmation-receipt"]}},"delta_apply_receipt":{"description":"apply_delta receipt id required by the closed transition and by merge-ready -> open reopen","type":"string","x-cambium-cli":{"action":"store","option_strings":["--delta-apply-receipt"]}},"delta_path":{"description":"repository-relative .cambium/deltas/.yaml batch delta required by open -> merge-ready","type":"string","x-cambium-cli":{"action":"store","option_strings":["--delta-path"]}},"expected_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Queue; the write is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-sha256"]}},"expected_state_revision":{"description":"compare-and-swap guard: the state_revision the caller read from the current Queue; the write is refused when the live value differs","type":"integer","x-cambium-cli":{"action":"store","option_strings":["--expected-state-revision"],"type":"int"}},"gate_receipt":{"description":"gate receipt id: activation gate for queued -> open, Queue consistency gate for closed and for clearing revalidation-required","type":"string","x-cambium-cli":{"action":"store","option_strings":["--gate-receipt"]}},"hold_state":{"description":"target hold state; exclusive with --transition","enum":["blocked","confirmation-required","none","paused","revalidation-required"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--hold-state"]}},"id":{"description":"Required Queue batch id to transition","type":"string","x-cambium-cli":{"action":"store","option_strings":["--id"]}},"json":{"default":false,"description":"write the applied transition receipt(s) to stdout as one canonical JSON array and move the human report to stderr; a dry run publishes no receipt and so writes nothing there; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"reason":{"description":"non-empty rationale required by merge-ready -> open and by any non-none hold","type":"string","x-cambium-cli":{"action":"store","option_strings":["--reason"]}},"receipts":{"default":".cambium/receipts/queue-transitions.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"standards_revalidation_receipt":{"description":"check_queue --require-revalidation receipt discharging an outstanding Standards revalidation; queued -> open or revalidation-required -> none only","type":"string","x-cambium-cli":{"action":"store","option_strings":["--standards-revalidation-receipt"]}},"transition":{"description":"target lifecycle state; exclusive with --hold-state","enum":["closed","merge-ready","open"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--transition"]}}},"required":["root","id"],"type":"object"},"name":"update_queue","x-cambium-mutually-exclusive":[{"dests":["transition","hold_state"],"required":true}]},{"description":"Apply one canonical task-state transition","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply a task-state write","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the transition; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"at":{"description":"transition timestamp; defaults to now in UTC","type":"string","x-cambium-cli":{"action":"store","option_strings":["--at"]}},"checkpoint_summary":{"description":"non-empty reason required by paused, blocked and cancelled, and when leaving completion-candidate for anything but complete","type":"string","x-cambium-cli":{"action":"store","option_strings":["--checkpoint-summary"]}},"expected_progress_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Progress; --apply is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-progress-sha256"]}},"expected_queue_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Queue; --apply is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-queue-sha256"]}},"json":{"default":false,"description":"write the applied transition receipt to stdout as one canonical JSON array and move the human report to stderr; a dry run publishes no receipt and so writes nothing there; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"maintenance_completion_receipt":{"description":"maintenance completion gate receipt id required by complete under maintenance completion_semantics","type":"string","x-cambium-cli":{"action":"store","option_strings":["--maintenance-completion-receipt"]}},"queue_check_receipt":{"description":"Queue completion gate receipt id required by the completion-candidate transition","type":"string","x-cambium-cli":{"action":"store","option_strings":["--queue-check-receipt"]}},"receipts":{"default":".cambium/receipts/task-transitions.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"terminal_proof_receipt":{"description":"Terminal Proof receipt id required by complete under build completion_semantics","type":"string","x-cambium-cli":{"action":"store","option_strings":["--terminal-proof-receipt"]}},"transition":{"description":"target task state in the Progress Ledger","enum":["active","blocked","cancelled","complete","completion-candidate","paused"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--transition"]}}},"required":["root","transition"],"type":"object"},"name":"update_task"}],"transports":["stdio","streamable-http"]} +{"artifact":"agent-interface-projection","form":"mcp","generated":{"not_a_revision_basis":"This file is downstream of each tool's own argparse declaration and is never the basis for revising one. To change what an agent may call, change the tool's argparse block, recompile Tools/compiled/cli-contract.yaml, then regenerate this file.","notice":"Generated artifact -- do not edit. Every value here is projected from Tools/compiled/cli-contract.yaml by Tools/render_interface_projection.py; a hand edit is reported by --check as a HOLD.","regenerate":"python3 Tools/render_interface_projection.py .","verify":"python3 Tools/render_interface_projection.py . --check"},"generator":"Tools/render_interface_projection.py","generator_version":"1.0.0","schema_version":1,"source":"Tools/compiled/cli-contract.yaml","source_artifact":"cli-invocation-contract","source_hash":"sha256:c529a97ed0e1e19ff3bf651daf1bee9cce41259fa559e651dd454e413274aace","source_manifest_hash":"sha256:290d21438a77d803aec886b7596dc5f2c34c1aa5d61068907ed12dbc12892067","source_schema_version":1,"tool_count":46,"tools":[{"description":"Adopt one approved Standards/Profile revision","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply a Standards adoption","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the transaction; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"plan":{"description":".cambium/deltas/standards-adoptions/*.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"default":".cambium/receipts/standards-adoptions.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan"],"type":"object"},"name":"adopt_standards"},{"description":"Apply one approved cross-Ledger Amendment transaction","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply an Amendment transaction","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the transaction; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"expected_coverage_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Coverage; planning is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-coverage-sha256"]}},"expected_progress_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Progress; planning is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-progress-sha256"]}},"expected_queue_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Queue; planning is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-queue-sha256"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"plan":{"description":".cambium/deltas/amendments/*.yaml plan","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"default":".cambium/receipts/amendments.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan","expected_coverage_sha256","expected_progress_sha256","expected_queue_sha256"],"type":"object"},"name":"apply_amendment"},{"description":"Amend the frozen Task Contract from one confirmed plan.","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply a contract amendment","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the transaction; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"plan":{"description":"repository-relative path under .cambium/deltas/contract-amendments","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"default":".cambium/receipts/contract-amendments.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan"],"type":"object"},"name":"apply_contract_amendment"},{"description":"Deterministic Coverage Delta application","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply canonical Coverage","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the merged Coverage; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"delta":{"description":"batch Coverage delta to apply; canonical mode requires exactly .cambium/deltas/.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"expected_coverage_sha256":{"description":"compare-and-swap guard for canonical --apply: sha256: the caller read from the current Coverage; the write is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-coverage-sha256"]}},"expected_queue_sha256":{"description":"compare-and-swap guard for canonical --apply: sha256: the caller read from the current Queue; the write is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-queue-sha256"]}},"force":{"default":false,"description":"legacy mode only: keep pages whose ledger batch/next_batch does not match the delta batch","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--force"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"ledger":{"description":"Coverage ledger to merge into; canonical mode requires exactly .cambium/state/coverage_ledger.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"preflight":{"default":false,"description":"plan canonical Coverage and routed-gap settlement without writes; allows an open batch","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--preflight"]}},"receipts":{"description":"receipt JSONL destination; canonical mode defaults to a new .cambium/receipts/.jsonl and refuses an existing path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root (canonical mode)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--root"]}}},"required":["ledger","delta"],"type":"object"},"name":"apply_delta","x-cambium-mutually-exclusive":[{"dests":["apply","preflight"],"required":false}]},{"description":"Apply one receipt-backed Profile metadata transition","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may write","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"commit owner state and page projection","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"expected_coverage_sha256":{"description":"Coverage fingerprint observed by the caller","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-coverage-sha256"]}},"expected_page_sha256":{"description":"target page fingerprint observed by the caller","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-page-sha256"]}},"gate_id":{"description":"exact typed Profile Extension Gate ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--gate-id"]}},"gate_receipt":{"description":"current producer receipt ID for this Gate","type":"string","x-cambium-cli":{"action":"store","option_strings":["--gate-receipt"]}},"json":{"default":false,"description":"write the applied receipt as one JSON array","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"page":{"description":"repository-relative Markdown target","type":"string","x-cambium-cli":{"action":"store","option_strings":["--page"]}},"receipts":{"description":"fresh JSONL path under .cambium/receipts; default is .jsonl","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"value":{"description":"requested registered completion value","type":"string","x-cambium-cli":{"action":"store","option_strings":["--value"]}}},"required":["root","gate_id","page","value","gate_receipt"],"type":"object"},"name":"apply_metadata_transition"},{"description":"Apply one no-runtime R09 Profile adoption (initial adoption or pre-runtime profile revision) from a restricted-YAML plan","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"perform the transaction; without it the complete planned change is reported and nothing is written","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"emit the plan/result as one JSON document","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"plan":{"description":"root-relative adoption plan (schemas/profile_adoption_plan.template.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"description":"must be the canonical Standards history stream .cambium/receipts/standards-adoptions.jsonl","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"repository root (no task runtime may exist; governance state may exist)","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan"],"type":"object"},"name":"apply_profile_adoption"},{"description":"Materialize a task runtime from one confirmed plan.","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"write the transaction; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"plan":{"description":"repository-relative path under .cambium/deltas/task-plans","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"default":".cambium/receipts/task-plans.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan"],"type":"object"},"name":"apply_task_plan"},{"description":"Run and publish the K12/09 batch-close evidence bundle","inputSchema":{"additionalProperties":false,"properties":{"accept_candidate_id":{"default":[],"description":"accept this exact current candidate for this close only","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--accept-candidate-id"]}},"accept_candidate_type":{"default":[],"description":"accept every current candidate of this exact tool:check type for this close only","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--accept-candidate-type"]}},"accept_while_unchanged_id":{"default":[],"description":"accept this exact current candidate and permit reuse while its observation is unchanged","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--accept-while-unchanged-id"]}},"accept_while_unchanged_type":{"default":[],"description":"expand this current exact type set and permit those rows to be reused while unchanged","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--accept-while-unchanged-type"]}},"batch":{"description":"merge-ready batch ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--batch"]}},"integrator":{"description":"declared integrator label recorded in the evidence","type":"string","x-cambium-cli":{"action":"store","option_strings":["--integrator"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"default":".cambium/receipts/batch-close.jsonl","description":"repository-relative close evidence JSONL","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"review_attestation":{"description":"reviewer's explicit global-review statement","type":"string","x-cambium-cli":{"action":"store","option_strings":["--review-attestation"]}},"reviewer":{"description":"declared reviewer label (must differ from integrator)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--reviewer"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","batch","integrator","reviewer","review_attestation"],"type":"object"},"name":"check_batch_close"},{"description":"Validate page boundary blocks against the K08/09 page boundary contract (gate: boundary-contract; advisory by default).","inputSchema":{"additionalProperties":false,"properties":{"contract":{"default":"Tools/page_contract.yaml","description":"compiled contract path (default Tools/page_contract.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--contract"]}},"exclude":{"default":[],"description":"subpath to exclude; repeatable","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile":{"description":"profile directory override; default is the selected_profile_manifest of the active Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"only scan .md files under this subpath (directory or single page)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"strict":{"default":false,"description":"treat violations as failures except the B4 migration-tolerated case; the mode a governance decision promotes to a gate","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--strict"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"check_boundary_contract"},{"description":"Validate explicit Corpus Planning artifacts","inputSchema":{"additionalProperties":false,"properties":{"json":{"default":false,"description":"write only the deterministic normalized result JSON to stdout","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile":{"description":"repository-relative Profile manifest or Profile directory; default: selected Profile in Progress Ledger","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"receipts":{"description":"append JSONL receipts here","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"check_corpus_plan"},{"description":"Closed-world freshness / review_by candidate check","inputSchema":{"additionalProperties":false,"properties":{"as_of":{"description":"reference date YYYY-MM-DD for overdue computation (default: today)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--as-of"]}},"defaults":{"description":"optional domain -> volatility mapping file (restricted YAML subset); an active page with no explicit or defaulted volatility is a candidate","type":"string","x-cambium-cli":{"action":"store","option_strings":["--defaults"]}},"exclude":{"default":[],"description":"skip files whose path contains this component (repeatable; default: none)","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable report to stderr; receipts written, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"only scan .md files under this subpath","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"check_freshness"},{"description":"Wiki link missing/ambiguous/heading check","inputSchema":{"additionalProperties":false,"properties":{"exclude":{"default":[],"description":"path component to exclude (repeatable); files whose path contains the component are neither scanned for outgoing links nor used in basename disambiguation, but exact full-path links into them still resolve (excluded means not audited, not nonexistent)","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"only scan .md files under this subpath (the index still covers the whole vault)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"check_links"},{"description":"MOC Module Index consistency candidate detection","inputSchema":{"additionalProperties":false,"properties":{"exclude":{"default":[],"description":"path component to exclude (repeatable); no semantic directory name is excluded by default","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable report to stderr; receipts written, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"description":"JSONL path to append a machine-readable receipt to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"scan root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"check_moc"},{"description":"Validate pages against the compiled frontmatter page contract (gate: page-contract; advisory by default).","inputSchema":{"additionalProperties":false,"properties":{"contract":{"default":"Tools/page_contract.yaml","description":"compiled contract path (default Tools/page_contract.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--contract"]}},"exclude":{"default":[],"description":"subpath to exclude; repeatable","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile":{"description":"profile directory override; default is the selected_profile_manifest of the active Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"only scan .md files under this subpath (directory or single page)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"strict":{"default":false,"description":"treat violations as failures; the mode a governance decision promotes to a gate","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--strict"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"check_page_contract"},{"description":"Profile manifest completeness and unfilled-template check","inputSchema":{"additionalProperties":false,"properties":{"defaults":{"description":"machine-readable profile-form placeholder registry (default: Tools/schemas/execution_defaults.template.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--defaults"]}},"execution_defaults":{"description":"kernel execution-default override registry (default: kernel/K00 Standards Control/execution-defaults-base.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--execution-defaults"]}},"interface":{"description":"normative slot interface file (default: profiles/README.md under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--interface"]}},"json":{"default":false,"description":"write one deterministic JSON object (tool, root, result, findings each carrying a closed mechanical/semantic-unresolved category) to stdout instead of the human summary; receipts and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile_dir":{"description":"the profile directory to check (e.g. profiles/)","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"default":".","description":"vault root that vault-relative bindings resolve against (default: this script's repository root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--root"]}}},"required":["profile_dir"],"type":"object"},"name":"check_profile"},{"description":"Terminal Proof completeness and zero-condition check","inputSchema":{"additionalProperties":false,"properties":{"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"ledger":{"description":"Coverage Ledger YAML; with --root this must be exactly .cambium/state/coverage_ledger.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":["--ledger"]}},"progress_ledger":{"description":"Progress Ledger YAML; required with --root and must be exactly .cambium/state/progress_ledger.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":["--progress-ledger"]}},"proof":{"description":"path to the terminal proof YAML file","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"vault root; when given, path-valued proof fields must exist and selected routes, Cards, and kernel Read Sets must agree with the canonical route indexes","type":"string","x-cambium-cli":{"action":"store","option_strings":["--root"]}},"template":{"default":"Tools/schemas/terminal_proof.template.yaml","description":"field-list template (default Tools/schemas/terminal_proof.template.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--template"]}}},"required":["proof"],"type":"object"},"name":"check_proof"},{"description":"Validate canonical Required Queue state","inputSchema":{"additionalProperties":false,"properties":{"ack_activation_phase":{"description":"return one delivered phase part nonce as same-context delivery evidence","type":"string","x-cambium-cli":{"action":"store","option_strings":["--ack-activation-phase"]}},"ack_activation_piece":{"description":"return one delivered piece nonce as same-context delivery evidence","type":"string","x-cambium-cli":{"action":"store","option_strings":["--ack-activation-piece"]}},"boundary_gate_receipt":{"default":[],"description":"current gate evidence supplied to --require-revalidation","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--boundary-gate-receipt"]}},"budget_manifest_receipt":{"description":"closed budget-manifest receipt ID supplied to --require-maintenance-complete","type":"string","x-cambium-cli":{"action":"store","option_strings":["--budget-manifest-receipt"]}},"confirmation_receipt":{"description":"confirmation evidence supplied to --require-ready","type":"string","x-cambium-cli":{"action":"store","option_strings":["--confirmation-receipt"]}},"deliver_activation_piece":{"description":"deliver one frozen activation piece of BATCH_ID inside the protocol delivery budget","type":"string","x-cambium-cli":{"action":"store","option_strings":["--deliver-activation-piece"]}},"deliver_phase":{"description":"deliver one frozen activation phase part of BATCH_ID inside the protocol delivery budget","type":"string","x-cambium-cli":{"action":"store","option_strings":["--deliver-phase"]}},"deliver_readback":{"description":"deliver one registered conditional Card read-back source for an already-open batch","type":"string","x-cambium-cli":{"action":"store","option_strings":["--deliver-readback"]}},"json":{"default":false,"description":"write this run's receipt object to stdout as one canonical JSON array and move the human report to stderr; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"ledger_advance_receipt":{"description":"Coverage Ledger advance receipt ID supplied to --require-maintenance-complete","type":"string","x-cambium-cli":{"action":"store","option_strings":["--ledger-advance-receipt"]}},"phase":{"description":"frozen activation phase selected with --deliver-phase or --ack-activation-phase","type":"string","x-cambium-cli":{"action":"store","option_strings":["--phase"]}},"phase_delivery_receipt":{"description":"delivery receipt the acknowledged phase nonce came from, supplied to --ack-activation-phase","type":"string","x-cambium-cli":{"action":"store","option_strings":["--phase-delivery-receipt"]}},"phase_nonce":{"description":"nonce returned from the delivered phase part, supplied to --ack-activation-phase","type":"string","x-cambium-cli":{"action":"store","option_strings":["--phase-nonce"]}},"phase_part":{"default":0,"description":"part index inside the selected phase (default 0)","type":"integer","x-cambium-cli":{"action":"store","option_strings":["--phase-part"],"type":"int"}},"piece":{"description":"frozen activation piece selected with --deliver-activation-piece or --ack-activation-piece","type":"string","x-cambium-cli":{"action":"store","option_strings":["--piece"]}},"piece_delivery_receipt":{"description":"delivery receipt the acknowledged nonce came from, supplied to --ack-activation-piece","type":"string","x-cambium-cli":{"action":"store","option_strings":["--piece-delivery-receipt"]}},"piece_nonce":{"description":"nonce returned from the delivered piece, supplied to --ack-activation-piece","type":"string","x-cambium-cli":{"action":"store","option_strings":["--piece-nonce"]}},"readback_rule":{"description":"registered rule selected with --deliver-readback","type":"string","x-cambium-cli":{"action":"store","option_strings":["--readback-rule"]}},"receipts":{"description":"repository-relative JSONL receipt path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"require_complete":{"default":false,"description":"build completion gate: prove no Required work remains","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--require-complete"]}},"require_maintenance_complete":{"default":false,"description":"maintenance completion gate: prove one bounded maintenance run is complete","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--require-maintenance-complete"]}},"require_ready":{"description":"prove BATCH_ID is queued and ready to activate","type":"string","x-cambium-cli":{"action":"store","option_strings":["--require-ready"]}},"require_revalidation":{"description":"prove BATCH_ID may produce its Standards revalidation aggregate","type":"string","x-cambium-cli":{"action":"store","option_strings":["--require-revalidation"]}},"resume_status":{"default":false,"description":"show interruption-safe task and batch resume state","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--resume-status"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"watermark_advance_receipt":{"description":"watermark advance receipt ID supplied to --require-maintenance-complete","type":"string","x-cambium-cli":{"action":"store","option_strings":["--watermark-advance-receipt"]}}},"required":["root"],"type":"object"},"name":"check_queue","x-cambium-mutually-exclusive":[{"dests":["require_ready","require_revalidation","require_complete","require_maintenance_complete","resume_status","deliver_readback","deliver_activation_piece","ack_activation_piece","deliver_phase","ack_activation_phase"],"required":false}]},{"description":"Find profile-configured residual content outside accepted roots.","inputSchema":{"additionalProperties":false,"properties":{"config":{"description":"profile-owned restricted YAML scan configuration","type":"string","x-cambium-cli":{"action":"store","option_strings":["--config"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human summary to stderr; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"positive_controls_only":{"default":false,"description":"execute the registered controls through the production classifier without scanning repository content","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--positive-controls-only"]}},"receipts":{"description":"optional JSONL receipt path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scan_id":{"description":"stable ID from the selected profile's scan registry","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scan-id"]}},"time_limit":{"default":55.0,"description":"hard evidence-production budget in seconds (greater than 0 and at most 55)","type":"number","x-cambium-cli":{"action":"store","option_strings":["--time-limit"],"type":"float"}},"vault_root":{"description":"knowledge-vault root to scan","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root","scan_id","config"],"type":"object"},"name":"check_residual_content"},{"description":"Validate the selected profile's Structure Registry against the vault (gate: structure-registry).","inputSchema":{"additionalProperties":false,"properties":{"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable summary to stderr; receipts written and the exit code are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile":{"description":"profile directory override; default is the selected_profile_manifest of the active Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"check_structure"},{"description":"Frontmatter controlled-vocabulary check","inputSchema":{"additionalProperties":false,"properties":{"exclude":{"default":[],"description":"subpath to exclude (repeatable; e.g. the compiled kernel/Cards artifacts, whose frontmatter is not governed by the K08 module's knowledge-page schema)","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human summary to stderr; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"policy_fingerprint":{"description":"effective-policy fingerprint (kblib.effective_priority_policy) the quotas were resolved from; recorded on the priority-quota-compliance receipt so its consumers can bind the policy identity, never re-derive it","type":"string","x-cambium-cli":{"action":"store","option_strings":["--policy-fingerprint"]}},"quota_p0":{"default":15.0,"description":"P0 priority quota in percent (default 15; kernel default; the selected profile manifest or task contract may override)","type":"number","x-cambium-cli":{"action":"store","option_strings":["--quota-p0"],"type":"float"}},"quota_p1":{"default":35.0,"description":"P1 priority quota in percent (default 35; kernel default; the selected profile manifest or task contract may override)","type":"number","x-cambium-cli":{"action":"store","option_strings":["--quota-p1"],"type":"float"}},"receipts":{"description":"JSONL path to append machine-readable receipts to","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"only scan .md files under this subpath","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"vocab":{"description":"path to vocab.yaml (defaults to vocab.yaml next to this script)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--vocab"]}}},"required":["vault_root"],"type":"object"},"name":"check_vocab"},{"description":"Compile the machine-readable CLI invocation contract from every Tools/*.py argparse declaration.","inputSchema":{"additionalProperties":false,"properties":{"check":{"default":false,"description":"recompute and compare against the existing output; exit 0 when byte-identical, 2 when it is stale or hand-edited","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"output":{"description":"artifact path to write or verify (default: /Tools/compiled/cli-contract.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"root":{"description":"repository root whose Tools/ directory is compiled","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"compile_cli_contract"},{"description":"Compile Required Queue from explicit Coverage assignments","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply a Queue write or replan","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"amendment_id":{"description":"registered Amendment id authorizing the replan; required with --apply-replan","type":"string","x-cambium-cli":{"action":"store","option_strings":["--amendment-id"]}},"apply":{"default":false,"description":"materialize an initially empty Queue","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"apply_replan":{"default":false,"description":"apply a controlled structural diff to a non-empty Queue","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply-replan"]}},"coverage_proposal":{"description":"repository-contained .cambium/deltas/replans/*.coverage.yaml input","type":"string","x-cambium-cli":{"action":"store","option_strings":["--coverage-proposal"]}},"expected_coverage_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Coverage; the replan is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-coverage-sha256"]}},"expected_progress_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Progress; the replan is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-progress-sha256"]}},"expected_queue_revision":{"description":"compare-and-swap guard: the queue_revision the caller read from the current Queue; the write is refused when the live value differs","type":"integer","x-cambium-cli":{"action":"store","option_strings":["--expected-queue-revision"],"type":"int"}},"expected_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Queue; the write is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-sha256"]}},"expected_state_revision":{"description":"compare-and-swap guard: the state_revision the caller read from the current Queue; the replan is refused when the live value differs","type":"integer","x-cambium-cli":{"action":"store","option_strings":["--expected-state-revision"],"type":"int"}},"json":{"default":false,"description":"write this run's receipt objects to stdout as one canonical JSON array and move the human-readable report to stderr; receipt writing, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"output":{"description":"repository-relative proposal path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"receipts":{"default":".cambium/receipts/queue-structure.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"replan_diff":{"description":"existing .cambium/tmp/*.yaml diff to consume","type":"string","x-cambium-cli":{"action":"store","option_strings":["--replan-diff"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"compile_queue","x-cambium-mutually-exclusive":[{"dests":["apply","apply_replan"],"required":false}]},{"description":"Compose the effective frontmatter page contract from the kernel bases and the selected profile's Metadata Contract.","inputSchema":{"additionalProperties":false,"properties":{"base":{"description":"applicability base to compile from (default: kernel/K08 Metadata and Status/applicability-base.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--base"]}},"check":{"default":false,"description":"recompute and compare against the existing output; exit 0 when byte-identical, 2 otherwise","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"output":{"description":"compiled page contract to write, or to compare against under --check (default: Tools/page_contract.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"profile":{"description":"profile directory for a validation run; the vault selection stays with K00/03","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"relationships":{"description":"relationship base to compile from (default: kernel/K08 Metadata and Status/relationship-base.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--relationships"]}},"root":{"default":".","description":"vault root (default: this repository)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--root"]}},"sources_role":{"description":"sources-role base to compile from (default: kernel/K07 Sources and Accuracy/sources-role-base.yaml under --root)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--sources-role"]}}},"type":"object"},"name":"compose_page_contract"},{"description":"Deterministically compose the vocabulary artifact from the kernel base and the selected profile's extensions.","inputSchema":{"additionalProperties":false,"properties":{"base":{"default":"kernel/K08 Metadata and Status/vocabulary-base.yaml","description":"the kernel vocabulary base the extensions are appended to (default: kernel/K08 Metadata and Status/vocabulary-base.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--base"]}},"check":{"default":false,"description":"recompute and compare against the existing output; exit 0 when values and provenance are identical, 2 otherwise","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"extensions":{"description":"the active profile's vocabulary-extensions.yaml. Canonical adopter Standards state selects the path; when this flag is present it must name that same path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--extensions"]}},"output":{"default":"Tools/vocab.yaml","description":"composed vocabulary artifact to write, or to compare against under --check (default: Tools/vocab.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}}},"type":"object"},"name":"compose_vocab"},{"description":"Cross-file duplicate paragraph candidate detection (for maintenance runs and governance tasks)","inputSchema":{"additionalProperties":false,"properties":{"exclude":{"description":"skip files whose path contains this component (repeatable; default: legacy)","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable report to stderr; receipts written, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"description":"JSONL path to append machine-readable receipts to (shared convention, Tools/schemas/receipt.template.jsonl)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"scope":{"description":"subpath (relative to vault, or absolute): only report similar pairs with at least one side under it","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"vault":{"default":".","description":"vault root directory (default: current directory)","type":"string","x-cambium-cli":{"action":"store","nargs":"?","option_strings":[]}}},"type":"object"},"name":"duplicate_check"},{"description":"Initialize empty Cambium runtime state","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"materialize .cambium/; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"at":{"description":"initial Coverage timestamp (default: current UTC)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--at"]}},"completion_semantics":{"description":"build requires completion-candidate plus Terminal Proof; maintenance closes directly through the bounded maintenance completion gate","enum":["build","maintenance"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--completion-semantics"]}},"concurrency_cap":{"description":"explicit task-contract override of K13/10's concurrency cap; omit it to take the selected profile manifest's registered override, or the kernel default 3 when the manifest registers none","type":"integer","x-cambium-cli":{"action":"store","option_strings":["--concurrency-cap"],"type":"int"}},"contract_version":{"default":"c1","description":"non-empty task-contract version recorded on the Progress Ledger contract","type":"string","x-cambium-cli":{"action":"store","option_strings":["--contract-version"]}},"exclusions":{"default":[],"description":"explicit out-of-scope item; repeatable","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"objective":{"description":"non-empty statement of the task outcome","type":"string","x-cambium-cli":{"action":"store","option_strings":["--objective"]}},"profile_manifest":{"description":"repository-relative selected profile manifest; must equal the selected_profile_manifest of the canonical adopter Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile-manifest"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"scope_version":{"description":"non-empty scope identity stamped on the Queue, Coverage Ledger and task contract","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope-version"]}},"standards_version":{"description":"Standards version this runtime adopts; must equal the approved standards_version of the canonical adopter Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--standards-version"]}},"task_id":{"description":"non-empty task identity stamped on the Queue, Coverage Ledger and Progress Ledger","type":"string","x-cambium-cli":{"action":"store","option_strings":["--task-id"]}}},"required":["root","task_id","objective","scope_version","standards_version","profile_manifest","completion_semantics"],"type":"object"},"name":"init_state"},{"description":"Compile and load Cambium's closed metadata-execution authority contract. This module is deliberately the single authority boundary between metadata declarations and executable writers. A field rule is executable only when an installed writer capability declares the same ``(field, transition, adapter)`` operation, and every installed writer operation must be authorized by exactly one rule. Unknown keys, unknown adapters, orphan implementations, and partial evidence bindings fail closed.","inputSchema":{"additionalProperties":false,"properties":{"authority":{"default":"kernel/K08 Metadata and Status/metadata-authority-base.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":["--authority"]}},"capabilities":{"default":"Tools/operation-capabilities.yaml","type":"string","x-cambium-cli":{"action":"store","option_strings":["--capabilities"]}},"check":{"default":false,"type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"output":{"default":"Tools/compiled/metadata-execution-contract.json","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"root":{"default":".","type":"string","x-cambium-cli":{"action":"store","option_strings":["--root"]}}},"type":"object"},"name":"metadata_execution_contract"},{"description":"Migrate existing runtime identity to Standards state","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"write state; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"migrate_standards_state"},{"description":"Read-only onboarding status projector: derives the adoption/onboarding state of one root and exactly one next_action token; writes nothing and owns no ledger","inputSchema":{"additionalProperties":false,"properties":{"json":{"default":false,"description":"emit the status view as one deterministic JSON object instead of the human summary","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile_id":{"description":"target one candidate profile directory name under profiles/ for the full profile-load evaluation (defaults to the single candidate when exactly one exists)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile-id"]}},"root":{"description":"the adopting repository root to project","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"profile_onboarding_status"},{"description":"Project metadata-contract owner state onto page frontmatter","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"take the runtime writer lock and publish the projection; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"page":{"description":"limit to these repository-relative pages (repeatable); default is every Ledger page","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--page"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"project_page_state"},{"description":"Record one snapshot-bound Batch Review judgment","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"append the evidence; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"batch":{"description":"exact open Queue batch ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--batch"]}},"json":{"default":false,"description":"write the applied receipt as one JSON array","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"judgment_item":{"description":"registered Batch Review Requirement Judgment Item ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--judgment-item"]}},"receipts":{"default":".cambium/receipts/batch-judgments.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"reviewer_role":{"description":"declared pass-authority Profile role ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--reviewer-role"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"statement":{"description":"bounded judgment statement (the concrete verdict, not \"reviewed\")","type":"string","x-cambium-cli":{"action":"store","option_strings":["--statement"]}},"target":{"description":"manifest page path, or the batch ID for a batch-selector requirement","type":"string","x-cambium-cli":{"action":"store","option_strings":["--target"]}}},"required":["root","batch","judgment_item","target","reviewer_role","statement"],"type":"object"},"name":"record_batch_judgment"},{"description":"Record a Profile-authorized Corpus Planning semantic decision as machine-readable JSONL","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"description":"declared authority Role ID; required with --apply and must equal the Profile/plan binding","type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"append the structural and semantic receipts; default is dry-run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"plan":{"description":"closed restricted-YAML acceptance decision plan; one .yaml file directly under .cambium/deltas/corpus-plan-acceptances/","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"receipts":{"default":".cambium/receipts/corpus-plan-acceptance.jsonl","description":"repository-relative JSONL path the receipts are appended to (default: .cambium/receipts/corpus-plan-acceptance.jsonl)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","plan"],"type":"object"},"name":"record_corpus_acceptance"},{"description":"Record snapshot-bound manual Extension Gate evidence","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"description":"declared pass-authority Profile role ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"append the evidence; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"gate_id":{"description":"exact typed Profile Extension Gate ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--gate-id"]}},"json":{"default":false,"description":"write the applied receipt as one JSON array","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"page":{"description":"repository-relative Markdown target","type":"string","x-cambium-cli":{"action":"store","option_strings":["--page"]}},"receipts":{"default":".cambium/receipts/gate-attestations.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"statement":{"description":"bounded manual attestation statement","type":"string","x-cambium-cli":{"action":"store","option_strings":["--statement"]}},"value":{"description":"requested registered completion value","type":"string","x-cambium-cli":{"action":"store","option_strings":["--value"]}}},"required":["root","gate_id","page","value","actor_role","statement"],"type":"object"},"name":"record_gate_attestation"},{"description":"Run a registered scan and record a deterministic Extension Gate result","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"run and append the bound Gate result","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"gate_id":{"description":"exact deterministic typed Profile Gate ID","type":"string","x-cambium-cli":{"action":"store","option_strings":["--gate-id"]}},"json":{"default":false,"description":"write the applied receipt as one JSON array","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"page":{"description":"repository-relative Markdown target","type":"string","x-cambium-cli":{"action":"store","option_strings":["--page"]}},"receipts":{"default":".cambium/receipts/gate-results.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","gate_id","page"],"type":"object"},"name":"record_gate_result"},{"description":"Register one approved current-protocol Amendment","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may register or withdraw an Amendment","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"amendment_id":{"description":"id for a queue-replan registration; cross-Ledger operations derive it from --plan instead","type":"string","x-cambium-cli":{"action":"store","option_strings":["--amendment-id"]}},"apply":{"default":false,"description":"write the registration; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"approval_reference":{"description":"explicit-user approval reference; required when --decision-mode is explicit-user","type":"string","x-cambium-cli":{"action":"store","option_strings":["--approval-reference"]}},"coverage_proposal":{"description":".cambium/deltas/replans/*.coverage.yaml proposal","type":"string","x-cambium-cli":{"action":"store","option_strings":["--coverage-proposal"]}},"date":{"description":"YYYY-MM-DD; must equal the UTC registration date","type":"string","x-cambium-cli":{"action":"store","option_strings":["--date"]}},"decision_mode":{"default":"auto","description":"derive delegated authority by default; explicit-user requires --approval-reference","enum":["auto","contract-delegated","explicit-user"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--decision-mode"]}},"expected_coverage_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Coverage; registration is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-coverage-sha256"]}},"expected_progress_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Progress; registration is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-progress-sha256"]}},"expected_queue_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Queue; registration is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-queue-sha256"]}},"json":{"default":false,"description":"write the published receipt to stdout as one canonical JSON array and move the human report to stderr; a dry run publishes no receipt and so writes nothing there; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"operation":{"description":"Amendment operation being registered","enum":["cancel-batch","gap-routing-reconciliation","property-state-migration","queue-replan","scope-replan"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--operation"]}},"plan":{"description":".cambium/deltas/amendments/*.yaml plan","type":"string","x-cambium-cli":{"action":"store","option_strings":["--plan"]}},"reason":{"description":"nonempty withdrawal reason recorded on the row and its receipt","type":"string","x-cambium-cli":{"action":"store","option_strings":["--reason"]}},"receipts":{"default":".cambium/receipts/amendments.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"summary":{"description":"non-empty one-line rationale recorded on the row","type":"string","x-cambium-cli":{"action":"store","option_strings":["--summary"]}},"withdraw":{"description":"retire the named pending registration instead of registering one (K13/06 withdrawal); requires --reason","type":"string","x-cambium-cli":{"action":"store","option_strings":["--withdraw"]}}},"required":["root","expected_coverage_sha256","expected_progress_sha256","expected_queue_sha256"],"type":"object"},"name":"register_amendment"},{"description":"Render the K08/09 boundary projection blocks from page `boundary` frontmatter.","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"rewrite the stale owned blocks atomically; omit to only report what would render","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"check":{"default":false,"description":"exit 2 when any owned block is stale; the default report never fails on staleness","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"contract":{"default":"Tools/page_contract.yaml","description":"compiled contract path (default Tools/page_contract.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--contract"]}},"profile":{"description":"profile directory override; default is the selected_profile_manifest of the active Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"scope":{"description":"only scan .md files under this subpath","type":"string","x-cambium-cli":{"action":"store","option_strings":["--scope"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"render_boundary_projection"},{"description":"Render the Cambium MCP server's registration and corpus binding into the configuration file each supported host reads.","inputSchema":{"additionalProperties":false,"properties":{"check":{"default":false,"description":"re-render and compare against the existing products; exit 0 when byte-identical, 2 when one is stale or hand-edited","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"distribution_root":{"description":"absolute path of the Cambium checkout the server is launched from; substituted for (default: leave the placeholder)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--distribution-root"]}},"host":{"description":"render only this host's product (default: every host)","enum":["claude-code","codex","dsh-env","dsh-profile-patch","kimi-code"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--host"]}},"output_dir":{"description":"directory to write or verify the products in (default: /Tools/compiled/host-configs)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output-dir"]}},"projection":{"description":"compiled interface projection to bind to (default: /Tools/compiled/mcp-tools.json)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--projection"]}},"root":{"description":"repository root holding the compiled interface projection","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"sources":{"default":false,"description":"print the declaration source of every rendered field and exit without reading or writing any product","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--sources"]}},"workspace_root":{"description":"absolute path of the corpus repository this registration is bound to; substituted for (default: leave the placeholder)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--workspace-root"]}}},"required":["root"],"type":"object"},"name":"render_host_configs","x-cambium-mutually-exclusive":[{"dests":["check","sources"],"required":false}]},{"description":"Project the compiled CLI invocation contract into the agent-facing interface forms registered in this tool.","inputSchema":{"additionalProperties":false,"properties":{"check":{"default":false,"description":"recompute and compare against the existing artifacts; exit 0 when byte-identical, 2 when one is stale or hand-edited","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"contract":{"description":"compiled CLI contract to project (default: /Tools/compiled/cli-contract.yaml)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--contract"]}},"form":{"description":"project only this form (default: every registered form)","enum":["mcp"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--form"]}},"output":{"description":"artifact path to write or verify; requires --form, because one path cannot hold two forms","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"root":{"description":"repository root holding the compiled CLI contract","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"sources":{"default":false,"description":"print the declaration source of every projected field and exit without reading or writing any artifact","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--sources"]}}},"required":["root"],"type":"object"},"name":"render_interface_projection","x-cambium-mutually-exclusive":[{"dests":["check","sources"],"required":false}]},{"description":"Render Required Queue human report","inputSchema":{"additionalProperties":false,"properties":{"check":{"default":false,"description":"compare existing report instead of writing","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"output":{"default":".cambium/reports/required_queue.md","description":"repository-relative report path","type":"string","x-cambium-cli":{"action":"store","option_strings":["--output"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"stdout":{"default":false,"description":"print the report to stdout and write nothing","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--stdout"]}}},"required":["root"],"type":"object"},"name":"render_queue"},{"description":"Render derived Structure Registry coverage projections (K01/05 derived roles).","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"rewrite the stale owned blocks atomically; omit to only report what would render","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"check":{"default":false,"description":"exit 2 when any owned block is stale or missing; the default report never fails on staleness","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"profile":{"description":"profile directory override; default is the selected_profile_manifest of the active Standards state","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"vault_root":{"description":"vault root directory","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["vault_root"],"type":"object"},"name":"render_structure_projection"},{"description":"Run the adopter verification set derived from the K00/12 Stable Gate ID Registry (deterministic, not-batch-scoped producers).","inputSchema":{"additionalProperties":false,"properties":{"exclude":{"default":[],"description":"path prefix passed through to scanners that accept it (repeatable)","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--exclude"]}},"list":{"default":false,"description":"print the derived set and each command without running anything","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--list"]}},"profile":{"description":"profile directory override; default is the live runtime's selected_profile_manifest","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile"]}},"root":{"description":"repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root"],"type":"object"},"name":"run_gates"},{"description":"Scaffold a candidate profile from profiles/_template using the exact-copy whitelist in profiles/template-files.yaml","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"create the candidate; without it the plan is reported and nothing is written","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"emit the plan/result as one JSON document","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"profile_id":{"description":"candidate profile slug matching [a-z0-9][a-z0-9_-]* (equals the directory name)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--profile-id"]}},"root":{"description":"repository root containing profiles/","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}}},"required":["root","profile_id"],"type":"object"},"name":"scaffold_profile"},{"description":"Seal verified frozen receipt history (K12/07). --apply is a maintenance-window operation: run it only with no other Cambium or adopter writer, checker or receipt appender active against this repository.","inputSchema":{"additionalProperties":false,"properties":{"apply":{"default":false,"description":"write the seal, or with --reconcile finish the interrupted one; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"json":{"default":false,"description":"write the receipts this run produced to stdout as one canonical JSON array and move the human-readable report to stderr; receipts written, verdicts, and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"receipts":{"default":".cambium/receipts/seal-receipts.jsonl","description":"repository-relative JSONL path for this tool's own seal receipts, which never seal (default: .cambium/receipts/seal-receipts.jsonl)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"reconcile":{"default":false,"description":"finish an interrupted seal over the publication paths this tool implements; other interruptions fail closed and are resolved by the runbook in Tools/README.md","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--reconcile"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"verify":{"default":false,"description":"re-prove every sealed segment, projection and seal-receipt binding, then exit","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--verify"]}}},"required":["root"],"type":"object"},"name":"seal_receipts"},{"description":"Stamp kernel Runtime Cards","inputSchema":{"additionalProperties":false,"properties":{"acknowledge_compiled":{"default":false,"description":"after semantic regeneration/review, advance compiled_source_hash to the exact current source digest","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--acknowledge-compiled"]}},"cards_dir":{"default":"kernel/Cards","description":"Card directory relative to (default: kernel/Cards)","type":"string","x-cambium-cli":{"action":"store","option_strings":["--cards-dir"]}},"check":{"default":false,"description":"verify only; never write","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--check"]}},"root":{"description":"repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"set_version":{"description":"also set every card's compiled_from value","type":"string","x-cambium-cli":{"action":"store","option_strings":["--set-version"]}}},"required":["root"],"type":"object"},"name":"stamp_cards"},{"description":"Apply one Required Queue transition","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; Queue transition planning and apply both require integrator","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the transition; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"at":{"description":"transition timestamp; defaults to now in UTC","type":"string","x-cambium-cli":{"action":"store","option_strings":["--at"]}},"batch_receipt":{"default":[],"description":"batch-review gate receipt id for open -> merge-ready; exactly one is accepted","items":{"type":"string"},"type":"array","x-cambium-cli":{"action":"append","option_strings":["--batch-receipt"]}},"close_gate_receipt":{"description":"check_batch_close receipt id required by the closed transition","type":"string","x-cambium-cli":{"action":"store","option_strings":["--close-gate-receipt"]}},"confirmation_receipt":{"description":"confirmation receipt id required by queued -> open when the batch is confirmation_required","type":"string","x-cambium-cli":{"action":"store","option_strings":["--confirmation-receipt"]}},"delta_apply_receipt":{"description":"apply_delta receipt id required by the closed transition and by merge-ready -> open reopen","type":"string","x-cambium-cli":{"action":"store","option_strings":["--delta-apply-receipt"]}},"delta_path":{"description":"repository-relative .cambium/deltas/.yaml batch delta required by open -> merge-ready","type":"string","x-cambium-cli":{"action":"store","option_strings":["--delta-path"]}},"expected_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Queue; the write is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-sha256"]}},"expected_state_revision":{"description":"compare-and-swap guard: the state_revision the caller read from the current Queue; the write is refused when the live value differs","type":"integer","x-cambium-cli":{"action":"store","option_strings":["--expected-state-revision"],"type":"int"}},"gate_receipt":{"description":"gate receipt id: activation gate for queued -> open, Queue consistency gate for closed and for clearing revalidation-required","type":"string","x-cambium-cli":{"action":"store","option_strings":["--gate-receipt"]}},"hold_state":{"description":"target hold state; exclusive with --transition","enum":["blocked","confirmation-required","none","paused","revalidation-required"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--hold-state"]}},"id":{"description":"Required Queue batch id to transition","type":"string","x-cambium-cli":{"action":"store","option_strings":["--id"]}},"json":{"default":false,"description":"write the applied transition receipt(s) to stdout as one canonical JSON array and move the human report to stderr; a dry run publishes no receipt and so writes nothing there; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"reason":{"description":"non-empty rationale required by merge-ready -> open and by any non-none hold","type":"string","x-cambium-cli":{"action":"store","option_strings":["--reason"]}},"receipts":{"default":".cambium/receipts/queue-transitions.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"standards_revalidation_receipt":{"description":"check_queue --require-revalidation receipt discharging an outstanding Standards revalidation; queued -> open or revalidation-required -> none only","type":"string","x-cambium-cli":{"action":"store","option_strings":["--standards-revalidation-receipt"]}},"transition":{"description":"target lifecycle state; exclusive with --hold-state","enum":["closed","merge-ready","open"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--transition"]}}},"required":["root","id"],"type":"object"},"name":"update_queue","x-cambium-mutually-exclusive":[{"dests":["transition","hold_state"],"required":true}]},{"description":"Apply one canonical task-state transition","inputSchema":{"additionalProperties":false,"properties":{"actor_role":{"default":"worker","description":"declared caller role; only integrator may apply a task-state write","enum":["integrator","worker"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--actor-role"]}},"apply":{"default":false,"description":"write the transition; omit for a dry run","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--apply"]}},"at":{"description":"transition timestamp; defaults to now in UTC","type":"string","x-cambium-cli":{"action":"store","option_strings":["--at"]}},"checkpoint_summary":{"description":"non-empty reason required by paused, blocked and cancelled, and when leaving completion-candidate for anything but complete","type":"string","x-cambium-cli":{"action":"store","option_strings":["--checkpoint-summary"]}},"expected_progress_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Progress; --apply is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-progress-sha256"]}},"expected_queue_sha256":{"description":"compare-and-swap guard: sha256: the caller read from the current Queue; --apply is refused when the live bytes differ","type":"string","x-cambium-cli":{"action":"store","option_strings":["--expected-queue-sha256"]}},"json":{"default":false,"description":"write the applied transition receipt to stdout as one canonical JSON array and move the human report to stderr; a dry run publishes no receipt and so writes nothing there; receipt writing and exit codes are unchanged","type":"boolean","x-cambium-cli":{"action":"store_true","nargs":0,"option_strings":["--json"]}},"maintenance_completion_receipt":{"description":"maintenance completion gate receipt id required by complete under maintenance completion_semantics","type":"string","x-cambium-cli":{"action":"store","option_strings":["--maintenance-completion-receipt"]}},"queue_check_receipt":{"description":"Queue completion gate receipt id required by the completion-candidate transition","type":"string","x-cambium-cli":{"action":"store","option_strings":["--queue-check-receipt"]}},"receipts":{"default":".cambium/receipts/task-transitions.jsonl","description":"receipt JSONL path under .cambium/receipts","type":"string","x-cambium-cli":{"action":"store","option_strings":["--receipts"]}},"root":{"description":"adopting repository root","type":"string","x-cambium-cli":{"action":"store","option_strings":[]}},"terminal_proof_receipt":{"description":"Terminal Proof receipt id required by complete under build completion_semantics","type":"string","x-cambium-cli":{"action":"store","option_strings":["--terminal-proof-receipt"]}},"transition":{"description":"target task state in the Progress Ledger","enum":["active","blocked","cancelled","complete","completion-candidate","paused"],"type":"string","x-cambium-cli":{"action":"store","option_strings":["--transition"]}}},"required":["root","transition"],"type":"object"},"name":"update_task"}],"transports":["stdio","streamable-http"]} diff --git a/Tools/compiled/metadata-execution-contract.json b/Tools/compiled/metadata-execution-contract.json index c562ec5..e2c9e99 100644 --- a/Tools/compiled/metadata-execution-contract.json +++ b/Tools/compiled/metadata-execution-contract.json @@ -1 +1 @@ -{"artifact":"metadata-execution-contract","capability_implementations":[{"path":"Tools/apply_amendment.py","sha256":"sha256:d541f4de5caa0b55c68817c406c820de856a675b030a716eaab10e47f3fad4d8"},{"path":"Tools/apply_delta.py","sha256":"sha256:3749db54ecc0d713c657eb32d1fe52011d65eb64e3a4c4938430344bcfe957d2"},{"path":"Tools/apply_metadata_transition.py","sha256":"sha256:71d687f1a2afb4006dc19b90bcb27e886ca46ce6e577d294802925523e7ae0cd"},{"path":"Tools/apply_task_plan.py","sha256":"sha256:99b47d8dfc2366098ebb3f7d285dec2bc84c0c834c39efea3b846a06b0a36f5d"},{"path":"Tools/card_activation.py","sha256":"sha256:dde8c9a0a15620ade6935b249b6e1edce57e4331e65a8dd76d48b7fda7c9dfd7"},{"path":"Tools/check_batch_close.py","sha256":"sha256:bc2326400a6dde7863fd1384382475ea98fa78592cd0b67d84e3c817b5bf4d16"},{"path":"Tools/check_queue.py","sha256":"sha256:4ec7f2dc3727c35688ec89105a396d4421ae52568b14e8b7db7c373b870f7904"},{"path":"Tools/mcp_server.py","sha256":"sha256:667e6f983cdc702dce32a7ea1269d7f83de33cd253844221f5b045ebbc1c51fc"},{"path":"Tools/metadata_gate_runtime.py","sha256":"sha256:da4aebb718dcbb37f31116c25e6cee3e374fa1e0a3edb87ab96eac6106ab22a3"},{"path":"Tools/metadata_property_state.py","sha256":"sha256:9fa07bf32b366a0bc1797006485b78f4d614b60c97f8b05c0e3dfa1c16ba2d43"},{"path":"Tools/project_page_state.py","sha256":"sha256:77c500cfbb0435f78908f8ab680f3fa4858c2c4d54cb90ce53e5870ddcfa3de4"},{"path":"Tools/record_gate_attestation.py","sha256":"sha256:73e8ad584a4c8e77f3510c09666496c2c7f2a2dd4b24b8394d6f41f9b9a81e3e"},{"path":"Tools/record_gate_result.py","sha256":"sha256:6111c6ff8bd5bf28fdb659cc891db318c314bd878cc9b75d86c6e2b9a97ed8d0"},{"path":"Tools/register_amendment.py","sha256":"sha256:917e0df2c028908b752e58894b61237807778e169e8e452d96d70458d0317fdc"},{"path":"Tools/update_queue.py","sha256":"sha256:f691748b42ac0252cc7ecf948af01f593845242e2dc28f2ad462977f426a564f"}],"contract_fingerprint":"sha256:20146bb9451ce32a83b7d248544024f80ce66295c2c0c8755cef0a55956c9ef4","contract_id":"kernel-metadata-execution","field_rules":[{"authority_class":"ledger-projection","canonical_owner":"coverage-ledger.pages[].authoring_status","evidence_requirement":null,"field":"authoring_status","invalidation_rule":"owner-value-change-v1","reconcile_policy":"existing-copy-exact-or-remove-v1","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection","value_shape":"scalar-string-or-null","write_timing":"batch-close-after-owner-update","writer_capability":"project-page-state-v2"},{"authority_class":"ledger-projection","canonical_owner":"coverage-ledger.pages[].coverage_disposition","evidence_requirement":null,"field":"coverage_disposition","invalidation_rule":"owner-value-change-v1","reconcile_policy":"existing-copy-exact-or-remove-v1","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection","value_shape":"scalar-string-or-null","write_timing":"batch-close-after-owner-update","writer_capability":"project-page-state-v2"},{"authority_class":"ledger-projection","canonical_owner":"coverage-ledger.pages[].property_state.last_content_modified","evidence_requirement":null,"field":"last_content_modified","invalidation_rule":"owner-property-state-change-v1","reconcile_policy":"upsert-exact-or-remove-v1","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection","value_shape":"date","write_timing":"after-owner-state-transition","writer_capability":"project-page-state-v2"},{"authority_class":"evidence-projection","canonical_owner":"coverage-ledger.pages[].property_state.last_content_modified","evidence_requirement":{"change_scope":"semantic-content","content_binding":"after-page-content-sha256","excluded_change_classes":["projection-only","tool-controlled-metadata-only"],"invalidation":"current-content-fingerprint","protocol":"semantic-content-change-v1","result":"pass","target_binding":"exact-page-path","value_selector":"accepted-at-utc-date"},"field":"last_content_modified","invalidation_rule":"superseded-by-later-semantic-content-change-v1","reconcile_policy":"upsert-owner-property-state-v1","source_adapter":"content-change-event-v1","transition":"semantic-content-change","value_shape":"date","write_timing":"semantic-content-acceptance","writer_capability":"metadata-transition-integrator-v1"},{"authority_class":"ledger-projection","canonical_owner":"coverage-ledger.pages[].property_state.last_reviewed","evidence_requirement":null,"field":"last_reviewed","invalidation_rule":"semantic-content-change-tombstone-v1","reconcile_policy":"upsert-exact-or-remove-v1","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection","value_shape":"date","write_timing":"after-owner-state-transition","writer_capability":"project-page-state-v2"},{"authority_class":"evidence-projection","canonical_owner":"coverage-ledger.pages[].property_state.last_reviewed","evidence_requirement":{"change_scope":"reviewed-content","content_binding":"exact-page-content-sha256","excluded_change_classes":[],"invalidation":"invalidated-by-null","protocol":"current-page-review-v1","result":"pass","target_binding":"exact-page-path","value_selector":"checked-at-utc-date"},"field":"last_reviewed","invalidation_rule":"superseded-by-review-or-semantic-content-change-v1","reconcile_policy":"upsert-owner-property-state-v1","source_adapter":"current-review-receipt-value-v1","transition":"review-completed","value_shape":"date","write_timing":"review-evidence-acceptance","writer_capability":"metadata-transition-integrator-v1"},{"authority_class":"evidence-projection","canonical_owner":"coverage-ledger.pages[].property_state.last_reviewed","evidence_requirement":{"change_scope":"semantic-content","content_binding":"after-page-content-sha256","excluded_change_classes":["projection-only","tool-controlled-metadata-only"],"invalidation":"current-content-fingerprint","protocol":"semantic-content-change-v1","result":"pass","target_binding":"exact-page-path","value_selector":"tombstone-null"},"field":"last_reviewed","invalidation_rule":"semantic-content-change-tombstone-v1","reconcile_policy":"tombstone-owner-property-state-v1","source_adapter":"content-change-event-v1","transition":"semantic-content-change","value_shape":"date","write_timing":"semantic-content-acceptance","writer_capability":"metadata-transition-integrator-v1"},{"authority_class":"ledger-projection","canonical_owner":"coverage-ledger.pages[].next_batch","evidence_requirement":null,"field":"next_batch","invalidation_rule":"owner-value-change-v1","reconcile_policy":"existing-copy-exact-or-remove-v1","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection","value_shape":"scalar-string-or-null","write_timing":"batch-close-after-owner-update","writer_capability":"project-page-state-v2"}],"operation_capabilities":[{"capability_id":"metadata-transition-integrator-v1","capability_version":"1.0.0","implementation_paths":["Tools/apply_metadata_transition.py","Tools/metadata_property_state.py"],"kind":"consumer","operations":[{"operation":"typed-field-metadata-transition"}]},{"capability_id":"card-context-delivery-v1","capability_version":"1.0.2","implementation_paths":["Tools/card_activation.py","Tools/check_queue.py","Tools/mcp_server.py","Tools/update_queue.py"],"kind":"producer","operations":[]},{"capability_id":"manual-attestation-v1","capability_version":"1.0.0","implementation_paths":["Tools/record_gate_attestation.py"],"kind":"producer","operations":[]},{"capability_id":"registered-scan-v1","capability_version":"1.0.0","implementation_paths":["Tools/record_gate_result.py"],"kind":"producer","operations":[]},{"capability_id":"deterministic-gate-result-v1","capability_version":"1.0.0","implementation_paths":["Tools/metadata_gate_runtime.py"],"kind":"receipt-schema","operations":[]},{"capability_id":"manual-gate-attestation-v1","capability_version":"1.0.0","implementation_paths":["Tools/metadata_gate_runtime.py"],"kind":"receipt-schema","operations":[]},{"capability_id":"legacy-property-adoption-v1","capability_version":"1.0.0","implementation_paths":["Tools/apply_amendment.py","Tools/apply_task_plan.py","Tools/metadata_property_state.py","Tools/project_page_state.py","Tools/register_amendment.py"],"kind":"writer","operations":[{"operation":"legacy-property-adoption-v1"}]},{"capability_id":"metadata-transition-integrator-v1","capability_version":"1.0.0","implementation_paths":["Tools/apply_delta.py","Tools/apply_metadata_transition.py","Tools/check_batch_close.py","Tools/metadata_property_state.py","Tools/update_queue.py"],"kind":"writer","operations":[{"field":"last_content_modified","source_adapter":"content-change-event-v1","transition":"semantic-content-change"},{"field":"last_reviewed","source_adapter":"content-change-event-v1","transition":"semantic-content-change"},{"field":"last_reviewed","source_adapter":"current-review-receipt-value-v1","transition":"review-completed"}]},{"capability_id":"project-page-state-v2","capability_version":"2.0.0","implementation_paths":["Tools/metadata_property_state.py","Tools/project_page_state.py"],"kind":"writer","operations":[{"field":"authoring_status","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"field":"coverage_disposition","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"field":"last_content_modified","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection"},{"field":"last_reviewed","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection"},{"field":"next_batch","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"operation":"profile-extension-enum-owner-projection-v1"}]}],"schema_version":1,"source_adapters":[{"adapter_id":"content-change-event-v1","authority_class":"evidence-projection","evidence_required":true,"owner_record_keys":[]},{"adapter_id":"coverage-property-state-v1","authority_class":"ledger-projection","evidence_required":false,"owner_record_keys":["content_fingerprint","evidence_receipt","value"]},{"adapter_id":"coverage-row-value-v1","authority_class":"ledger-projection","evidence_required":false,"owner_record_keys":[]},{"adapter_id":"current-review-receipt-value-v1","authority_class":"evidence-projection","evidence_required":true,"owner_record_keys":[]}],"temporal_order":["first_seen","last_content_modified","last_reviewed","last_verified"],"writer_capabilities":[{"capability_id":"legacy-property-adoption-v1","capability_version":"1.0.0","implementation_paths":["Tools/apply_amendment.py","Tools/apply_task_plan.py","Tools/metadata_property_state.py","Tools/project_page_state.py","Tools/register_amendment.py"],"kind":"writer","operations":[{"operation":"legacy-property-adoption-v1"}]},{"capability_id":"metadata-transition-integrator-v1","capability_version":"1.0.0","implementation_paths":["Tools/apply_delta.py","Tools/apply_metadata_transition.py","Tools/check_batch_close.py","Tools/metadata_property_state.py","Tools/update_queue.py"],"kind":"writer","operations":[{"field":"last_content_modified","source_adapter":"content-change-event-v1","transition":"semantic-content-change"},{"field":"last_reviewed","source_adapter":"content-change-event-v1","transition":"semantic-content-change"},{"field":"last_reviewed","source_adapter":"current-review-receipt-value-v1","transition":"review-completed"}]},{"capability_id":"project-page-state-v2","capability_version":"2.0.0","implementation_paths":["Tools/metadata_property_state.py","Tools/project_page_state.py"],"kind":"writer","operations":[{"field":"authoring_status","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"field":"coverage_disposition","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"field":"last_content_modified","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection"},{"field":"last_reviewed","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection"},{"field":"next_batch","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"operation":"profile-extension-enum-owner-projection-v1"}]}]} +{"artifact":"metadata-execution-contract","capability_implementations":[{"path":"Tools/apply_amendment.py","sha256":"sha256:d541f4de5caa0b55c68817c406c820de856a675b030a716eaab10e47f3fad4d8"},{"path":"Tools/apply_delta.py","sha256":"sha256:3749db54ecc0d713c657eb32d1fe52011d65eb64e3a4c4938430344bcfe957d2"},{"path":"Tools/apply_metadata_transition.py","sha256":"sha256:71d687f1a2afb4006dc19b90bcb27e886ca46ce6e577d294802925523e7ae0cd"},{"path":"Tools/apply_task_plan.py","sha256":"sha256:99b47d8dfc2366098ebb3f7d285dec2bc84c0c834c39efea3b846a06b0a36f5d"},{"path":"Tools/card_activation.py","sha256":"sha256:25f80fb1bed4e3348722e72a260180ba1f5e4d036069a806f2e6c3d014559f44"},{"path":"Tools/check_batch_close.py","sha256":"sha256:bc2326400a6dde7863fd1384382475ea98fa78592cd0b67d84e3c817b5bf4d16"},{"path":"Tools/check_queue.py","sha256":"sha256:3467bec37aa3c7be3cb6df0e7d5f5400d6cbde8a2da3b96cc38fdc44b416a2e0"},{"path":"Tools/mcp_server.py","sha256":"sha256:667e6f983cdc702dce32a7ea1269d7f83de33cd253844221f5b045ebbc1c51fc"},{"path":"Tools/metadata_gate_runtime.py","sha256":"sha256:da4aebb718dcbb37f31116c25e6cee3e374fa1e0a3edb87ab96eac6106ab22a3"},{"path":"Tools/metadata_property_state.py","sha256":"sha256:9fa07bf32b366a0bc1797006485b78f4d614b60c97f8b05c0e3dfa1c16ba2d43"},{"path":"Tools/project_page_state.py","sha256":"sha256:77c500cfbb0435f78908f8ab680f3fa4858c2c4d54cb90ce53e5870ddcfa3de4"},{"path":"Tools/record_batch_judgment.py","sha256":"sha256:33d65be54777d0f6b4abf2f9b1d76ac0bbea5eb51d416f6782fb5111c529b7e2"},{"path":"Tools/record_gate_attestation.py","sha256":"sha256:73e8ad584a4c8e77f3510c09666496c2c7f2a2dd4b24b8394d6f41f9b9a81e3e"},{"path":"Tools/record_gate_result.py","sha256":"sha256:6111c6ff8bd5bf28fdb659cc891db318c314bd878cc9b75d86c6e2b9a97ed8d0"},{"path":"Tools/register_amendment.py","sha256":"sha256:917e0df2c028908b752e58894b61237807778e169e8e452d96d70458d0317fdc"},{"path":"Tools/update_queue.py","sha256":"sha256:87aa7219da2ff93d1024062b0e605e0a308f63342a92b9beb49ccd0268ff2a01"},{"path":"Tools/update_task.py","sha256":"sha256:35bd0045eb56f50de497e61df1f7aa481178a3bf831b18f72d829b873232bdfe"}],"contract_fingerprint":"sha256:68a199efd5fdb9667943904e81ca639b4b59c2a21dd77563eefff4eca8bb18c5","contract_id":"kernel-metadata-execution","field_rules":[{"authority_class":"ledger-projection","canonical_owner":"coverage-ledger.pages[].authoring_status","evidence_requirement":null,"field":"authoring_status","invalidation_rule":"owner-value-change-v1","reconcile_policy":"existing-copy-exact-or-remove-v1","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection","value_shape":"scalar-string-or-null","write_timing":"batch-close-after-owner-update","writer_capability":"project-page-state-v2"},{"authority_class":"ledger-projection","canonical_owner":"coverage-ledger.pages[].coverage_disposition","evidence_requirement":null,"field":"coverage_disposition","invalidation_rule":"owner-value-change-v1","reconcile_policy":"existing-copy-exact-or-remove-v1","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection","value_shape":"scalar-string-or-null","write_timing":"batch-close-after-owner-update","writer_capability":"project-page-state-v2"},{"authority_class":"ledger-projection","canonical_owner":"coverage-ledger.pages[].property_state.last_content_modified","evidence_requirement":null,"field":"last_content_modified","invalidation_rule":"owner-property-state-change-v1","reconcile_policy":"upsert-exact-or-remove-v1","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection","value_shape":"date","write_timing":"after-owner-state-transition","writer_capability":"project-page-state-v2"},{"authority_class":"evidence-projection","canonical_owner":"coverage-ledger.pages[].property_state.last_content_modified","evidence_requirement":{"change_scope":"semantic-content","content_binding":"after-page-content-sha256","excluded_change_classes":["projection-only","tool-controlled-metadata-only"],"invalidation":"current-content-fingerprint","protocol":"semantic-content-change-v1","result":"pass","target_binding":"exact-page-path","value_selector":"accepted-at-utc-date"},"field":"last_content_modified","invalidation_rule":"superseded-by-later-semantic-content-change-v1","reconcile_policy":"upsert-owner-property-state-v1","source_adapter":"content-change-event-v1","transition":"semantic-content-change","value_shape":"date","write_timing":"semantic-content-acceptance","writer_capability":"metadata-transition-integrator-v1"},{"authority_class":"ledger-projection","canonical_owner":"coverage-ledger.pages[].property_state.last_reviewed","evidence_requirement":null,"field":"last_reviewed","invalidation_rule":"semantic-content-change-tombstone-v1","reconcile_policy":"upsert-exact-or-remove-v1","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection","value_shape":"date","write_timing":"after-owner-state-transition","writer_capability":"project-page-state-v2"},{"authority_class":"evidence-projection","canonical_owner":"coverage-ledger.pages[].property_state.last_reviewed","evidence_requirement":{"change_scope":"reviewed-content","content_binding":"exact-page-content-sha256","excluded_change_classes":[],"invalidation":"invalidated-by-null","protocol":"current-page-review-v1","result":"pass","target_binding":"exact-page-path","value_selector":"checked-at-utc-date"},"field":"last_reviewed","invalidation_rule":"superseded-by-review-or-semantic-content-change-v1","reconcile_policy":"upsert-owner-property-state-v1","source_adapter":"current-review-receipt-value-v1","transition":"review-completed","value_shape":"date","write_timing":"review-evidence-acceptance","writer_capability":"metadata-transition-integrator-v1"},{"authority_class":"evidence-projection","canonical_owner":"coverage-ledger.pages[].property_state.last_reviewed","evidence_requirement":{"change_scope":"semantic-content","content_binding":"after-page-content-sha256","excluded_change_classes":["projection-only","tool-controlled-metadata-only"],"invalidation":"current-content-fingerprint","protocol":"semantic-content-change-v1","result":"pass","target_binding":"exact-page-path","value_selector":"tombstone-null"},"field":"last_reviewed","invalidation_rule":"semantic-content-change-tombstone-v1","reconcile_policy":"tombstone-owner-property-state-v1","source_adapter":"content-change-event-v1","transition":"semantic-content-change","value_shape":"date","write_timing":"semantic-content-acceptance","writer_capability":"metadata-transition-integrator-v1"},{"authority_class":"ledger-projection","canonical_owner":"coverage-ledger.pages[].next_batch","evidence_requirement":null,"field":"next_batch","invalidation_rule":"owner-value-change-v1","reconcile_policy":"existing-copy-exact-or-remove-v1","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection","value_shape":"scalar-string-or-null","write_timing":"batch-close-after-owner-update","writer_capability":"project-page-state-v2"}],"operation_capabilities":[{"capability_id":"metadata-transition-integrator-v1","capability_version":"1.0.0","implementation_paths":["Tools/apply_metadata_transition.py","Tools/metadata_property_state.py"],"kind":"consumer","operations":[{"operation":"typed-field-metadata-transition"}]},{"capability_id":"phase-delivery-consumer-v1","capability_version":"1.0.0","implementation_paths":["Tools/check_queue.py","Tools/record_batch_judgment.py","Tools/update_queue.py","Tools/update_task.py"],"kind":"consumer","operations":[]},{"capability_id":"card-context-delivery-v1","capability_version":"1.0.3","implementation_paths":["Tools/card_activation.py","Tools/check_queue.py","Tools/mcp_server.py","Tools/update_queue.py"],"kind":"producer","operations":[]},{"capability_id":"manual-attestation-v1","capability_version":"1.0.0","implementation_paths":["Tools/record_gate_attestation.py"],"kind":"producer","operations":[]},{"capability_id":"registered-scan-v1","capability_version":"1.0.0","implementation_paths":["Tools/record_gate_result.py"],"kind":"producer","operations":[]},{"capability_id":"deterministic-gate-result-v1","capability_version":"1.0.0","implementation_paths":["Tools/metadata_gate_runtime.py"],"kind":"receipt-schema","operations":[]},{"capability_id":"manual-gate-attestation-v1","capability_version":"1.0.0","implementation_paths":["Tools/metadata_gate_runtime.py"],"kind":"receipt-schema","operations":[]},{"capability_id":"legacy-property-adoption-v1","capability_version":"1.0.0","implementation_paths":["Tools/apply_amendment.py","Tools/apply_task_plan.py","Tools/metadata_property_state.py","Tools/project_page_state.py","Tools/register_amendment.py"],"kind":"writer","operations":[{"operation":"legacy-property-adoption-v1"}]},{"capability_id":"metadata-transition-integrator-v1","capability_version":"1.0.0","implementation_paths":["Tools/apply_delta.py","Tools/apply_metadata_transition.py","Tools/check_batch_close.py","Tools/metadata_property_state.py","Tools/update_queue.py"],"kind":"writer","operations":[{"field":"last_content_modified","source_adapter":"content-change-event-v1","transition":"semantic-content-change"},{"field":"last_reviewed","source_adapter":"content-change-event-v1","transition":"semantic-content-change"},{"field":"last_reviewed","source_adapter":"current-review-receipt-value-v1","transition":"review-completed"}]},{"capability_id":"project-page-state-v2","capability_version":"2.0.0","implementation_paths":["Tools/metadata_property_state.py","Tools/project_page_state.py"],"kind":"writer","operations":[{"field":"authoring_status","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"field":"coverage_disposition","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"field":"last_content_modified","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection"},{"field":"last_reviewed","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection"},{"field":"next_batch","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"operation":"profile-extension-enum-owner-projection-v1"}]}],"schema_version":1,"source_adapters":[{"adapter_id":"content-change-event-v1","authority_class":"evidence-projection","evidence_required":true,"owner_record_keys":[]},{"adapter_id":"coverage-property-state-v1","authority_class":"ledger-projection","evidence_required":false,"owner_record_keys":["content_fingerprint","evidence_receipt","value"]},{"adapter_id":"coverage-row-value-v1","authority_class":"ledger-projection","evidence_required":false,"owner_record_keys":[]},{"adapter_id":"current-review-receipt-value-v1","authority_class":"evidence-projection","evidence_required":true,"owner_record_keys":[]}],"temporal_order":["first_seen","last_content_modified","last_reviewed","last_verified"],"writer_capabilities":[{"capability_id":"legacy-property-adoption-v1","capability_version":"1.0.0","implementation_paths":["Tools/apply_amendment.py","Tools/apply_task_plan.py","Tools/metadata_property_state.py","Tools/project_page_state.py","Tools/register_amendment.py"],"kind":"writer","operations":[{"operation":"legacy-property-adoption-v1"}]},{"capability_id":"metadata-transition-integrator-v1","capability_version":"1.0.0","implementation_paths":["Tools/apply_delta.py","Tools/apply_metadata_transition.py","Tools/check_batch_close.py","Tools/metadata_property_state.py","Tools/update_queue.py"],"kind":"writer","operations":[{"field":"last_content_modified","source_adapter":"content-change-event-v1","transition":"semantic-content-change"},{"field":"last_reviewed","source_adapter":"content-change-event-v1","transition":"semantic-content-change"},{"field":"last_reviewed","source_adapter":"current-review-receipt-value-v1","transition":"review-completed"}]},{"capability_id":"project-page-state-v2","capability_version":"2.0.0","implementation_paths":["Tools/metadata_property_state.py","Tools/project_page_state.py"],"kind":"writer","operations":[{"field":"authoring_status","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"field":"coverage_disposition","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"field":"last_content_modified","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection"},{"field":"last_reviewed","source_adapter":"coverage-property-state-v1","transition":"owner-to-page-projection"},{"field":"next_batch","source_adapter":"coverage-row-value-v1","transition":"owner-to-page-projection"},{"operation":"profile-extension-enum-owner-projection-v1"}]}]} diff --git a/Tools/host-conformance.yaml b/Tools/host-conformance.yaml index 5e9768d..941e18e 100644 --- a/Tools/host-conformance.yaml +++ b/Tools/host-conformance.yaml @@ -29,10 +29,45 @@ # Only the restricted YAML subset (Tools/kblib.py parse_yaml_subset). # ============================================================================= -schema_version: 1 +# Schema 2 groups registrations by delivery channel. Schema 1 had one +# global conformance_version and one minimum, both meaning "inline tool +# result"; a second channel with different physics cannot borrow either. +# Each channel therefore declares what it can prove, using the three +# independent dimensions the protocol records -- content identity, transport +# assurance, and subject acknowledgement. A channel that cannot prove +# transport says so here rather than being read as if it could. +schema_version: 2 conformance_version: activation-inline-v1 minimum_bytes: 49152 +channels: + - channel_id: inline-mcp + conformance_version: activation-inline-v1 + minimum_bytes: 49152 + proves_identity: true + proves_transport: true + proves_acknowledgement: true + probe: Tools/tests/host_conformance_probe.py + note: "Bytes ride inside the tool result and the trailing nonce returns from the same context. Registration requires both controls: a within-budget payload arriving whole, and a larger one observed to be externalized." + + - channel_id: remote-bundle + conformance_version: activation-inline-v1 + minimum_bytes: 49152 + proves_identity: true + proves_transport: true + proves_acknowledgement: true + probe: Tools/tests/host_conformance_probe.py + note: "A phase part is one tool result, so this channel is inline-mcp measured over a part instead of a single file. It shares the probe and the budget because it shares the physics." + + - channel_id: agent-native-file-read + conformance_version: activation-native-read-v1 + minimum_bytes: 0 + proves_identity: true + proves_transport: false + proves_acknowledgement: true + probe: null + note: "The Core names paths and hashes and the host reads them with its own file access. Identity is checkable and the actor can acknowledge, but nothing observes that the bytes entered the model context, so this channel never mints transport assurance. Raising it requires trusted host read telemetry -- an adapter report of what was actually read -- carried by its own probe with both controls. A trailing-bytes challenge does not qualify: it shows the tail was seen, which is acknowledgement, not transport." + adapters: - client_name: claude-code version_range_from: 2.1.223 diff --git a/Tools/operation-capabilities.yaml b/Tools/operation-capabilities.yaml index 4b0d1f3..c0cf93a 100644 --- a/Tools/operation-capabilities.yaml +++ b/Tools/operation-capabilities.yaml @@ -96,10 +96,20 @@ capabilities: - capability_id: card-context-delivery-v1 kind: producer - capability_version: 1.0.2 + capability_version: 1.0.3 implementation_paths: - Tools/card_activation.py - Tools/check_queue.py - Tools/mcp_server.py - Tools/update_queue.py operations: [] + + - capability_id: phase-delivery-consumer-v1 + kind: consumer + capability_version: 1.0.0 + implementation_paths: + - Tools/check_queue.py + - Tools/record_batch_judgment.py + - Tools/update_queue.py + - Tools/update_task.py + operations: [] diff --git a/Tools/record_batch_judgment.py b/Tools/record_batch_judgment.py index d07a98a..0b6f3ed 100644 --- a/Tools/record_batch_judgment.py +++ b/Tools/record_batch_judgment.py @@ -94,6 +94,17 @@ def build_judgment_receipt(runtime, contract, item, judgment_item_id, "activation-frozen requirement set; reactivate the batch " "before judging") + # Judging is the first act of the gate phase, so this is where that + # phase's delivery is owed. The actor's own execution context is passed + # deliberately: a judgment is somebody's judgment, and evidence that + # another context received the Gate Card proves nothing about this one. + phase_errors = check_queue.activation_phase_delivery_errors( + runtime, item, card_activation.PHASE_BATCH_GATE, + actor_context_id=os.environ.get( + card_activation.EXECUTION_CONTEXT_ENV)) + if phase_errors: + raise ValueError("; ".join(phase_errors)) + semantic_sha = None if requirement.target_selector == "each-manifest-page": _snapshot, semantic_sha = metadata_property_state.\ diff --git a/Tools/tests/test_phased_readback.py b/Tools/tests/test_phased_readback.py new file mode 100644 index 0000000..03e51b2 --- /dev/null +++ b/Tools/tests/test_phased_readback.py @@ -0,0 +1,649 @@ +"""Acceptance for `card-first-phased-readback-v4`. + +The protocol's whole claim is that moving *when* frozen bytes travel costs +nothing in what can be proved. These tests therefore pair every capability +with the negative control that would make it hollow: a phase that packs is +matched by a phase that must not be split, an ack that satisfies a gate is +matched by a stale-but-complete ack chain that must not, and an actor's own +evidence is matched by somebody else's evidence being refused. +""" + +import copy +import json +import os +import subprocess +from pathlib import Path +import shutil +import sys +import tempfile +import unittest + + +TOOLS = Path(__file__).resolve().parents[1] +FIXTURE = TOOLS / "tests" / "fixtures" / "runtime_state" / "valid" +sys.path.insert(0, str(TOOLS / "tests")) +sys.path.insert(0, str(TOOLS)) + +import card_activation +import check_queue +import kblib +from profile_fixture import install_loadable_profile + + +CONTEXT = "mcp:1111111111111111111111111111aaaa" +OTHER_CONTEXT = "mcp:2222222222222222222222222222bbbb" + + +def add_conditional_routes(root, routes=("R09", "R12")): + """Give the shared fixture the conditional routes it does not ship. + + The runtime fixture selects three preflight routes, so on it every + conditional phase is empty and every gate assertion would pass by having + nothing to check. These tests need the opposite: a gate phase with real + membership, so refusing to act without it can actually fail. + """ + for route_id in routes: + card_relative = "kernel/Cards/%s Fixture Card.md" % route_id + read_relative = "kernel/Read Sets/%s Fixture Read Set.md" % route_id + read_path = root / read_relative + read_path.parent.mkdir(parents=True, exist_ok=True) + read_path.write_text( + "---\ntype: read-set\nroute_id: %s\n---\n" + "# %s Fixture Read Set\n\n## Purpose\n\nBound the route.\n" % + (route_id, route_id), encoding="utf-8") + card = { + "type": "runtime-card", + "route_id": route_id, + "read_set": read_relative, + "compiled_from": "3.0.0", + "source_files": [read_relative], + "readback_sources": [], + "readback_policy": "none", + "source_hash": "0123456789ab", + "compiled_source_hash": "0123456789ab", + } + card_path = root / card_relative + card_path.parent.mkdir(parents=True, exist_ok=True) + card_path.write_text( + "---\n%s---\n# %s Fixture Card\n\nConditional route payload.\n" % + (kblib.canonical_yaml(card), route_id), encoding="utf-8") + + index_path = root / "kernel/Cards/Card Index.md" + text = index_path.read_text(encoding="utf-8") + for route_id in routes: + text = text.replace( + ' - route_id: %s\n path: "kernel/Cards/%s Fixture Card.md"\n' + ' read_set: "kernel/Read Sets/%s Fixture Read Set.md"\n' % + (route_id, route_id, route_id), + ' - route_id: %s\n path: "kernel/Cards/%s Fixture Card.md"\n' + ' read_set: "kernel/Read Sets/%s Fixture Read Set.md"\n' % + (route_id, route_id, route_id)) + index_path.write_text(text, encoding="utf-8") + + progress_path = root / ".cambium/state/progress_ledger.yaml" + progress = kblib.load_yaml_file(progress_path) + contract = progress["contract"] + contract["selected_route_ids"] = sorted( + set(contract["selected_route_ids"]) | set(routes)) + contract["selected_card_paths"] = sorted( + set(contract["selected_card_paths"]) | + {"kernel/Cards/%s Fixture Card.md" % route for route in routes}) + contract["selected_read_sets"] = sorted( + set(contract["selected_read_sets"]) | + {"kernel/Read Sets/%s Fixture Read Set.md" % route + for route in routes}) + progress_path.write_text(kblib.canonical_yaml(progress), encoding="utf-8") + # The contract is anchored by the initial task transition; widening the + # route set without moving that anchor would leave the fixture claiming + # a contract it no longer holds. + receipt_path = root / ".cambium/receipts/task-transitions.jsonl" + records = [json.loads(line) for line + in receipt_path.read_text(encoding="utf-8").splitlines() + if line.strip()] + for record in records: + if record.get("receipt_id") == "audit-fixture-initial-queue": + record["contract_sha256"] = kblib.sha256_bytes( + kblib.canonical_yaml(contract)) + record["after_progress_sha256"] = kblib.sha256_file(progress_path) + receipt_path.write_text( + "".join(json.dumps(record, separators=(",", ":")) + "\n" + for record in records), encoding="utf-8") + + +class PhasedActivationTests(unittest.TestCase): + def setUp(self): + self.temporary = tempfile.TemporaryDirectory() + self.addCleanup(self.temporary.cleanup) + self.root = Path(self.temporary.name).resolve() / "repo" + shutil.copytree(FIXTURE, self.root) + install_loadable_profile(self.root) + add_conditional_routes(self.root) + + def runtime(self): + result = check_queue.validate_runtime(self.root) + self.assertEqual([], result["errors"], result["errors"]) + return result + + def context(self, execution_context_id=CONTEXT, batch="B1"): + runtime = self.runtime() + return card_activation.build_activation_context( + self.root, runtime["progress"], runtime["items_by_id"][batch], + runtime_state=runtime, + execution_context_id=execution_context_id) + + def plan(self, context=None): + context = context or self.context() + return context["activation_bundle_manifest"]["phase_plan"] + + # ---- the plan itself ------------------------------------------------ + + def test_every_frozen_piece_belongs_to_exactly_one_phase(self): + context = self.context() + pieces = context["activation_bundle_manifest"]["pieces"] + planned = [] + for phase in self.plan(context)["phases"]: + planned.extend(phase["piece_ids"]) + self.assertEqual(sorted(row["piece_id"] for row in pieces), + sorted(planned)) + self.assertEqual(len(planned), len(set(planned))) + for row in pieces: + self.assertIn(row["phase"], card_activation.PHASES) + + def test_the_phase_set_is_closed_and_ordered(self): + self.assertEqual( + list(card_activation.PHASE_ORDER), + [phase["phase_id"] for phase in self.plan()["phases"]]) + + def test_conditional_phases_are_frozen_but_not_in_preflight(self): + # The point of freezing a phase nobody may enter is that entering it + # later proves what it always was, instead of resolving it afresh + # under whatever the repository looks like by then. + by_id = {phase["phase_id"]: phase for phase in self.plan()["phases"]} + preflight = set(by_id[card_activation.PHASE_BATCH_PREFLIGHT] + ["piece_ids"]) + for phase_id in card_activation.CONDITIONAL_PHASES: + self.assertTrue(by_id[phase_id]["conditional"]) + self.assertEqual( + set(), preflight & set(by_id[phase_id]["piece_ids"])) + + def test_governance_routes_leave_the_preflight_phase(self): + context = self.context() + by_id = {row["piece_id"]: row + for row in context["activation_bundle_manifest"]["pieces"]} + governance = [row for row in by_id.values() + if row.get("route_id") == "R09"] + if not governance: + self.skipTest("fixture contract selects no governance route") + for row in governance: + self.assertEqual(card_activation.PHASE_GOVERNANCE, row["phase"]) + + def test_the_plan_freezes_what_resolved_it(self): + environment = self.plan()["environment"] + for field in ("standards_version", "selected_profile_manifest", + "profile_snapshot_sha256", + "profile_contract_fingerprint", "resolver_version", + "card_index_sha256", "task_contract_sha256"): + self.assertTrue(environment.get(field), field) + self.assertEqual(card_activation.PHASE_RESOLVER_VERSION, + environment["resolver_version"]) + + def test_the_plan_hash_binds_the_plan(self): + context = self.context() + self.assertEqual([], card_activation.activation_context_errors(context)) + broken = copy.deepcopy(context) + broken["activation_bundle_manifest"]["phase_plan"]["phases"][0][ + "piece_ids"] = [] + self.assertTrue(card_activation.activation_context_errors(broken)) + + def test_a_standard_phase_must_fit_one_part(self): + for phase in self.plan()["phases"]: + if phase["phase_id"] in card_activation.STANDARD_PHASES: + self.assertLessEqual( + phase["part_count"], 1, + "%s was cut too wide" % phase["phase_id"]) + + def test_every_part_fits_the_delivery_budget(self): + for phase in self.plan()["phases"]: + for part in phase["parts"]: + self.assertLessEqual( + part["envelope_bytes"], + card_activation.MAX_ACTIVATION_PIECE_ENVELOPE_BYTES) + + # ---- narrowing ------------------------------------------------------ + + def test_work_spec_narrowing_moves_unused_routes_out_of_preflight(self): + routes = ["R01", "R05", "R09"] + assignment = card_activation.resolve_route_phases( + routes, narrowing=["R01"]) + self.assertEqual(card_activation.PHASE_BATCH_PREFLIGHT, + assignment["R01"]) + # A narrowed-away route is still reachable, just not at startup. + self.assertEqual(card_activation.PHASE_BATCH_RUNNING, + assignment["R05"]) + # An override is not a work route and narrowing cannot move it. + self.assertEqual(card_activation.PHASE_GOVERNANCE, assignment["R09"]) + + def test_silence_is_not_a_narrowing_claim(self): + assignment = card_activation.resolve_route_phases( + ["R01", "R05"], narrowing=None) + self.assertEqual(card_activation.PHASE_BATCH_PREFLIGHT, + assignment["R05"]) + + # ---- delivery and ack ---------------------------------------------- + + def deliver(self, phase_id, part=0, context=None, + execution_context_id=CONTEXT): + context = context or self.context(execution_context_id) + return card_activation.build_phase_delivery( + self.root, context, phase_id, part, + execution_context_id=execution_context_id) + + def test_a_part_carries_whole_files_and_a_trailing_nonce(self): + delivery = self.deliver(card_activation.PHASE_BATCH_PREFLIGHT) + payload = delivery["activation_phase_payload"] + self.assertEqual(card_activation.PHASE_DELIVERY_PROTOCOL, + payload["phase_protocol"]) + self.assertEqual(list(payload)[-1], "delivery_nonce") + for piece in payload["pieces"]: + self.assertEqual( + piece["sha256"], + kblib.sha256_bytes(piece["content"].encode("utf-8"))) + + def test_ack_returns_to_the_delivering_context_only(self): + delivery = self.deliver(card_activation.PHASE_BATCH_PREFLIGHT) + ack = card_activation.build_phase_ack( + delivery, delivery["delivery_nonce"], + execution_context_id=CONTEXT) + self.assertEqual(card_activation.PHASE_ACK_PROTOCOL, + ack["phase_ack_protocol"]) + with self.assertRaisesRegex(ValueError, "delivering execution"): + card_activation.build_phase_ack( + delivery, delivery["delivery_nonce"], + execution_context_id=OTHER_CONTEXT) + + def test_a_wrong_nonce_is_refused(self): + delivery = self.deliver(card_activation.PHASE_BATCH_PREFLIGHT) + with self.assertRaisesRegex(ValueError, "nonce"): + card_activation.build_phase_ack( + delivery, "0" * 32, execution_context_id=CONTEXT) + + def test_delivery_refuses_a_part_that_does_not_exist(self): + with self.assertRaisesRegex(ValueError, "part"): + self.deliver(card_activation.PHASE_BATCH_PREFLIGHT, part=99) + + def test_delivery_refuses_an_unregistered_phase(self): + with self.assertRaisesRegex(ValueError, "registered phase"): + self.deliver("batch-whenever") + + def test_a_source_that_drifts_after_admission_is_refused(self): + context = self.context() + record = card_activation.phase_record( + context, card_activation.PHASE_BATCH_PREFLIGHT) + piece_id = record["parts"][0]["piece_ids"][0] + frozen = next(row for row + in context["activation_bundle_manifest"]["pieces"] + if row["piece_id"] == piece_id) + target = self.root / frozen["path"] + target.write_text(target.read_text(encoding="utf-8") + "\ndrift\n", + encoding="utf-8") + with self.assertRaisesRegex(ValueError, "drifted"): + self.deliver(card_activation.PHASE_BATCH_PREFLIGHT, + context=context) + + # ---- the authoritative pointer -------------------------------------- + + def test_the_attempt_id_is_derived_from_bundle_and_context(self): + context = self.context() + delivery = self.deliver(card_activation.PHASE_BATCH_PREFLIGHT, + context=context) + self.assertEqual( + card_activation.expected_delivery_attempt_id( + context["card_bundle_sha256"], CONTEXT), + delivery["delivery_attempt_id"]) + + def test_another_context_derives_another_attempt(self): + context = self.context() + self.assertNotEqual( + card_activation.expected_delivery_attempt_id( + context["card_bundle_sha256"], CONTEXT), + card_activation.expected_delivery_attempt_id( + context["card_bundle_sha256"], OTHER_CONTEXT)) + + def test_a_superseded_bundle_derives_another_attempt(self): + # This is what makes a complete-but-stale ack chain fail: the chain + # stays internally consistent and simply stops matching the pointer. + context = self.context() + self.assertNotEqual( + card_activation.expected_delivery_attempt_id( + context["card_bundle_sha256"], CONTEXT), + card_activation.expected_delivery_attempt_id( + "sha256:" + ("0" * 64), CONTEXT)) + + +class PhaseGateConsumerTests(unittest.TestCase): + """The gate predicate itself, exercised without a live receipt store.""" + + def setUp(self): + self.temporary = tempfile.TemporaryDirectory() + self.addCleanup(self.temporary.cleanup) + self.root = Path(self.temporary.name).resolve() / "repo" + shutil.copytree(FIXTURE, self.root) + install_loadable_profile(self.root) + add_conditional_routes(self.root) + self.result = check_queue.validate_runtime(self.root) + self.assertEqual([], self.result["errors"], self.result["errors"]) + self.item = self.result["items_by_id"]["B1"] + self.context = card_activation.build_activation_context( + self.root, self.result["progress"], self.item, + runtime_state=self.result, execution_context_id=CONTEXT) + + def catalog_with(self, *receipts): + catalog = dict(check_queue.current_receipt_catalog(self.result)) + activation = dict( + card_activation.activation_receipt_binding(self.context), + tool=check_queue.TOOL, tool_version=check_queue.TOOL_VERSION, + receipt_id="audit-activation-1") + catalog["audit-activation-1"] = ("x", activation) + for index, receipt in enumerate(receipts): + catalog["audit-ack-%d" % index] = ("x", receipt) + view = dict(self.result) + view["current_receipt_catalog"] = catalog + view["receipt_catalog"] = catalog + return view, dict(self.item, activation_receipt="audit-activation-1") + + def ack_for(self, phase_id, part=0, context_id=CONTEXT, + bundle_sha=None): + delivery = card_activation.build_phase_delivery( + self.root, self.context, phase_id, part, + execution_context_id=context_id) + ack = card_activation.build_phase_ack( + delivery, delivery["delivery_nonce"], + execution_context_id=context_id) + if bundle_sha is not None: + ack = dict(ack, card_bundle_sha256=bundle_sha) + return dict(card_activation.phase_ack_receipt_binding(ack), + result="pass", invalidated_by=None) + + def test_an_undelivered_phase_blocks_the_actor(self): + view, item = self.catalog_with() + errors = check_queue.activation_phase_delivery_errors( + view, item, card_activation.PHASE_BATCH_GATE, + actor_context_id=CONTEXT) + gate = card_activation.phase_piece_ids( + self.context, card_activation.PHASE_BATCH_GATE) + if not gate: + self.skipTest("fixture gate phase is empty") + self.assertTrue(errors) + + def test_a_delivered_phase_admits_the_actor(self): + gate = card_activation.phase_record( + self.context, card_activation.PHASE_BATCH_GATE) + if not gate["piece_ids"]: + self.skipTest("fixture gate phase is empty") + acks = [self.ack_for(card_activation.PHASE_BATCH_GATE, index) + for index in range(gate["part_count"])] + view, item = self.catalog_with(*acks) + self.assertEqual([], check_queue.activation_phase_delivery_errors( + view, item, card_activation.PHASE_BATCH_GATE, + actor_context_id=CONTEXT)) + + def test_another_actors_complete_chain_is_refused(self): + gate = card_activation.phase_record( + self.context, card_activation.PHASE_BATCH_GATE) + if not gate["piece_ids"]: + self.skipTest("fixture gate phase is empty") + acks = [self.ack_for(card_activation.PHASE_BATCH_GATE, index, + context_id=OTHER_CONTEXT) + for index in range(gate["part_count"])] + view, item = self.catalog_with(*acks) + errors = check_queue.activation_phase_delivery_errors( + view, item, card_activation.PHASE_BATCH_GATE, + actor_context_id=CONTEXT) + self.assertTrue(errors) + self.assertIn("another execution context", errors[0]) + # The same chain is still valid history for an integrator, which + # checks that the phase was earned, not that it earned it. + self.assertEqual([], check_queue.activation_phase_delivery_errors( + view, item, card_activation.PHASE_BATCH_GATE)) + + def test_a_prepared_activation_is_exempt(self): + prepared = card_activation.build_activation_context( + self.root, self.result["progress"], self.item, + runtime_state=self.result, execution_context_id=None) + self.assertEqual("prepared", prepared["delivery_assurance"]) + catalog = dict(check_queue.current_receipt_catalog(self.result)) + catalog["audit-activation-1"] = ("x", dict( + card_activation.activation_receipt_binding(prepared), + tool=check_queue.TOOL, tool_version=check_queue.TOOL_VERSION)) + view = dict(self.result, current_receipt_catalog=catalog, + receipt_catalog=catalog) + item = dict(self.item, activation_receipt="audit-activation-1") + self.assertEqual([], check_queue.activation_phase_delivery_errors( + view, item, card_activation.PHASE_BATCH_GATE, + actor_context_id=CONTEXT)) + + def test_native_read_channel_may_not_mint_transport_assurance(self): + # The ceiling itself is the assertion. Testing only that a missing + # ack fails would leave the channel free to claim transport once an + # ack arrives, which is precisely the conflation this registry was + # restructured to prevent. + registry = kblib.parse_yaml_subset( + (TOOLS / "host-conformance.yaml").read_text(encoding="utf-8")) + self.assertEqual(2, registry["schema_version"]) + channels = {row["channel_id"]: row for row in registry["channels"]} + native = channels["agent-native-file-read"] + self.assertFalse(native["proves_transport"]) + self.assertTrue(native["proves_identity"]) + self.assertTrue(native["proves_acknowledgement"]) + for channel_id in ("inline-mcp", "remote-bundle"): + self.assertTrue(channels[channel_id]["proves_transport"]) + self.assertEqual( + card_activation.MAX_ACTIVATION_PIECE_ENVELOPE_BYTES, + channels[channel_id]["minimum_bytes"]) + + def test_control_plane_predicate_is_about_the_manifest(self): + self.assertFalse(check_queue.batch_touches_control_plane( + {"manifest": ["Topics/A.md"]})) + self.assertTrue(check_queue.batch_touches_control_plane( + {"manifest": ["Topics/A.md", "kernel/K00 Standards Overview.md"]})) + self.assertTrue(check_queue.batch_touches_control_plane( + {"manifest": ["profiles/some-adopter/profile.md"]})) + + +class PhaseCliTests(unittest.TestCase): + """The CLI round trip, because the library round trip is not the same one. + + The first phase delivery through the CLI produced a receipt with every + phase field missing: the library call was correct and the tool simply + never handed its result to the receipt writer. A library-only suite + cannot see that, so this exercises the actual command. + """ + + def setUp(self): + self.temporary = tempfile.TemporaryDirectory() + self.addCleanup(self.temporary.cleanup) + self.root = Path(self.temporary.name).resolve() / "repo" + shutil.copytree(FIXTURE, self.root) + install_loadable_profile(self.root) + add_conditional_routes(self.root) + + def run_tool(self, name, *arguments, context_id=CONTEXT): + environ = dict(os.environ) + environ[card_activation.EXECUTION_CONTEXT_ENV] = context_id + return subprocess.run( + [sys.executable, str(TOOLS / name), str(self.root), *arguments], + text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + env=environ, check=False) + + def open_b1(self): + ready = self.run_tool( + "check_queue.py", "--require-ready", "B1", + "--receipts", ".cambium/receipts/ready.jsonl", "--json") + self.assertEqual(0, ready.returncode, ready.stderr) + receipt = json.loads(ready.stdout)[0] + self.assertEqual("host-bound", receipt["delivery_assurance"]) + self.assertIn("phase_plan_sha256", receipt) + queue = kblib.load_yaml_file(self.root / check_queue.QUEUE_PATH) + opened = self.run_tool( + "update_queue.py", "--id", "B1", "--transition", "open", + "--gate-receipt", receipt["receipt_id"], + "--expected-state-revision", str(queue["state_revision"]), + "--expected-sha256", + kblib.sha256_file(self.root / check_queue.QUEUE_PATH), + "--actor-role", "integrator", "--apply") + self.assertEqual(0, opened.returncode, opened.stdout + opened.stderr) + return receipt + + def test_phase_delivery_and_ack_round_trip_through_the_cli(self): + self.open_b1() + delivered = self.run_tool( + "check_queue.py", "--deliver-phase", "B1", + "--phase", card_activation.PHASE_BATCH_PREFLIGHT, + "--receipts", ".cambium/receipts/phase.jsonl", "--json") + self.assertEqual(0, delivered.returncode, delivered.stderr) + delivery = json.loads(delivered.stdout)[0] + # The regression this pins: the tool result and the receipt both + # have to carry the phase, not just the library return value. + self.assertEqual(card_activation.PHASE_BATCH_PREFLIGHT, + delivery["phase_id"]) + self.assertEqual(0, delivery["part_index"]) + self.assertTrue(delivery["phase_piece_ids"]) + self.assertTrue(delivery["delivery_nonce"]) + payload = delivery["activation_phase_payload"] + self.assertEqual(len(delivery["phase_piece_ids"]), + len(payload["pieces"])) + + persisted = json.loads(( + self.root / ".cambium/receipts/phase.jsonl" + ).read_text(encoding="utf-8").splitlines()[0]) + self.assertEqual(card_activation.PHASE_BATCH_PREFLIGHT, + persisted["phase_id"]) + # Bytes ride the tool result; the register keeps identities only. + self.assertNotIn("activation_phase_payload", persisted) + self.assertNotIn("content", json.dumps(persisted, sort_keys=True)) + + acked = self.run_tool( + "check_queue.py", "--ack-activation-phase", "B1", + "--phase", card_activation.PHASE_BATCH_PREFLIGHT, + "--phase-nonce", delivery["delivery_nonce"], + "--phase-delivery-receipt", delivery["receipt_id"], + "--receipts", ".cambium/receipts/phase-ack.jsonl", "--json") + self.assertEqual(0, acked.returncode, acked.stderr) + ack = json.loads(acked.stdout)[0] + self.assertEqual(card_activation.PHASE_ACK_PROTOCOL, + ack["phase_ack_protocol"]) + self.assertEqual(delivery["delivery_attempt_id"], + ack["delivery_attempt_id"]) + self.assertEqual(sorted(delivery["phase_piece_ids"]), + sorted(ack["phase_piece_ids"])) + + def test_the_cli_refuses_an_ack_from_another_context(self): + self.open_b1() + delivered = self.run_tool( + "check_queue.py", "--deliver-phase", "B1", + "--phase", card_activation.PHASE_BATCH_PREFLIGHT, + "--receipts", ".cambium/receipts/phase.jsonl", "--json") + self.assertEqual(0, delivered.returncode, delivered.stderr) + delivery = json.loads(delivered.stdout)[0] + refused = self.run_tool( + "check_queue.py", "--ack-activation-phase", "B1", + "--phase", card_activation.PHASE_BATCH_PREFLIGHT, + "--phase-nonce", delivery["delivery_nonce"], + "--phase-delivery-receipt", delivery["receipt_id"], + "--receipts", ".cambium/receipts/phase-ack.jsonl", + context_id=OTHER_CONTEXT) + self.assertEqual(1, refused.returncode) + self.assertIn("delivering execution context", refused.stdout) + + +class ProducerEraReplayTests(unittest.TestCase): + """A sealed receipt is judged by the rules of the era that wrote it. + + The v4 constant rename made this concrete: two era checks compared + against "the current protocol" rather than against the shape they meant, + so shipping v4 silently re-filed every sealed v3 receipt under the + embedded-payload rules of v1. These tests pin the shapes themselves. + """ + + def setUp(self): + self.temporary = tempfile.TemporaryDirectory() + self.addCleanup(self.temporary.cleanup) + self.root = Path(self.temporary.name).resolve() / "repo" + shutil.copytree(FIXTURE, self.root) + install_loadable_profile(self.root) + add_conditional_routes(self.root) + result = check_queue.validate_runtime(self.root) + self.assertEqual([], result["errors"], result["errors"]) + self.current = card_activation.build_activation_context( + self.root, result["progress"], result["items_by_id"]["B1"], + runtime_state=result, execution_context_id=CONTEXT) + + def as_v3(self): + """Rebuild the v3 shape: pieces without phases, no phase plan.""" + context = copy.deepcopy(self.current) + manifest = context["activation_bundle_manifest"] + manifest["activation_protocol"] = card_activation.\ + V3_ACTIVATION_PROTOCOL + manifest.pop("phase_plan", None) + manifest.pop("phase_plan_sha256", None) + for piece in manifest["pieces"]: + piece.pop("phase", None) + context["activation_protocol"] = card_activation.\ + V3_ACTIVATION_PROTOCOL + context.pop("phase_plan_sha256", None) + context["card_bundle_sha256"] = kblib.sha256_bytes( + kblib.canonical_json_bytes(manifest)) + return context + + def test_a_sealed_v3_context_still_validates(self): + self.assertEqual( + [], card_activation.activation_context_errors(self.as_v3())) + + def test_a_sealed_v3_context_keeps_its_own_field_set(self): + v3 = self.as_v3() + self.assertEqual(card_activation.ACTIVATION_CONTEXT_FIELDS, + card_activation.activation_context_fields(v3)) + self.assertNotIn( + "phase_plan_sha256", + card_activation.activation_receipt_binding(v3)) + self.assertIn("phase_plan_sha256", + card_activation.activation_receipt_binding(self.current)) + + def test_v3_may_still_deliver_single_pieces(self): + v3 = self.as_v3() + piece_id = v3["activation_bundle_manifest"]["pieces"][0]["piece_id"] + delivery = card_activation.build_activation_piece( + self.root, v3, piece_id, execution_context_id=CONTEXT) + self.assertEqual(card_activation.PIECE_PROTOCOL, + delivery["piece_protocol"]) + + def test_v3_has_no_phases_to_deliver(self): + with self.assertRaisesRegex(ValueError, "phase delivery requires"): + card_activation.build_phase_delivery( + self.root, self.as_v3(), + card_activation.PHASE_BATCH_PREFLIGHT, 0, + execution_context_id=CONTEXT) + + def test_a_pre_phase_era_must_not_carry_a_phase_plan(self): + forged = self.as_v3() + forged["phase_plan_sha256"] = "sha256:" + ("0" * 64) + self.assertTrue(card_activation.activation_context_errors(forged)) + + def test_a_pre_phase_era_gate_owes_nothing(self): + # An old batch does not acquire a new obligation retroactively. + result = check_queue.validate_runtime(self.root) + catalog = dict(check_queue.current_receipt_catalog(result)) + catalog["audit-activation-v3"] = ("x", dict( + card_activation.activation_receipt_binding(self.as_v3()), + tool=check_queue.TOOL, tool_version=check_queue.TOOL_VERSION)) + view = dict(result, current_receipt_catalog=catalog, + receipt_catalog=catalog) + item = dict(result["items_by_id"]["B1"], + activation_receipt="audit-activation-v3") + self.assertEqual([], check_queue.activation_phase_delivery_errors( + view, item, card_activation.PHASE_BATCH_GATE, + actor_context_id=CONTEXT)) + + +if __name__ == "__main__": + unittest.main() diff --git a/Tools/tests/test_update_queue.py b/Tools/tests/test_update_queue.py index 7afc2c2..03a30e4 100644 --- a/Tools/tests/test_update_queue.py +++ b/Tools/tests/test_update_queue.py @@ -3781,6 +3781,8 @@ def test_legacy_activation_era_carries_no_obligations(self): legacy_manifest = dict(activation["activation_bundle_manifest"]) legacy_manifest["activation_protocol"] = "card-first-readback-v1" legacy_manifest.pop("batch_review_plan", None) + legacy_manifest.pop("phase_plan", None) + legacy_manifest.pop("phase_plan_sha256", None) pieces = legacy_manifest.pop("pieces", []) legacy_manifest.pop("piece_count", None) legacy_manifest.pop("max_piece_envelope_bytes", None) @@ -3798,6 +3800,7 @@ def test_legacy_activation_era_carries_no_obligations(self): def downgrade(record): record["activation_protocol"] = "card-first-readback-v1" record.pop("review_requirement_set_sha256", None) + record.pop("phase_plan_sha256", None) if "activation_bundle_manifest" in record: record["activation_bundle_manifest"] = legacy_manifest record["card_bundle_sha256"] = legacy_bundle_sha diff --git a/Tools/update_queue.py b/Tools/update_queue.py index 5e388b3..79704a8 100644 --- a/Tools/update_queue.py +++ b/Tools/update_queue.py @@ -641,6 +641,28 @@ def require_standards_revalidation(): raise ValueError( "open -> merge-ready requires the Profile batch-review " "judgment set: %s" % "; ".join(judgment_errors)) + # The gate phase had to be delivered for this batch to have reached + # a merge-ready claim at all. The integrator checks history here + # rather than acting on the Cards itself, so it binds no actor + # context: what it verifies is that one attempt of the current + # activation earned the phase. + phase_errors = check_queue.activation_phase_delivery_errors( + result, item, card_activation.PHASE_BATCH_GATE) + if phase_errors: + raise ValueError( + "open -> merge-ready requires the batch gate phase: %s" % + "; ".join(phase_errors)) + # A batch whose own manifest edits the control plane did governance, + # whichever writer it used. Enforcing that here rather than inside + # each governance tool puts the check on the edge no file edit can + # route around, and keeps the predicate on what the batch changed. + if check_queue.batch_touches_control_plane(item): + governance_errors = check_queue.activation_phase_delivery_errors( + result, item, card_activation.PHASE_GOVERNANCE) + if governance_errors: + raise ValueError( + "a batch that edits the control plane requires the " + "governance phase: %s" % "; ".join(governance_errors)) item["state"] = "merge-ready" item["merge_ready_at"] = now item["delta_path"] = args.delta_path diff --git a/Tools/update_task.py b/Tools/update_task.py index 9e8610a..79c75c0 100644 --- a/Tools/update_task.py +++ b/Tools/update_task.py @@ -17,6 +17,7 @@ import time sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import card_activation import check_queue import kblib @@ -562,6 +563,17 @@ def build_task_transition(result, after_state, at, summary, evidence_receipt, ) if not _nonempty(evidence_receipt): raise ValueError("completion-candidate requires --queue-check-receipt") + # R08 travels in the task-completion phase. Its carrier is whatever + # batch still holds an activation; with zero remaining work there is + # usually none, and then the phase has nothing to prove against. + phase_errors = check_queue.task_phase_delivery_errors( + result, card_activation.PHASE_TASK_COMPLETION, + actor_context_id=os.environ.get( + card_activation.EXECUTION_CONTEXT_ENV)) + if phase_errors: + raise ValueError( + "completion-candidate requires the task-completion phase: %s" + % "; ".join(phase_errors)) completion_receipt = _completion_gate_receipt( result, evidence_receipt) completion_time = check_queue._timestamp_value( diff --git a/kernel/Cards/Card Index.md b/kernel/Cards/Card Index.md index ead27af..f85384b 100644 --- a/kernel/Cards/Card Index.md +++ b/kernel/Cards/Card Index.md @@ -7,8 +7,8 @@ source_files: - kernel/K00 Standards Control/01 Operating Role and Reading Protocol.md - kernel/K00 Standards Control/02 Task Routing.md - kernel/K00 Standards Control/03 Standards Governance.md -source_hash: '9d7651a8270b' -compiled_source_hash: '9d7651a8270b' +source_hash: '946cd4916239' +compiled_source_hash: '946cd4916239' route_registry: - route_id: R01 path: "kernel/Cards/R01 Core Bootstrap Card.md" diff --git a/kernel/Cards/R01 Core Bootstrap Card.md b/kernel/Cards/R01 Core Bootstrap Card.md index 0c8b299..cb8ecb5 100644 --- a/kernel/Cards/R01 Core Bootstrap Card.md +++ b/kernel/Cards/R01 Core Bootstrap Card.md @@ -18,11 +18,12 @@ source_files: - kernel/K00 Standards Control/17 Profile Dependency Closure.md - kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery.md - kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate.md + - kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan.md - kernel/K13 Task Runtime and Execution Control/11 Completion Policy.md readback_sources: [] readback_policy: none -source_hash: '2025ae92d192' -compiled_source_hash: '2025ae92d192' +source_hash: '3550fde7adbb' +compiled_source_hash: '3550fde7adbb' --- # R01 Core Bootstrap Card @@ -44,15 +45,17 @@ The selected profile's `Priority Rubric` grants P0/P1. Record the tier in the Co ## Before Start -- [ ] Enter through a `card-first-readback-v3` admission result. It freezes a - piece manifest naming R01 and every selected task Card; the bytes arrive - afterwards, one budgeted piece per tool result, each acknowledged from this - execution context. Admission records `host-bound` or `prepared` and claims - no delivery of its own. -- [ ] Treat delivery as incomplete until the ack set matches the frozen - manifest and the host adapter is a registered conformant build. Only then - may a runtime call this context `running`. An unbound CLI delivery, or any - unregistered adapter, is `degraded`: work may proceed, but no layer may +- [ ] Enter through a `card-first-phased-readback-v4` admission result. It + freezes every phase's piece manifest and the environment that resolved it; + the bytes arrive afterwards one phase part per tool result, each + acknowledged from this execution context. Admission records `host-bound` or + `prepared` and claims no delivery of its own. +- [ ] Pull the `batch-preflight` phase before working, and each later phase + before the act that owes it: the gate phase before the first judgment or + merge-ready request, the governance phase before a batch that edits the + control plane can reach merge-ready. Treat a phase as incomplete until its + ack set matches that phase's frozen manifest. An unbound CLI delivery, or + any unregistered adapter, is `degraded`: work may proceed, but no layer may claim machine-enforced Card delivery. - [ ] State the objective, target scope, exclusions, and latest user instructions. - [ ] Inspect the repository root for `.cambium/state/` before any content or diff --git a/kernel/Cards/R07 Long-running Execution Card.md b/kernel/Cards/R07 Long-running Execution Card.md index 4212769..38b9cfa 100644 --- a/kernel/Cards/R07 Long-running Execution Card.md +++ b/kernel/Cards/R07 Long-running Execution Card.md @@ -23,6 +23,7 @@ source_files: - kernel/K13 Task Runtime and Execution Control/10 Batch Admission Transitions and Serial Integration.md - kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery.md - kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate.md + - kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan.md - kernel/K13 Task Runtime and Execution Control/11 Completion Policy.md - kernel/K13 Task Runtime and Execution Control/12 Completion Gate Bindings.md - kernel/K13 Task Runtime and Execution Control/13 Final Handoff.md @@ -47,8 +48,8 @@ readback_sources: - kernel/K12 Quality Assurance/17 Gate Receipt Payload Contract.md - kernel/K13 Task Runtime and Execution Control/16 Resume Next Action Vocabulary.md readback_policy: declared -source_hash: 'b66901b13a27' -compiled_source_hash: 'b66901b13a27' +source_hash: '4cf500e4297a' +compiled_source_hash: '4cf500e4297a' --- # R07 Long-running Execution Card @@ -72,7 +73,7 @@ Run a multi-batch task, sustain checkpoints, resume after interruption, maintain ## During -Each batch follows the fixed loop: version/Guidance self-check → `check_queue.py --require-ready` (freezes the piece manifest; delivers no bytes) → integrator records `queued -> open` → pull every frozen piece with `check_queue.py --deliver-activation-piece` and return each nonce with `--ack-activation-piece`, which is what lets a runtime call this context `running` → execute the frozen manifest → build one AuditPlan, finish in-batch QA — including one `record_batch_judgment.py` receipt per record of the activation-delivered Batch Review plan — and write the delta → integrator records `open -> merge-ready` → serially applies the delta and global gates → reconciles Coverage/Queue/Progress → records `merge-ready -> closed`. +Each batch follows the fixed loop: version/Guidance self-check → `check_queue.py --require-ready` (freezes every phase's manifest and the environment that resolved it; delivers no bytes) → integrator records `queued -> open` → pull the preflight phase with `check_queue.py --deliver-phase --phase batch-preflight` and return its nonce with `--ack-activation-phase`, which is what lets a runtime call this context `running` → execute the frozen manifest → pull `batch-gate` before judging → build one AuditPlan, finish in-batch QA — including one `record_batch_judgment.py` receipt per record of the activation-delivered Batch Review plan — and write the delta → integrator records `open -> merge-ready` → serially applies the delta and global gates → reconciles Coverage/Queue/Progress → records `merge-ready -> closed`. - Concurrent batches have disjoint manifests and merged prerequisites; only the integrator writes shared control state and hub pages. - In-batch QA is not satisfied by producing the close evidence set alone: each M-tier manifest page passes, page by page, the M-tier Gate Checklist surfaced by the kernel Single Note Authoring Card (K12/14 folds note-level acceptance into Batch Review), including the sources-role and page-contract items; the per-page conclusion is recorded in that page's attestation, not asserted once in the batch wrapper. diff --git a/kernel/Cards/R09 Standards Governance Card.md b/kernel/Cards/R09 Standards Governance Card.md index 3b474a1..e588a3a 100644 --- a/kernel/Cards/R09 Standards Governance Card.md +++ b/kernel/Cards/R09 Standards Governance Card.md @@ -38,8 +38,8 @@ readback_sources: - kernel/K12 Quality Assurance/02 Rendering Verification.md - kernel/K12 Quality Assurance/05 Automated and Manual Checks.md readback_policy: activation -source_hash: '5d3baf0de814' -compiled_source_hash: '5d3baf0de814' +source_hash: 'ec7d6b418e52' +compiled_source_hash: 'ec7d6b418e52' --- # R09 Standards Governance Card diff --git a/kernel/Cards/R10 Maintenance Run Card.md b/kernel/Cards/R10 Maintenance Run Card.md index 0980776..3280316 100644 --- a/kernel/Cards/R10 Maintenance Run Card.md +++ b/kernel/Cards/R10 Maintenance Run Card.md @@ -26,8 +26,8 @@ readback_sources: - kernel/K12 Quality Assurance/11 Content-level Propagation.md - kernel/K12 Quality Assurance/12 Substantive Correctness Review.md readback_policy: declared -source_hash: '1b513ada03a8' -compiled_source_hash: '1b513ada03a8' +source_hash: 'b21efa9202ff' +compiled_source_hash: 'b21efa9202ff' --- # R10 Maintenance Run Card diff --git a/kernel/Cards/R11 Large-scale Work Admission Card.md b/kernel/Cards/R11 Large-scale Work Admission Card.md index 9ed911c..b1c99ca 100644 --- a/kernel/Cards/R11 Large-scale Work Admission Card.md +++ b/kernel/Cards/R11 Large-scale Work Admission Card.md @@ -21,8 +21,8 @@ source_files: readback_sources: - kernel/K12 Quality Assurance/19 Incremental Audit Planning.md readback_policy: declared -source_hash: 'e3e0aed9df30' -compiled_source_hash: 'e3e0aed9df30' +source_hash: 'ecf549f1db1b' +compiled_source_hash: 'ecf549f1db1b' --- # R11 Large-scale Work Admission Card @@ -36,7 +36,7 @@ Load before large-scale creation, moves, or deletion, together with [[kernel/Car - [ ] Confirm the execution context received the exact R01/R11 activation Bundle before the admission checklist is used to authorize work. -- [ ] Record contract, scope, initial batch, Standards version, exact `selected_profile_manifest`, selected routes and Cards, the derived loading envelope, target scope, exclusions, and latest user requirements; delivery receipts, not the frozen envelope, record actual context delivery. +- [ ] Record contract, scope, initial batch, Standards version, exact `selected_profile_manifest`, selected routes and Cards, the frozen batch-phase reading plan, target scope, exclusions, and latest user requirements; delivery receipts, not the frozen plan, record actual context delivery. - [ ] Make `minimum_run_until`, `checkpoint_at`, `hard_stop_at`, and the Completion Gate explicit; leave unspecified fields explicitly empty. - [ ] Initialize task state only when `.cambium/state/` is absent. If it exists, first run `check_queue.py --resume-status` and reconcile the recorded task; preserve a governance-only `.cambium/` parent, and bind Coverage, Required Queue, and Progress to the same task, scope, Standards version, and selected Profile. - [ ] Reconcile Coverage with the file system and exclusions; inventory ownership, incoming links, user modifications, explicit batch manifests, and dependencies. diff --git a/kernel/K00 Standards Control/01 Operating Role and Reading Protocol.md b/kernel/K00 Standards Control/01 Operating Role and Reading Protocol.md index afd9374..c909f81 100644 --- a/kernel/K00 Standards Control/01 Operating Role and Reading Protocol.md +++ b/kernel/K00 Standards Control/01 Operating Role and Reading Protocol.md @@ -55,6 +55,8 @@ receipts provide that behavioral evidence. The default reading mode is to read the task's kernel Runtime Card. A Card is a faithful compression of the corresponding Read Set's Start/Triggered/Gate modules, covering the determinations, procedures, and Gate lists needed for routine tasks. +A Card is the minimal executable checklist for the current work phase: the operating surface of the Standards, not the Standards in full, not a knowledge-loading container, not a compliance receipt, and not a transport unit. The system delivers only the minimal Card set an action requires, and delivers it before that action occurs; the source Standards behind a Card are expanded on demand when a determination is traced back. + In the following cases the Standards source text MUST be read back; cards alone MUST NOT be relied on: - The card does not cover the current situation, or the card content is in doubt. diff --git a/kernel/K00 Standards Control/02 Task Routing.md b/kernel/K00 Standards Control/02 Task Routing.md index 733f477..199f559 100644 --- a/kernel/K00 Standards Control/02 Task Routing.md +++ b/kernel/K00 Standards Control/02 Task Routing.md @@ -8,6 +8,8 @@ All tasks first select R01 Core Bootstrap, then combine the Rxx route for the actual work and any event modules shown below. The Card is loaded first; its paired Read Set is read back when the Card-first protocol requires source text. +Selecting a route is not the same as loading it at every batch startup: a selected route's Card enters the execution context when that route's phase predicate holds, and the phase set, the route-to-phase mapping, and their freezing are owned by [[kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan|Phased Reading Plan]]. + | Task | Required Read Set Or Module | Main Decision | |---|---|---| | Create a concept page or extend one in a targeted way | [[kernel/Read Sets/R02 Single Note Authoring Read Set\|Single Note Authoring]] | note type, owner, depth, sources, links, and the note gate | diff --git a/kernel/K00 Standards Control/06 Completion Precedence and Task Contract.md b/kernel/K00 Standards Control/06 Completion Precedence and Task Contract.md index b9fe632..2f5d844 100644 --- a/kernel/K00 Standards Control/06 Completion Precedence and Task Contract.md +++ b/kernel/K00 Standards Control/06 Completion Precedence and Task Contract.md @@ -73,7 +73,7 @@ User's latest explicit instruction Each ultra-long task only needs to confirm the items that change the defaults: - Objective, contract version, scope version, in-scope domains, exclusions, and exactly one frozen `completion_semantics` value (`build` or `maintenance`); when Required Queue state applies, its path, `queue_revision`, `queue_state_revision`, SHA-256 fingerprint, and current check receipt. -- Standards version and `selected_profile_manifest`, copied exactly from the active Standards state; the selected Rxx route IDs and Runtime Card paths; the actual loaded set (including any namespaced profile route and every Read Set or leaf path actually read back); and gate items not yet triggered. These are frozen by default for content tasks, and a task-level amendment cannot select another profile. +- Standards version and `selected_profile_manifest`, copied exactly from the active Standards state; the selected Rxx route IDs and Runtime Card paths; the actual loaded set (including any namespaced profile route and every Read Set or leaf path actually read back); and gate items not yet triggered. What is frozen by default for content tasks is the route candidate set together with the batch-phase reading plan -- the phase set, the route-to-phase mapping, the transition predicates, the per-phase computation rules, and the content identity of every potential phase alongside its environment fingerprint -- and not the byte union loaded at each batch startup; that plan is owned by [[kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan|Phased Reading Plan]]. A task-level amendment cannot select another profile. - The target authoring status for P0 / P1 and the selected `Expression Status Axis` values. - `minimum_run_until`, `checkpoint_at`, `hard_stop_at`. - The boundaries of Required, optional, deferred, and excluded. diff --git a/kernel/K00 Standards Control/16 Leaf Module Size Register.md b/kernel/K00 Standards Control/16 Leaf Module Size Register.md index 9c3c663..25b6746 100644 --- a/kernel/K00 Standards Control/16 Leaf Module Size Register.md +++ b/kernel/K00 Standards Control/16 Leaf Module Size Register.md @@ -23,14 +23,15 @@ never implies delivery-budget conformance. | Exception register | Active entries | |---|---| -| Leaf module exceptions | 23 active; registered below | +| Leaf module exceptions | 24 active; registered below | | Control-plane exceptions | None; register is open for an authorized governance change | | Leaf module exception | Measured | Necessity | Growth cap | Follow-up | |---|---|---|---|---| | [[kernel/K08 Metadata and Status/05 Review Source and Migration Metadata\|Review Source and Migration Metadata]] | 6962 bytes | Freshness, review, verification, and semantic-content modification form one causal timeline. The maintenance classifier and Integrator writers need the same definitions to decide whether a review still binds the current content; splitting the modification event from the review baseline would make both halves defer to the other before accepting evidence | 7KB | Registered when `last_content_modified` became an evidence-backed intermediate state and semantic content changes began invalidating prior review authority. Re-measure whenever an event type or freshness baseline is added; split only when a routed consumer can evaluate modification invalidation without resolving the review/freshness timeline | +| [[kernel/K00 Standards Control/01 Operating Role and Reading Protocol\|Operating Role and Reading Protocol]] | 6507 bytes | The page defines what a Card is and when source text must be read back instead. The v4 design principle -- a Card is the minimal executable checklist for the current phase, not the Standards in full, a knowledge container, a receipt, or a transport unit -- is the sentence that decides which of those two a reader is holding, so it belongs beside the definition it constrains. Placing it anywhere else would let a reader take the definition without the limit, which is the exact inversion v4 exists to correct | 6.5KB | Registered when the phased-reading protocol landed and the principle became normative rather than implied. Re-measure whenever the reading protocol gains a rule; the split condition is a routed consumer that resolves the read-back cases without needing the Card definition -- which does not exist today, because every reader of one needs the other | | [[kernel/K00 Standards Control/03 Standards Governance\|Standards Governance]] | 11625 bytes | R09 reads the whole page because its governance lifecycle, write-back checklist, accretion rule, migration conservation, and size budget jointly define one revision boundary. Instance state and chronological adoption history are deliberately external and therefore no longer contribute to this page's size | 12KB | Re-measure at each governance-rule change. The state/history split has occurred: current identity is `.cambium/governance/standards_state.yaml`, history is the append-only Standards-adoption receipt stream, and neither may grow this Kernel owner. Split again only when a routed governance consumer can decide one remaining rule family without the shared revision boundary | -| [[kernel/K00 Standards Control/06 Completion Precedence and Task Contract\|Completion Precedence and Task Contract]] | 7582 bytes | Splitting saves no reader. All four anchored readers of its sections sit inside tasks that already hold the whole page, because [[kernel/Read Sets/R01 Core Bootstrap Read Set\|Core Bootstrap]] reads it at Start for every task. `Maintenance Completion` further MUST stay with `Definition Of Complete`: the page requires one of the two to be declared when the task contract is frozen and forbids mixing their semantics, so a task holding one half could not make that declaration | 8KB | The growth cap on this row was raised from 7KB to 8KB while the page itself stayed unmodified: a re-measure put it at 7582 bytes, over the 7168-byte cap then registered, and the necessity beside it resolves the split test against splitting, so the disposition stays a registered exception and the cap moves instead. The move is declared here as a governance change under [[kernel/K00 Standards Control/03 Standards Governance#Leaf Module Size Budget\|Leaf Module Size Budget]], not left to be read out of a diff. Re-measure whenever a contract decision or a completion semantic is added; the split condition is a routed consumer that resolves standard precedence without holding a task contract | +| [[kernel/K00 Standards Control/06 Completion Precedence and Task Contract\|Completion Precedence and Task Contract]] | 8011 bytes | Splitting saves no reader. All four anchored readers of its sections sit inside tasks that already hold the whole page, because [[kernel/Read Sets/R01 Core Bootstrap Read Set\|Core Bootstrap]] reads it at Start for every task. `Maintenance Completion` further MUST stay with `Definition Of Complete`: the page requires one of the two to be declared when the task contract is frozen and forbids mixing their semantics, so a task holding one half could not make that declaration | 8KB | The growth cap on this row was raised from 7KB to 8KB while the page itself stayed unmodified: a re-measure put it at 7582 bytes, over the 7168-byte cap then registered, and the necessity beside it resolves the split test against splitting, so the disposition stays a registered exception and the cap moves instead. The move is declared here as a governance change under [[kernel/K00 Standards Control/03 Standards Governance#Leaf Module Size Budget\|Leaf Module Size Budget]], not left to be read out of a diff. Re-measure whenever a contract decision or a completion semantic is added; the split condition is a routed consumer that resolves standard precedence without holding a task contract | | [[kernel/K00 Standards Control/15 Read Set Loading Boundaries\|Read Set Loading Boundaries]] | 7643 bytes | Its routed consumers load the page to derive and record one Read Set/module load contract. The two sections are one obligation read from both ends: `Default Read Sets` registers the boundaries that name every leaf, and `Derived Load Set` states what a declaration resolved from those boundaries MUST contain, so a split would make every containment question return to the boundary registry it was split from | 7.5KB | Raised from 7KB to 7.5KB when the page made each paired Runtime Card account for every boundary leaf as either compiled guidance or intentional read-back. That rule belongs beside the boundary it closes and prevents structural reachability from being mistaken for semantic coverage. The distinct Profile closure remains split to [[kernel/K00 Standards Control/17 Profile Dependency Closure\|K00/17]]. Re-measure whenever a Read Set or load-set rule is added; split when a routed consumer resolves the declared load set without needing the boundary registry it derives from | | [[kernel/K03 Note Types and Ownership/01 Note Type Catalog\|Note Type Catalog]] | 6668 bytes | One catalog whose function is choosing among its sixteen types. Both routed consumers, the Single Note Authoring and Module Build Read Sets, load it for that same choice, and no page links an individual type, so a split by type group would make every choice read both groups | 7KB | Re-measure whenever a note type is added. Its seven `Examples:` lines (561 bytes) were tested against the cut-examples remedy and held: they are what a reader compares against to decide which of the sixteen types a page is, so cutting them would remove the judgment the catalog exists to support. The split condition is a routed consumer that already knows its type group before opening the catalog | | [[kernel/K06 Knowledge Intake and Evolution/03 Source-to-Knowledge Pipeline\|Source-to-Knowledge Pipeline]] | 7443 bytes | Its two externally entered gates are already extracted to [[kernel/K06 Knowledge Intake and Evolution/07 Environmental Scanning and Watermark\|K06/07]] and [[kernel/K06 Knowledge Intake and Evolution/08 Canonical Promotion Gate\|K06/08]], which are the only stages a consumer enters on its own. What remains is one traversal: Stages 2-8 and 10 have no meaning without the stages before them, and both routed consumers, the Source-driven Expansion Read Set at Start and the Source-driven Expansion Batch of [[kernel/K02 Knowledge Work Construction/09 Knowledge Batch Production\|K02/09]] which requires Stage 1-10 in full, run them in order in a single pass | 7.5KB | Re-measure whenever a stage is added; the next split MUST be a stage a consumer can enter on its own, as K06/07 and K06/08 were, never a range of the traversal | @@ -46,7 +47,7 @@ never implies delivery-budget conformance. | [[kernel/K12 Quality Assurance/16 Terminal Proof Contract\|Terminal Proof Contract]] | 11042 bytes | The proof contract, the gate that consumes it, and the trust boundary that scopes it are one answer to whether a task may close. Its single routed consumer, the Audit and Completion Read Set, loads all three | 11KB | Re-measure whenever a proof field or a gate item is added. Raised from 10KB to 11KB when Terminal Proof was required to consume one shared Profile/runtime view and bind/recheck the root-owned profile-load inputs alongside the Profile snapshot, typed contract, and exact repository snapshot later consumed by the completion writer. This is a currentness condition of the same proof. The earlier 9.5KB-to-10KB raise applies when root validation was required to rerun `profile-load` and keep its closure outside the five loaded-set lists. That is a condition of the existing proof, not a new proof object. The earlier raise carries the exact five-list binding. The next split MUST be `Evidence Trust Boundary`, the only part carrying an anchor of its own, once a routed consumer reaches it without the contract | | [[kernel/K12 Quality Assurance/17 Gate Receipt Payload Contract\|Gate Receipt Payload Contract]] | 10482 bytes | Gate identity fields, producer-specific additions, recording authority, and rejection are one current-authorization payload contract. R07 loads the page when a receipt is offered and needs all four to decide whether it authorizes the boundary | 10.5KB | Raised from 8.5KB to 10.5KB when current Gate authorization separated raw semantic leaves from their registered owners and required native owner member chains while preserving producer-era replay. These are acceptance and rejection rules of the same receipt payload, not a second payload contract. Raised from 7KB to 8.5KB when profile-load and Profile-derived Gate receipts gained their root-input and compiled-artifact and terminal repository fingerprints; these are producer-specific fields under the same shared acceptance/rejection contract. Originally registered when `profile-load` added its pre-Queue manifest identity plus Profile snapshot and typed-contract fingerprints. Those fields specialize the one payload contract and splitting them would create a second owner of what a Gate receipt carries. Re-measured to 10482 bytes when the batch-review wrapper gained its frozen judgment-set binding — the same one-wrapper contract, extended, not a second payload owner. Re-measure whenever a producer adds required authorization fields; split only when a routed consumer can validate one receipt class without the shared payload and rejection rules | | [[kernel/K12 Quality Assurance/14 Batch Review\|Batch Review]] | 7328 bytes | The two checklist groups and the wrapper's binding contract are one merge-ready boundary: the in-batch items say what a batch owes, and the wrapper paragraph says how the one consuming receipt proves it, now including the frozen Batch Review judgment set. A reader given either half would rebuild the other from prose | 7.5KB | Registered when the wrapper gained the judgment-set binding (`review_requirement_set_sha256`, `judgment_receipt_ids`, `judgment_record_set_sha256`) and the in-batch items gained the per-record `record_batch_judgment` obligation — the binding belongs beside the wrapper it extends and nowhere else. Re-measure when a wrapper field or in-batch item is added; split only when a routed consumer can validate the wrapper without the in-batch items that produce its members | -| [[kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery\|Card Context Activation and Read-back Delivery]] | 10646 bytes | The Bundle, the transport budget, the Frozen Review Plan, progressive read-back, and resume redelivery are one delivery boundary read at every activation; splitting the plan or the budget from the Bundle would let one recompile and not the other | 11KB | Raised from 7.5KB when protocol v3 replaced embedded payload delivery with budgeted per-piece delivery. The `Budgeted Piece Delivery` section states the byte budget, the whole-file rule, and the three-part guarantee whose parts must be read together -- a reader who has the budget without the conformance requirement would conclude that a small result is a proven one, which is the exact error v3 exists to remove. The Assignment states that consume this evidence did split out, to [[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate\|K13/20]]. Re-measure when the activation payload gains a commitment; split further only when a consumer can validate one commitment without the shared delivery/era rules | +| [[kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery\|Card Context Activation and Read-back Delivery]] | 11498 bytes | The Bundle, the transport budget, the Frozen Review Plan, progressive read-back, and resume redelivery are one delivery boundary read at every activation; splitting the plan or the budget from the Bundle would let one recompile and not the other | 12KB | Raised from 11KB when protocol v4 made delivery phased: the transport section now states what a part is and how it is measured, next to the budget that bounds it. **This is the third raise, and the last one this necessity supports: the page currently carries three tenants, and `Frozen Review Plan` is the one that is not about transport at all -- its consumers are the judgment writer and the merge-ready edge, neither of which reads a byte of this page's delivery rules. The next revision that pushes this page over 12KB splits that section out rather than raising again.** Earlier raise from 7.5KB when protocol v3 replaced embedded payload delivery with budgeted per-piece delivery. The `Budgeted Piece Delivery` section states the byte budget, the whole-file rule, and the three-part guarantee whose parts must be read together -- a reader who has the budget without the conformance requirement would conclude that a small result is a proven one, which is the exact error v3 exists to remove. The Assignment states that consume this evidence did split out, to [[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate\|K13/20]]. Re-measure when the activation payload gains a commitment; split further only when a consumer can validate one commitment without the shared delivery/era rules | | [[kernel/K13 Task Runtime and Execution Control/06 Amendment Log and Controlled Replanning\|Amendment Log and Controlled Replanning]] | 9557 bytes | The Guidance record, the Amendment state machine, and the registration/withdrawal writer contract are one log discipline: both routed consumers load the page whole to decide what a Guidance or operational change may do next, and no page anchors a section of it. The withdrawal rule that took the page over the cap belongs beside the one-pending rule it protects — a pending registration whose execution can never validate would otherwise wedge every future operational Amendment — and nowhere else. The Contract Amendment section joined for the same reason: the guarded writer for the one amendable contract field is part of the same discipline that says what an approved decision may and may not execute, and a reader deciding whether a contract change is amendable or successor-bound needs the whole state machine in hand | 9.5KB | Re-measure whenever an Amendment state, registration rule, or versioning rule is added; raised from 8KB to 9.5KB when the Task Contract gained a closed delegated-authority record, operational registration began deriving and binding its exact impact under lock, and narrow gap-route reconciliation received an explicit-user writer. These are authorization rules of the existing Amendment state machine. Earlier: re-measured at 8185 bytes when the Contract Amendment section gained the writer's own authorization conditions (effective-policy fingerprint, joint ceiling, merge-ready refusal) -- invocation rules of the same writer, not a new discipline. The cap moved from 7KB to 8KB when the Contract Amendment writer landed, under the same standing necessity. The split condition is a routed consumer that resolves a registration or withdrawal without holding the Guidance state machine it serves | | [[kernel/K13 Task Runtime and Execution Control/08 Required Queue Contract and Lifecycle\|Required Queue Contract and Lifecycle]] | 9198 bytes | The Queue document contract, the Work Spec binding, and the batch lifecycle are one object read from three angles, and the routed consumers load the page whole. The Batch Reference Settlement table cannot be split from the lifecycle it settles: it states what each reference to a batch ID must become when that batch reaches a terminal state, so a reader holding the lifecycle without the table would have exactly the gap the table was written to close | 9KB | Raised from 8.5KB to 9KB when routed-gap settlement moved before Delta freeze, bound the prospective after-image, and retained landed/close rechecks so the terminal gate is defense in depth rather than first discovery. Registered here as a governance change under [[kernel/K00 Standards Control/03 Standards Governance#Leaf Module Size Budget\|Leaf Module Size Budget]]. The page passed the 6KB soft cap when it gained the settlement table; the table is a closed list of the four places a batch ID is referenced, added because three of the four had each been discovered as a separate production incident, and it belongs beside the terminal transition that consumes it. Re-measure whenever a reference kind or a lifecycle edge is added — adding a reference kind means amending the table and the close settlement in the same revision; the split condition is a routed consumer that resolves a batch transition without needing the reference contract it settles | | [[kernel/K13 Task Runtime and Execution Control/10 Batch Admission Transitions and Serial Integration\|Batch Admission Transitions and Serial Integration]] | 9200 bytes | Concurrent-batch admission and the transition gates that admit them are one state machine. Three routed consumers load it whole, and no page links a section of it | 9KB | Re-measured at 9200 bytes when Card delivery was delegated to K13/19 while Queue `open` remained the admission boundary; the state-machine split test still fails. Re-measure whenever a transition or a concurrency rule is added; the split condition is a routed consumer that evaluates a transition gate without holding the concurrency rules it guards. Raised from 7.5KB to 9KB when condition 2 gained its reporting-channel rule: the paragraph explains why one admission condition is time-invariant and therefore reported over the whole Queue while the others stay readiness-only, which belongs beside the conditions it distinguishes and nowhere else, and the split test above still fails — the consumers that evaluate a transition gate need those concurrency rules in hand | diff --git a/kernel/K13 Task Runtime and Execution Control Standard.md b/kernel/K13 Task Runtime and Execution Control Standard.md index 371e6ef..af65c2a 100644 --- a/kernel/K13 Task Runtime and Execution Control Standard.md +++ b/kernel/K13 Task Runtime and Execution Control Standard.md @@ -31,7 +31,8 @@ This page is the stable entry point of the Task Runtime and Execution Control st | [[kernel/K13 Task Runtime and Execution Control/17 Escalation Policy\|Escalation Policy]] | `Purpose And Boundary`, `The Kernel Trigger`, `Profile-declared Triggers`, `Firing And Resuming`, `A Trigger Is Not A Gate`, `Control Accretion Decision`, `Related` | | [[kernel/K13 Task Runtime and Execution Control/18 Initial Task Planning Transaction\|Initial Task Planning Transaction]] | `Purpose And Boundary`, `What The Plan Supplies And What It May Never Infer`, `Where The Transaction Stops`, `Guarded Write Protocol`, `Applying It Twice`, `Control Accretion Decision`, `Related` | | [[kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery\|Card Context Activation and Read-back Delivery]] | `Purpose And Boundary`, `Frozen Reading Plan`, `Card Activation Bundle`, `Execution-context Delivery`, `Budgeted Piece Delivery`, `Frozen Review Plan`, `Progressive Read-back`, `Resume Reassignment And Failure`, `Related` | -| [[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate\|Assignment State and Delivery Gate]] | `Purpose And Boundary`, `Why This Is A Separate Gate`, `Assignment Record`, `Delivery States`, `Attempt Invalidation`, `What This Gate Does Not Prove`, `Related` | +| [[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate\|Assignment State and Delivery Gate]] | `Purpose And Boundary`, `Why This Is A Separate Gate`, `Assignment Record`, `Delivery States`, `Phase Scope`, `Attempt Invalidation`, `What This Gate Does Not Prove`, `Related` | +| [[kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan\|Phased Reading Plan]] | `Purpose And Boundary`, `Phase Set`, `Route To Phase Mapping`, `Frozen Phase Plan`, `Phase Packages`, `Invalidation`, `Related` | ## Applicable Read Sets diff --git a/kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery.md b/kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery.md index 18034fb..c289a08 100644 --- a/kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery.md +++ b/kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery.md @@ -88,26 +88,38 @@ required the same session to consume it at `queued -> open`. That claim was minted before the result left the server, so a host that externalized an oversized tool result left the payload outside the model context while the receipt still asserted delivery, and no gate could observe the divergence. -Under v3 the session-identity rule is retired -- keeping it would re-couple -the Queue lifecycle to the context lifecycle this module separates -- and -delivery completion is earned per piece, by the Assignment delivery gate of -[[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate|K13/20]]. +The session-identity rule is retired -- keeping it would re-couple the Queue +lifecycle to the context lifecycle this module separates -- and delivery +completion is earned per piece rather than asserted at admission. +[[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate|K13/20]] +defines completion; +[[kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan|K13/21]] +names the writers that refuse to act without it. ## Budgeted Piece Delivery -Protocol `card-first-readback-v3` stops embedding Card and read-back bytes in -the admission result. Admission freezes a piece manifest -- one record per +Protocol `card-first-readback-v3` stopped embedding Card and read-back bytes +in the admission result. Admission freezes a piece manifest -- one record per deliverable file, carrying `piece_id`, `kind`, `path`, `sha256`, and `bytes` --- and the bytes travel afterwards, one file per tool result. +-- and the bytes travel afterwards. + +`card-first-phased-readback-v4` freezes the same records and adds the phase +each belongs to, so bytes travel one phase part per result rather than one +file per result. Grouping changes no commitment: every file in a part keeps +its own frozen hash and is re-proved against current bytes at delivery. The +phase set is owned by +[[kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan|K13/21]]. -A piece is always a whole file. Splitting one file across results is invalid: -the frozen hash binds the complete file, a receiving model cannot rehash -fragments, and no party could then prove a reassembly was faithful. +A piece is always a whole file, and a part holds whole files only. Splitting +one file across results is invalid: the frozen hash binds the complete file, +a receiving model cannot rehash fragments, and no party could then prove a +reassembly was faithful. `MAX_ACTIVATION_PIECE_ENVELOPE_BYTES` is 49152 and is owned here. The measured object is the complete serialized delivery, not the source file: envelope, -JSON escaping, nonce, and transport wrapper all count. Admission fails closed -when any frozen piece would exceed the budget, so an oversized leaf is caught +JSON escaping, nonce, and transport wrapper all count. Under v4 that object +is the phase part. Admission fails closed when any frozen piece would exceed +the budget alone, so an oversized leaf is caught as a governance problem at its own boundary rather than as a transport accident mid-batch. [[kernel/K00 Standards Control/16 Leaf Module Size Register|K00/16]] carries the derived check for `activation` leaves; it consumes this budget and @@ -181,7 +193,10 @@ before it acts on `next_action`; the bytes follow one budgeted piece at a time. A new execution context invalidates every earlier ack: delivery evidence never transfers between contexts, and [[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate|K13/20]] -requires the full set to be re-earned. +requires the set to be re-earned. Under v4 that set is the preflight phase +plus the phase being resumed into: phases already earned stay proved by +their own receipts under the plan hash they were earned against, and +re-earning unused phases would make resume cost grow with task progress. Activation or read-back fails closed when R01 or a selected Card is absent, the Card Index disagrees with the contract, semantic hashes differ, a path is diff --git a/kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate.md b/kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate.md index 98037f9..e15ede8 100644 --- a/kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate.md +++ b/kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate.md @@ -37,7 +37,12 @@ An Assignment binds, for one execution context: - the role (`integrator`, `writer`, `reviewer`, or `researcher`) and that role's permitted write scope; - the frozen `card_bundle_sha256` taken from Queue admission; -- the current `delivery_attempt_id`; +- the current `delivery_attempt_id`, derived rather than stored: the hash of + the current `card_bundle_sha256` and the acting `execution_context_id`, so + a consumer recomputes the one value that pair could produce. A complete + chain from a superseded bundle or another context stays self-consistent + and stops matching that derivation, which is why consistency alone cannot + license reuse; - the delivery state below, and the handoff checkpoint if one exists. Role topology is runtime metadata. It is never Profile configuration, and an @@ -47,34 +52,50 @@ Assignment never widens a scope the Queue and Profile did not already grant. ```text pending Assignment created against an admitted batch -delivering at least one piece delivered, ack set incomplete -delivered ack set complete and Adapter conformance current +delivering at least one part of a phase delivered, that phase incomplete +delivered one phase's ack set complete and Adapter conformance current running worker may execute ``` -`pending -> delivering` requires one delivered piece. `delivering -> delivered` -requires all of: +The states are per phase, not per task. `pending -> delivering` requires one +delivered part. `delivering -> delivered(phase)` requires all of: -- the ack set equals the frozen piece manifest exactly -- no missing, extra, - duplicated, or foreign record; +- the ack set equals that phase's frozen piece set exactly -- no missing, + extra, duplicated, or foreign record, and every part accounted for; - every ack binds the same `assignment_id`, `execution_context_id`, - `card_bundle_sha256`, and `delivery_attempt_id`; + `card_bundle_sha256`, `phase_plan_sha256`, and `delivery_attempt_id`; - the host's declared adapter identity resolves to a current inline-delivery conformance registration. -Only `delivered` admits `running`. A runtime that cannot reach `delivered` +`delivered(batch-preflight)` admits `running`. A runtime that cannot reach `delivered` may still work, but records `degraded` and MUST NOT claim machine-enforced Card delivery. Queue `open` is unaffected either way: a human integrator admits batches without any Assignment at all. +## Phase Scope + +Admitting `running` on preflight changes timing, not obligation: later +phases are owed at the point that consumes them rather than banked at +startup. Which writer refuses which phase is owned by +[[kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan|K13/21]]. + +`running` itself still has no executable carrier: no writer computes an +Assignment state, so it remains a definition the phase consumers +approximate at their own edges. Recording that keeps the distance between +definition and enforcement visible -- the distance this module exists to +stop hiding. + ## Attempt Invalidation Delivery evidence is bound to one attempt in one context, and does not transfer. A new execution context, a reassignment, a reopened batch, a new -`card_bundle_sha256`, or a revised Profile contract each start a new -`delivery_attempt_id` and void every earlier ack. Recovery is to deliver the -current pieces again, never to carry evidence across the boundary that -invalidated it. +`card_bundle_sha256`, a revised Profile contract, or any change to a frozen +input of the phase plan -- which moves `phase_plan_sha256` -- each start a +new `delivery_attempt_id` and void every earlier ack. Recovery is to deliver +the current phases again, never to carry evidence across the boundary that +invalidated it. Re-delivery is scoped to the preflight phase plus the phase +being resumed into: phases already earned remain proved by their own +receipts under the plan hash they were earned against. This is deliberately expensive to fake and cheap to redo: re-delivery is idempotent reading, while a transferable ack would let a context claim diff --git a/kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan.md b/kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan.md new file mode 100644 index 0000000..9d3382e --- /dev/null +++ b/kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan.md @@ -0,0 +1,108 @@ +## Navigation + +- Parent: [[kernel/K13 Task Runtime and Execution Control Standard|K13 Task Runtime and Execution Control Standard]]. +- Previous: [[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate|Assignment State and Delivery Gate]]. + +## Purpose And Boundary + +This module owns the phased reading plan of protocol +`card-first-phased-readback-v4`: which Cards a batch owes at each point of its +own execution, instead of all of them at startup. Freezing is unchanged from +v3 -- everything below is computed at admission; only the moment of delivery +moves. [[kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery|K13/19]] +owns the transport, the piece budget, and what one delivered piece proves; +[[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate|K13/20]] +owns Assignment state and the delivery gate. This module owns neither, and no +field of it asserts that anything was read or understood. + +Earlier protocols made one startup set carry every Card a batch might ever +need. Cost was paid for routes that never triggered, and the set was largest +exactly when the worker knew least about the work in front of it. + +## Phase Set + +Five phases, closed, in two tiers. + +Batch phases are reached by running the batch at all: + +- `batch-preflight`: R01, the batch's work-route Card, and R07. +- `batch-running`: no frozen set; only declared read-back already triggered. +- `batch-gate`: the work route's own Gate, normally a zero increment. R12 + enters only when its Card's self-stated scenario predicate holds. + +Task-level conditional phases are reached only when their transition is +actually attempted: + +- `governance`: the R09 set, entered only by a real in-batch Standards + governance transfer. +- `task-completion`: the R08 set, entered only by a completion-candidate + transition. + +The tiers are separated because their triggers are of different kinds. A batch +phase follows from execution; a conditional phase follows from a task-level +transition most batches never make, and charging every batch for those sets is +the waste this protocol exists to remove. + +## Route To Phase Mapping + +The mapping is deterministic: R01 to `batch-preflight` always; R09 to +`governance`; R08 to `task-completion`; R12 to `batch-gate`; every other +selected route to `batch-preflight`. The batch Work Spec MAY narrow that last +case through the optional `required_route_ids` field. Absent the field the +default is every selected non-conditional route, so an unrevised Work Spec +behaves exactly as it did before. + +The Card Index leaves the required set of every phase. It is a registry rather +than a route, and routing disputes are rare enough that carrying it at +preflight charges each batch for a lookup few need; it becomes one declared +rule in `readback_plan` and is retrieved when a dispute makes it worth reading. + +## Frozen Phase Plan + +Admission freezes four things, at the same moment v3 froze its manifest: + +1. the phase set, the route-to-phase mapping, the phase transition predicates, + and each phase's piece computation rule; +2. one `{piece_id, kind, path, sha256, bytes, phase}` record for every piece of + every potential phase, conditional phases included; +3. the environment fingerprint: `standards_version`, + `profile_snapshot_sha256`, `profile_contract_fingerprint`, + `resolver_version` (the `card_activation` tool version), `work_spec_sha256`, + and `card_index_sha256`; +4. their composite `phase_plan_sha256`. + +Conditional pieces are frozen although most batches never receive them. A plan +computed at the transition would be computed under later bytes, and the batch +could then enter `governance` under a content identity its own admission never +committed to. `phase_plan_sha256` is the attempt-level anchor on which v4 +dispatches producer-era replay. + +## Phase Packages + +A phase is delivered as its pieces greedily packed into N parts against the +budget owned by K13/19: one part per tool result, each carrying a trailing +single-use nonce exactly as a v3 single piece does. Acks are per part, while +ack accounting remains a set of pieces, so the delivery arithmetic of K13/20 is +unchanged by the repackaging. + +A standard phase -- `batch-preflight` or `batch-gate` -- MUST pack into +`part_count == 1`. More than one part is not a transport failure but a design +signal: that phase's set has outgrown what a worker can be handed at one +boundary, and the Cards or leaf sizes behind it are what must change. +Conditional phases MAY use several parts, because their sets are entered rarely +and sized by the transition rather than by the budget. + +## Invalidation + +Any change to a frozen input -- Standards version, Profile snapshot or +contract, resolver version, Work Spec, Card Index, or any piece hash -- changes +`phase_plan_sha256` and voids the plan whole. Recovery is reactivation under +current bytes, never patching one phase into a plan that no longer describes +it. + +## Related + +- [[kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery|Card Context Activation and Read-back Delivery]] +- [[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate|Assignment State and Delivery Gate]] +- [[kernel/K00 Standards Control/02 Task Routing|Task Routing]] +- [[kernel/K00 Standards Control/15 Read Set Loading Boundaries|Read Set Loading Boundaries]] diff --git a/kernel/Read Sets/R01 Core Bootstrap Read Set.md b/kernel/Read Sets/R01 Core Bootstrap Read Set.md index 2f879cd..c4cf0c0 100644 --- a/kernel/Read Sets/R01 Core Bootstrap Read Set.md +++ b/kernel/Read Sets/R01 Core Bootstrap Read Set.md @@ -22,6 +22,7 @@ Read in order: 9. [[kernel/K00 Standards Control/17 Profile Dependency Closure|Profile Dependency Closure]] 10. [[kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery|Card Context Activation and Read-back Delivery]] 11. [[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate|Assignment State and Delivery Gate]] +12. [[kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan|Phased Reading Plan]] Then select the task-specific Read Set from the [[kernel/Read Sets/Read Sets Index|Read Sets Index]]. diff --git a/kernel/Read Sets/R07 Long-running Execution Read Set.md b/kernel/Read Sets/R07 Long-running Execution Read Set.md index d4853c3..029a0cc 100644 --- a/kernel/Read Sets/R07 Long-running Execution Read Set.md +++ b/kernel/Read Sets/R07 Long-running Execution Read Set.md @@ -26,6 +26,7 @@ First read [[kernel/Read Sets/R01 Core Bootstrap Read Set|Core Bootstrap]], then - [[kernel/K13 Task Runtime and Execution Control/10 Batch Admission Transitions and Serial Integration|Batch Admission Transitions and Serial Integration]] - [[kernel/K13 Task Runtime and Execution Control/19 Card Context Activation and Read-back Delivery|Card Context Activation and Read-back Delivery]] - [[kernel/K13 Task Runtime and Execution Control/20 Assignment State and Delivery Gate|Assignment State and Delivery Gate]] +- [[kernel/K13 Task Runtime and Execution Control/21 Phased Reading Plan|Phased Reading Plan]] - [[kernel/K13 Task Runtime and Execution Control/14 Interruption Recovery and Rollover|Interruption Recovery and Rollover]] - [[kernel/K12 Quality Assurance/03 Module and Coverage Review|Module and Coverage Review]] - [[kernel/K12 Quality Assurance/14 Batch Review|Batch Review]]