Prepare INFD-WP-0002-T03 sitting without a fake bind.
T08 historically bound three SECRETS-WP-0010-T03 memos on this origin. Live accept is closed: /readyz 503 because audit-core has no ready endpoints. Compact drafts still lack approval_id. Operator packet and preflight record the gates; T03 stays wait. Assistant: grok Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
This commit is contained in:
parent
98aa4547a9
commit
6a386dd787
8 changed files with 413 additions and 3 deletions
74
docs/batches/2026-09-14/OPERATOR.md
Normal file
74
docs/batches/2026-09-14/OPERATOR.md
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Compact sitting — operator packet (INFD-WP-0002-T03)
|
||||||
|
|
||||||
|
Review group: `net-kingdom-admins`.
|
||||||
|
Surface: https://decisions.coulomb.social/
|
||||||
|
Contract: `docs/specs/CompactSignoffBatches.md`.
|
||||||
|
|
||||||
|
An agent may draft, order, and record evidence. It may not `accept` / `decline` / `seal`.
|
||||||
|
Do not mark INFD-WP-0002 finished on a partial sitting.
|
||||||
|
|
||||||
|
## What is already proven
|
||||||
|
|
||||||
|
On 2026-09-14 around 01:06 UTC this origin took **three real human accepts**
|
||||||
|
for `SECRETS-WP-0010-T03-{apply,verify,exec}`: presentations, required-highlight
|
||||||
|
acknowledgments, `accept` dispositions, and confirmed approval-engine
|
||||||
|
submissions are in the review store. That discharges “can a human bind through
|
||||||
|
this surface?” for T08 historically.
|
||||||
|
|
||||||
|
Those three memos are **not** this sitting. `infd-20260914-c01` asks a different
|
||||||
|
question (admit native delivery) and must not reuse those approval ids.
|
||||||
|
|
||||||
|
## What is closed right now (2026-09-14 16:56 UTC)
|
||||||
|
|
||||||
|
Live accept is refused:
|
||||||
|
|
||||||
|
- Origin `/healthz` 200; `/auth/start` 303 to KeyCape (`informed-decision-approver`, PKCE S256).
|
||||||
|
- Origin `/readyz` **503** `approval_path_not_connected`.
|
||||||
|
- `audit-core` pod Ready=false; `/readyz` hangs; Service has no ready endpoints;
|
||||||
|
the review pod gets connection refused talking to `audit-core.audit-core.svc:8080`.
|
||||||
|
- Accept requires recent audit delivery health. Until that Service has a ready
|
||||||
|
endpoint, a new sitting cannot submit entries.
|
||||||
|
|
||||||
|
Evidence: `docs/evidence/2026-09-14-infd-0002-t03-bind-path-probe.json`.
|
||||||
|
Audit-core owns the hang; this packet does not change that deployment.
|
||||||
|
|
||||||
|
## Eight unsigned memos (this sitting)
|
||||||
|
|
||||||
|
Open in this order. One question each. No approve-all.
|
||||||
|
|
||||||
|
| n | memo_id | Blocking record |
|
||||||
|
| --: | --- | --- |
|
||||||
|
| 1 | `infd-20260914-c01` | SECRETS-WP-0010 native delivery |
|
||||||
|
| 2 | `infd-20260914-c02` | RPF-WP-0035-T02 |
|
||||||
|
| 3 | `infd-20260914-c03` | NK-WP-0032-T03 |
|
||||||
|
| 4 | `infd-20260914-c04` | WARDEN-WP-0027-T02 |
|
||||||
|
| 5 | `infd-20260914-d01` | CUST-WP-0038-T08 |
|
||||||
|
| 6 | `infd-20260914-d02` | HFACT-WP-0001-T03 |
|
||||||
|
| 7 | `infd-20260914-d03` | MASON-WP-0005 plan |
|
||||||
|
| 8 | `infd-20260914-d04` | RCLK-WP-0002-T01 |
|
||||||
|
|
||||||
|
Drafts still have `approval_id: null` and principal `pending-human-session`.
|
||||||
|
The live controller refuses those with `missing_act_binding` / `wrong_recipient`.
|
||||||
|
They are not in the live store.
|
||||||
|
|
||||||
|
## After audit-core is Ready
|
||||||
|
|
||||||
|
1. Confirm `GET https://decisions.coulomb.social/readyz` returns 200, or run
|
||||||
|
`uv run python tools/sitting_bind_preflight.py --origin https://decisions.coulomb.social`.
|
||||||
|
2. For **each** memo, the owning requester creates one `approval-engine` object
|
||||||
|
with `human_control=true`, required_count 1, no entries. Do **not** reuse
|
||||||
|
`secrets-engine-requester` for unrelated acts (WSL2 retirement, clock
|
||||||
|
ownership, mason plan, …).
|
||||||
|
3. Substitute the operator’s live KeyCape `sub` for `pending-human-session`.
|
||||||
|
Carry the native `approval_id` and `binding.digest` on the memo. Do not
|
||||||
|
invent a digest.
|
||||||
|
4. Load packet bytes then `save_memo` into the review store (named-memo form,
|
||||||
|
no inbox).
|
||||||
|
5. Sign in at the origin. Open `/review?memo_id=infd-20260914-c01` through
|
||||||
|
`…-d04` in order. Acknowledge the required highlight. Bind that memo. Repeat.
|
||||||
|
6. Unfinished memos stay in the batch. File-level owning-repo updates are T04
|
||||||
|
after a human bind, via `fix-consistency`, never `POST /workplans/`.
|
||||||
|
|
||||||
|
A recorded desktop sitting (same order, same highlights, `view_hash` from
|
||||||
|
`presentation.render` only) is allowed if the Stage 1 UI still cannot take the
|
||||||
|
group. It is still a human bind. An agent must not complete the form.
|
||||||
|
|
@ -18,4 +18,10 @@ Two batches, eight memos, one compact sitting:
|
||||||
|
|
||||||
Contract: `docs/specs/CompactSignoffBatches.md`.
|
Contract: `docs/specs/CompactSignoffBatches.md`.
|
||||||
Regenerate: `uv run python tools/prepare_compact_batches.py`.
|
Regenerate: `uv run python tools/prepare_compact_batches.py`.
|
||||||
Live bind waits on `INFD-WP-0001-T08`.
|
Preflight: `uv run python tools/sitting_bind_preflight.py --origin https://decisions.coulomb.social`.
|
||||||
|
Operator packet: `OPERATOR.md`.
|
||||||
|
|
||||||
|
T08 already took three human accepts on this origin for `SECRETS-WP-0010-T03-*`.
|
||||||
|
Those memos are not this sitting. Live accept is currently closed
|
||||||
|
(`/readyz` 503) because audit-core has no ready Service endpoints.
|
||||||
|
This sitting stays `draft-unsigned` until a human binds through the surface.
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,6 @@
|
||||||
"infd-batch-2026-09-14-decisions"
|
"infd-batch-2026-09-14-decisions"
|
||||||
],
|
],
|
||||||
"memo_count": 8,
|
"memo_count": 8,
|
||||||
"bind_path": "INFD-WP-0001-T08 (not yet complete)",
|
"bind_path": "INFD-WP-0001-T08 historically proven; live accept closed 2026-09-14T16:56:55Z",
|
||||||
"note": "Unsigned drafts. Do not submit until CompactSignoffBatches.md is accepted. Live bind substitutes pending-human-session with the authenticated key-cape subject."
|
"note": "Unsigned drafts. Do not submit until a human sitting is opened under T03. Live bind substitutes pending-human-session with the authenticated key-cape subject. Probe: docs/evidence/2026-09-14-infd-0002-t03-bind-path-probe.json. Operator packet: OPERATOR.md."
|
||||||
}
|
}
|
||||||
|
|
|
||||||
83
docs/evidence/2026-09-14-infd-0002-t03-bind-path-probe.json
Normal file
83
docs/evidence/2026-09-14-infd-0002-t03-bind-path-probe.json
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
{
|
||||||
|
"kind": "infd-wp-0002-t03-bind-path-probe",
|
||||||
|
"observed_at": "2026-09-14T16:56:55Z",
|
||||||
|
"workplan": "INFD-WP-0002",
|
||||||
|
"task": "INFD-WP-0002-T03",
|
||||||
|
"scope": "Live bind-path diagnosis for the compact sitting. No human login, no presentation, no disposition, no approval create, no secret read.",
|
||||||
|
"origin": {
|
||||||
|
"url": "https://decisions.coulomb.social/",
|
||||||
|
"tls_verify": 0,
|
||||||
|
"healthz": {"http": 200, "body": {"status": "ok"}},
|
||||||
|
"readyz": {
|
||||||
|
"http": 503,
|
||||||
|
"body": {"status": "incomplete", "reason": "approval_path_not_connected"}
|
||||||
|
},
|
||||||
|
"auth_start": {
|
||||||
|
"http": 303,
|
||||||
|
"location_host": "kc.coulomb.social",
|
||||||
|
"client_id": "informed-decision-approver",
|
||||||
|
"redirect_uri": "https://decisions.coulomb.social/auth/callback",
|
||||||
|
"scopes": ["openid", "approval:read", "approval:approve"],
|
||||||
|
"pkce": "S256"
|
||||||
|
},
|
||||||
|
"unsigned_home": "Sign in with KeyCape only; memo form is session-gated"
|
||||||
|
},
|
||||||
|
"cluster": {
|
||||||
|
"informed-decision": {
|
||||||
|
"namespace": "informed-decision",
|
||||||
|
"pod": "informed-decision-b7f6fc6c9-kd4bl",
|
||||||
|
"ready": true,
|
||||||
|
"start_time": "2026-09-14T01:30:01Z",
|
||||||
|
"image": "forgejo.coulomb.social/coulomb/informed-decision@sha256:8f55bcecf37a8d65f96e073510b1ffb4636c0a91d75e1ee7d582ad4bce8b953a"
|
||||||
|
},
|
||||||
|
"approval-engine": {
|
||||||
|
"namespace": "approval-engine",
|
||||||
|
"pod": "approval-engine-0",
|
||||||
|
"ready": true,
|
||||||
|
"in_cluster_healthz": {"http": 200, "body": {"status": "ok"}}
|
||||||
|
},
|
||||||
|
"audit-core": {
|
||||||
|
"namespace": "audit-core",
|
||||||
|
"pod": "audit-core-7cb66768cf-pq6pw",
|
||||||
|
"ready": false,
|
||||||
|
"started_at": "2026-09-11T08:27:26Z",
|
||||||
|
"restarts": 0,
|
||||||
|
"local_healthz": {"http": 200},
|
||||||
|
"local_readyz": "timeout (>8s); kubelet probe timeoutSeconds=2 on /readyz",
|
||||||
|
"service_cluster_ip": "10.43.74.236",
|
||||||
|
"classic_endpoints": "no ready addresses; one notReadyAddresses entry",
|
||||||
|
"from_informed_decision_pod": "connection refused to audit-core.audit-core.svc:8080"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"review_store_counts": {
|
||||||
|
"schema_version": 2,
|
||||||
|
"sqlite_mtime_in_pod": "2026-09-14T01:06:00Z approximately",
|
||||||
|
"memos": 3,
|
||||||
|
"presentations": 3,
|
||||||
|
"acknowledgments": 3,
|
||||||
|
"dispositions": {"accept": 3},
|
||||||
|
"submissions": {"confirmed": 3},
|
||||||
|
"outbox": {"delivered": 15},
|
||||||
|
"memo_ids": [
|
||||||
|
"SECRETS-WP-0010-T03-apply",
|
||||||
|
"SECRETS-WP-0010-T03-exec",
|
||||||
|
"SECRETS-WP-0010-T03-verify"
|
||||||
|
],
|
||||||
|
"note": "Counts and identifiers only. No packet bytes, principals, view_hash values, or approval entry bodies were copied out of the store."
|
||||||
|
},
|
||||||
|
"compact_sitting": {
|
||||||
|
"id": "infd-sitting-2026-09-14",
|
||||||
|
"status": "draft-unsigned",
|
||||||
|
"memo_count": 8,
|
||||||
|
"approval_ids": "all null",
|
||||||
|
"principal": "pending-human-session",
|
||||||
|
"in_live_store": false
|
||||||
|
},
|
||||||
|
"conclusion": {
|
||||||
|
"t08_historical_bind": "Three real human accept dispositions with confirmed engine submissions already exist on this surface for the SECRETS-WP-0010-T03 named memos. That sitting is not the INFD-WP-0002 compact batch.",
|
||||||
|
"t03_live_accept": "closed",
|
||||||
|
"reason": "informed-decision /readyz is 503 because audit-core is not Ready, its Service has no ready endpoints, and accept is refused while pump.ready() is false.",
|
||||||
|
"agent_disposition": "forbidden",
|
||||||
|
"infd_wp_0002_t03": "wait"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -50,3 +50,11 @@ a human bind (T04), via repo files + `fix-consistency`, never
|
||||||
`docs/batches/2026-09-14/` — four credential/custody memos and four
|
`docs/batches/2026-09-14/` — four credential/custody memos and four
|
||||||
decision/assent memos. Indexes name the blocking workplan/task. Do not
|
decision/assent memos. Indexes name the blocking workplan/task. Do not
|
||||||
submit until a human sitting is opened under T03.
|
submit until a human sitting is opened under T03.
|
||||||
|
|
||||||
|
2026-09-14 16:56 UTC: Stage 1 historically bound three other memos
|
||||||
|
(`SECRETS-WP-0010-T03-*`) on this origin. New accepts are closed while
|
||||||
|
`GET /readyz` returns 503 (`approval_path_not_connected`) because
|
||||||
|
audit-core is not Ready and its Service has no ready endpoints. Compact
|
||||||
|
memos still have `approval_id: null`. Operator packet:
|
||||||
|
`docs/batches/2026-09-14/OPERATOR.md`. Preflight:
|
||||||
|
`tools/sitting_bind_preflight.py`.
|
||||||
|
|
|
||||||
78
tests/test_sitting_bind_preflight.py
Normal file
78
tests/test_sitting_bind_preflight.py
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
import importlib.util
|
||||||
|
from io import BytesIO
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
spec = importlib.util.spec_from_file_location(
|
||||||
|
"sitting_bind_preflight",
|
||||||
|
Path(__file__).resolve().parents[1] / "tools" / "sitting_bind_preflight.py",
|
||||||
|
)
|
||||||
|
preflight = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(preflight)
|
||||||
|
evaluate, load_sitting, probe_origin = preflight.evaluate, preflight.load_sitting, preflight.probe_origin
|
||||||
|
|
||||||
|
|
||||||
|
class _Resp:
|
||||||
|
def __init__(self, status, body=b"", headers=None):
|
||||||
|
self.status = status
|
||||||
|
self.headers = headers or {}
|
||||||
|
self._body = BytesIO(body)
|
||||||
|
|
||||||
|
def getcode(self):
|
||||||
|
return self.status
|
||||||
|
|
||||||
|
def read(self, n=-1):
|
||||||
|
return self._body.read(n)
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, *exc):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def test_unsigned_sitting_is_not_ready_to_sit():
|
||||||
|
report = evaluate(load_sitting())
|
||||||
|
assert report["ready_to_sit"] is False
|
||||||
|
assert report["agent_disposition"] == "forbidden"
|
||||||
|
assert report["memo_count"] == 8
|
||||||
|
assert "missing_act_binding" in report["gates"]
|
||||||
|
assert "principal_not_live_subject" in report["gates"]
|
||||||
|
assert len(report["missing_act_binding"]) == 8
|
||||||
|
assert report["live_accept"] is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_origin_readyz_503_is_live_accept_closed():
|
||||||
|
bodies = {
|
||||||
|
"/healthz": _Resp(200, b'{"status":"ok"}'),
|
||||||
|
"/readyz": _Resp(503, b'{"status":"incomplete","reason":"approval_path_not_connected"}'),
|
||||||
|
"/auth/start": _Resp(303, b"", {"Location": "https://kc.coulomb.social/authorize?client_id=informed-decision-approver"}),
|
||||||
|
}
|
||||||
|
|
||||||
|
def opener(req, timeout=10):
|
||||||
|
return bodies[req.full_url.split("https://decisions.coulomb.social", 1)[1]]
|
||||||
|
|
||||||
|
probe = probe_origin("https://decisions.coulomb.social", opener=opener)
|
||||||
|
report = evaluate(load_sitting(), probe)
|
||||||
|
assert report["live_accept"] == "closed"
|
||||||
|
assert "live_accept_closed" in report["gates"]
|
||||||
|
assert report["ready_to_sit"] is False
|
||||||
|
assert probe["auth_start"]["http"] == 303
|
||||||
|
assert probe["auth_start"]["location_host"] == "kc.coulomb.social"
|
||||||
|
assert "body" not in probe["auth_start"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_origin_ready_still_blocked_on_unsigned_memos():
|
||||||
|
bodies = {
|
||||||
|
"/healthz": _Resp(200, b'{"status":"ok"}'),
|
||||||
|
"/readyz": _Resp(200, b'{"status":"ready"}'),
|
||||||
|
"/auth/start": _Resp(303, b"", {"Location": "https://kc.example/authorize"}),
|
||||||
|
}
|
||||||
|
|
||||||
|
def opener(req, timeout=10):
|
||||||
|
return bodies[req.full_url.split("https://origin.example", 1)[1]]
|
||||||
|
|
||||||
|
report = evaluate(load_sitting(), probe_origin("https://origin.example", opener=opener))
|
||||||
|
assert report["live_accept"] == "open"
|
||||||
|
assert "live_accept_closed" not in report["gates"]
|
||||||
|
assert report["ready_to_sit"] is False
|
||||||
|
assert "missing_act_binding" in report["gates"]
|
||||||
146
tools/sitting_bind_preflight.py
Normal file
146
tools/sitting_bind_preflight.py
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
"""INFD-WP-0002-T03 sitting bind preflight.
|
||||||
|
|
||||||
|
Reports whether the compact sitting can be submitted to the live Stage 1
|
||||||
|
surface. Does not present, acknowledge, bind, or create approvals.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from urllib.error import HTTPError, URLError
|
||||||
|
from urllib.request import HTTPRedirectHandler, Request, build_opener, urlopen
|
||||||
|
|
||||||
|
from informed_decision.records import memo_from
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1] / "docs" / "batches" / "2026-09-14"
|
||||||
|
|
||||||
|
|
||||||
|
def load_sitting(root: Path = ROOT) -> dict:
|
||||||
|
sitting = json.loads((root / "sitting.json").read_text())
|
||||||
|
memos = []
|
||||||
|
for name in ("credentials", "decisions"):
|
||||||
|
index = json.loads((root / name / "index.json").read_text())
|
||||||
|
for row in index["ordinal"]:
|
||||||
|
memo = memo_from(json.loads((root / name / row["memo"]).read_text()))
|
||||||
|
memos.append(
|
||||||
|
{
|
||||||
|
"batch": name,
|
||||||
|
"memo_id": memo.id,
|
||||||
|
"approval_id": memo.approval_id,
|
||||||
|
"principal": memo.binding.principal.id,
|
||||||
|
"question": memo.question,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return {"sitting": sitting, "memos": memos}
|
||||||
|
|
||||||
|
|
||||||
|
class _NoRedirect(HTTPRedirectHandler):
|
||||||
|
def http_error_302(self, req, fp, code, msg, headers):
|
||||||
|
raise HTTPError(req.full_url, code, msg, headers, fp)
|
||||||
|
|
||||||
|
http_error_301 = http_error_303 = http_error_307 = http_error_308 = http_error_302
|
||||||
|
|
||||||
|
|
||||||
|
def _default_opener():
|
||||||
|
return build_opener(_NoRedirect()).open
|
||||||
|
|
||||||
|
|
||||||
|
def probe_origin(origin: str, opener=None) -> dict:
|
||||||
|
origin = origin.rstrip("/")
|
||||||
|
fetch = opener or _default_opener()
|
||||||
|
result = {"origin": origin, "healthz": None, "readyz": None, "auth_start": None}
|
||||||
|
|
||||||
|
def get(path):
|
||||||
|
req = Request(origin + path, method="GET")
|
||||||
|
try:
|
||||||
|
with fetch(req, timeout=10) as response:
|
||||||
|
return _probe_row(response, getattr(response, "status", None) or response.getcode())
|
||||||
|
except HTTPError as exc:
|
||||||
|
return _probe_row(exc, exc.code)
|
||||||
|
except (URLError, TimeoutError, OSError) as exc:
|
||||||
|
return {"http": None, "error": type(exc).__name__}
|
||||||
|
|
||||||
|
result["healthz"] = get("/healthz")
|
||||||
|
result["readyz"] = get("/readyz")
|
||||||
|
result["auth_start"] = get("/auth/start")
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _probe_row(response, status):
|
||||||
|
headers = getattr(response, "headers", None)
|
||||||
|
location = headers.get("Location") if headers else None
|
||||||
|
raw = response.read(4096)
|
||||||
|
try:
|
||||||
|
body = json.loads(raw.decode("utf-8")) if raw else None
|
||||||
|
except (UnicodeDecodeError, json.JSONDecodeError):
|
||||||
|
body = None
|
||||||
|
row = {"http": status}
|
||||||
|
if location:
|
||||||
|
row["location_host"] = location.split("/")[2] if "://" in location else location
|
||||||
|
if isinstance(body, dict):
|
||||||
|
row["status"] = body.get("status")
|
||||||
|
if "reason" in body:
|
||||||
|
row["reason"] = body.get("reason")
|
||||||
|
return row
|
||||||
|
|
||||||
|
|
||||||
|
def evaluate(bundle: dict, origin_probe: dict | None = None) -> dict:
|
||||||
|
sitting = bundle["sitting"]
|
||||||
|
memos = bundle["memos"]
|
||||||
|
missing_act = [row["memo_id"] for row in memos if not row["approval_id"]]
|
||||||
|
pending_principal = [row["memo_id"] for row in memos if row["principal"] == "pending-human-session"]
|
||||||
|
gates = []
|
||||||
|
if sitting.get("status") != "draft-unsigned" or sitting.get("submitted") is True:
|
||||||
|
gates.append("sitting_already_submitted")
|
||||||
|
if len(memos) != 8:
|
||||||
|
gates.append("unexpected_memo_count")
|
||||||
|
if missing_act:
|
||||||
|
gates.append("missing_act_binding")
|
||||||
|
if pending_principal:
|
||||||
|
gates.append("principal_not_live_subject")
|
||||||
|
live_accept = None
|
||||||
|
if origin_probe is not None:
|
||||||
|
health = (origin_probe.get("healthz") or {}).get("http")
|
||||||
|
ready = (origin_probe.get("readyz") or {}).get("http")
|
||||||
|
start = (origin_probe.get("auth_start") or {}).get("http")
|
||||||
|
if health != 200:
|
||||||
|
gates.append("origin_healthz_not_ok")
|
||||||
|
if start not in (302, 303):
|
||||||
|
gates.append("auth_start_not_redirect")
|
||||||
|
if ready != 200:
|
||||||
|
gates.append("live_accept_closed")
|
||||||
|
live_accept = "closed"
|
||||||
|
else:
|
||||||
|
live_accept = "open"
|
||||||
|
ready_to_sit = not gates
|
||||||
|
return {
|
||||||
|
"kind": "informed-decision-sitting-preflight",
|
||||||
|
"sitting_id": sitting.get("id"),
|
||||||
|
"memo_count": len(memos),
|
||||||
|
"missing_act_binding": missing_act,
|
||||||
|
"principal_not_live_subject": pending_principal,
|
||||||
|
"live_accept": live_accept,
|
||||||
|
"gates": gates,
|
||||||
|
"ready_to_sit": ready_to_sit,
|
||||||
|
"agent_disposition": "forbidden",
|
||||||
|
"origin_probe": origin_probe,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("--origin", help="Probe this Stage 1 origin; omit for file checks only")
|
||||||
|
parser.add_argument("--receipt", type=Path, help="Write the JSON report")
|
||||||
|
args = parser.parse_args()
|
||||||
|
probe = probe_origin(args.origin) if args.origin else None
|
||||||
|
report = evaluate(load_sitting(), probe)
|
||||||
|
text = json.dumps(report, indent=2, ensure_ascii=False) + "\n"
|
||||||
|
if args.receipt:
|
||||||
|
args.receipt.write_text(text, encoding="utf-8")
|
||||||
|
print(text, end="")
|
||||||
|
return 0 if report["ready_to_sit"] else 2
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
|
|
@ -116,6 +116,21 @@ by a human through this surface, reconstructable from stored
|
||||||
presentation, and the blocking hub tasks are updated from those
|
presentation, and the blocking hub tasks are updated from those
|
||||||
dispositions rather than from chat.
|
dispositions rather than from chat.
|
||||||
|
|
||||||
|
2026-09-14 — **T08 bind path historically proven; this sitting still
|
||||||
|
cannot run.** Probe
|
||||||
|
`docs/evidence/2026-09-14-infd-0002-t03-bind-path-probe.json`.
|
||||||
|
The live store already holds three `accept` dispositions with confirmed
|
||||||
|
engine submissions for `SECRETS-WP-0010-T03-{apply,verify,exec}`
|
||||||
|
(presentations + required acks). That is not this batch. Compact memos
|
||||||
|
remain `approval_id: null` / `pending-human-session` and are not in the
|
||||||
|
store. New accept is refused: origin `/readyz` 503
|
||||||
|
`approval_path_not_connected` because `audit-core` is not Ready, its
|
||||||
|
Service has no ready endpoints, and the review pod gets connection
|
||||||
|
refused talking to the audit ClusterIP. Operator packet
|
||||||
|
`docs/batches/2026-09-14/OPERATOR.md`; preflight
|
||||||
|
`tools/sitting_bind_preflight.py`. No agent disposition. Task stays
|
||||||
|
`wait`.
|
||||||
|
|
||||||
## Feed outcomes back to State Hub without hub-authoring
|
## Feed outcomes back to State Hub without hub-authoring
|
||||||
|
|
||||||
```task
|
```task
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue