206 lines
8.6 KiB
Python
206 lines
8.6 KiB
Python
"""Admission dispatch for wave wave-consent-bridge: the chat→task consent
|
|
card, phase 1 (owner-approved queue item 2a — the dichotomy's y/n card).
|
|
|
|
classify + activate + admit (the headless scaffolding entry law,
|
|
scripts/admit_wave_k27_composer_depth.py exemplar), admitted through the
|
|
research gate on the consent bridge's own round chain
|
|
research/factory-consent-bridge/07-qualify.json (registry entry
|
|
factory-consent-bridge, verdict PROCEED).
|
|
|
|
Artifacts this wave admits: tui/consent (the phase-1 deterministic
|
|
bridge — tier-0 declared promote language via the promote SA-D3 ladder's
|
|
explicit class, tier-1 structural suppression gate in the
|
|
construction_intent style, the one-live-card lifecycle with the
|
|
STALE_GAP_TURNS=2 lapse law, the BriefRecord consent-time snapshot, the
|
|
gold y/n strip render with default focus No), the card's wiring into the
|
|
shell (observe on chat sends/replies, y → enqueue through the
|
|
task-queue admission carrying the brief, n/Esc → dismiss demoting to the
|
|
promote hold queue), and the red-first frozen batteries. Tier-2 (model
|
|
self-report work_intent envelope) is NOT built — the synthesis phases it
|
|
as phase 2 behind kill tests K1-K3 and owner decision OD-B.
|
|
|
|
Still wiring (main session lands): the core-side widening of the task
|
|
envelope/ledger Brief slot beyond the enqueue surface's text field.
|
|
"""
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
|
|
|
|
from rune import construction_activation as cact # noqa: E402
|
|
from rune import construction_admission as cadm # noqa: E402
|
|
from rune import construction_mode as cmode # noqa: E402
|
|
from rune import scaffold as sc # noqa: E402
|
|
|
|
ROOT = os.path.join(os.path.dirname(__file__), "..")
|
|
|
|
SLUG = "wave-consent-bridge"
|
|
RESEARCH_SLUG = "factory-consent-bridge"
|
|
|
|
OBJECTIVE = (
|
|
"construct the consent bridge phase 1 (owner-approved queue item 2a; "
|
|
"openspec add-native-rune-tui task 2.2's importance-aware promotion, "
|
|
"suggested-task accept/dismiss leg): when a chat message is really a "
|
|
"work request, Rune proposes starting it as a task via one live y/n "
|
|
"card at the chat pane's bottom; on y the task starts immediately "
|
|
"carrying the conversation's context. Detection tiers 0-1 "
|
|
"deterministic only: tier-0 declared promote language (the SA-D3 "
|
|
"explicit class — idiom prefixes stripped, imperative verb, not "
|
|
"keyword spam) and tier-1 structural suppression (interrogative + "
|
|
"analysis markers suppress the card; everything ambiguous passes — "
|
|
"recall-preserving, in the construction_intent resolver's style). "
|
|
"The card: one live card per chat channel, non-modal, composer keeps "
|
|
"focus, y/n keys bind only while the composer is empty, DEFAULT "
|
|
"FOCUS NO, keyboard-first with click equivalents; a newer proposal "
|
|
"supersedes; lapse after 2 recorded turns (STALE_GAP_TURNS) demotes "
|
|
"to the promote hold queue — a proposal never dies silently. Consent "
|
|
"captures the BriefRecord snapshot AT CONSENT TIME (triggering msg "
|
|
"id + verbatim text, brief statement, evidence refs, channel) and "
|
|
"the enqueue carries it through the task-queue admission (never "
|
|
"preempting a running turn). Dismissal demotes to the promote hold "
|
|
"queue with a receipt. Tier-2 model self-report is NOT built (phase "
|
|
"2, kill tests K1-K3 + owner decision OD-B). Frozen tests: "
|
|
"detection table, lapse state machine, BriefRecord verbatim "
|
|
"immutability, card render exact-width + button geometry, key "
|
|
"universe (typing never answers a card). Red-first."
|
|
)
|
|
AFFECTED = [
|
|
"tui/consent/consent.go",
|
|
"tui/consent/render.go",
|
|
"tui/consent/consent_test.go",
|
|
"tui/promote/promote.go",
|
|
"tui/promote/promote_hold_test.go",
|
|
"tui/tasks/face.go",
|
|
"tui/cmd/rune-tui/main.go",
|
|
"tui/consent/README.md",
|
|
]
|
|
|
|
def record_research_gate(marker: str) -> int:
|
|
store_dir = os.path.join(ROOT, "store", "scaffold")
|
|
scaffold = sc.Scaffold(store_dir, "rune")
|
|
doc = scaffold.load()
|
|
c = scaffold.contract(doc, f"ADMIT-{SLUG}")
|
|
if c is None:
|
|
print("contract ADMIT-<slug> not found — nothing to record")
|
|
return 1
|
|
ext = c.setdefault("ext", {})
|
|
rg = ext.get("research_gate") or {}
|
|
rg.update({
|
|
"chain": "research/factory-consent-bridge/07-qualify.json",
|
|
"verdict": "PROCEED",
|
|
"marker": marker,
|
|
"note": "consent bridge phase 1 (queue item 2a): tiers 0-1 + "
|
|
"card + snapshot + hold-queue demotion; tier-2 stays "
|
|
"phase 2 behind kill tests K1-K3 and OD-B",
|
|
})
|
|
ext["research_gate"] = rg
|
|
scaffold.commit(doc, what=f"record research_gate evidence for {SLUG}")
|
|
print("research_gate record committed on ADMIT-" + SLUG)
|
|
return 0
|
|
|
|
def main() -> int:
|
|
gate = subprocess.run(
|
|
[sys.executable, os.path.join("scripts", "check_research_gate.py"),
|
|
"admit", "--slug", SLUG, "--objective", OBJECTIVE,
|
|
"--research-slug", RESEARCH_SLUG],
|
|
capture_output=True, text=True, cwd=ROOT,
|
|
)
|
|
print(gate.stdout.strip())
|
|
if gate.returncode != 0:
|
|
print("research gate REFUSED — the law holds")
|
|
return 1
|
|
marker = ""
|
|
for line in gate.stdout.splitlines():
|
|
if line.startswith("research-gate:ALLOW") or line.startswith("exempt:research-gate:"):
|
|
marker = line.strip()
|
|
break
|
|
if not marker:
|
|
print("no ALLOW marker in gate output — refusing to mint unrecorded")
|
|
return 1
|
|
|
|
store = os.path.join(ROOT, "store", "scaffold")
|
|
scaffold = sc.Scaffold(store, "rune")
|
|
|
|
md = cmode.classify_mode(
|
|
OBJECTIVE,
|
|
target_project="rune",
|
|
project_exists=True,
|
|
affected_surface=AFFECTED,
|
|
)
|
|
print("classified mode:", md.mode)
|
|
|
|
need = {
|
|
"need_id": f"need-{SLUG}",
|
|
"objective": OBJECTIVE,
|
|
"origin": "worker",
|
|
"project": "rune",
|
|
"task_ref": SLUG,
|
|
"affected_surface": AFFECTED,
|
|
"evidence_refs": [
|
|
marker,
|
|
"research/factory-consent-bridge/06-synthesis.json",
|
|
"research/factory-consent-bridge/07-qualify.json",
|
|
"docs/openspec/changes/add-native-rune-tui/specs/dual-lane-interface/spec.md",
|
|
"docs/openspec/changes/add-native-rune-tui/tasks.md#2.2",
|
|
"src/rune/construction_intent.py",
|
|
"tui/promote/promote.go",
|
|
"tui/approvals/approvals.go",
|
|
"tui/runtime/lib/command.go",
|
|
"tui/vendor/rune/task-state/ledger/ledger.go",
|
|
],
|
|
}
|
|
act = cact.activate(md, need=need, scaffold=scaffold,
|
|
builder=SLUG)
|
|
print("activated:", act.get("activated"), act.get("mode"))
|
|
|
|
env = cadm.admit(
|
|
act,
|
|
objective=OBJECTIVE,
|
|
builder=SLUG,
|
|
affected_surface=AFFECTED,
|
|
evidence_refs=need["evidence_refs"],
|
|
origin="worker",
|
|
task_ref=SLUG,
|
|
expected_new_entities=[
|
|
"tui/consent consent bridge phase 1: tier-0/tier-1 detector "
|
|
"(declared promote language + structural suppression), "
|
|
"one-live-card Hub with STALE_GAP_TURNS lapse law, "
|
|
"BriefRecord consent-time snapshot, gold y/n strip render "
|
|
"(default focus No)",
|
|
"promote.Promote.Hold (the visible-hold demotion path the "
|
|
"card's dismissal and lapse ride)",
|
|
"shell wiring: observe on chat sends/replies, y → enqueue "
|
|
"carrying the brief, n/Esc → hold-queue demotion",
|
|
],
|
|
expected_runtime_effects=[
|
|
"phase-1 deterministic only: no model changes, no prompt "
|
|
"overhead, tier-2 work_intent envelope NOT built (kill "
|
|
"tests K1-K3 + OD-B gate it); the card never creates a "
|
|
"task silently — only consent does; a running turn is "
|
|
"never preempted (enqueue, never interrupt); no commits",
|
|
],
|
|
verification_obligations=[
|
|
"go test ./consent/ ./promote/ -count=1 green in tui/ "
|
|
"(frozen groups: detection table, lapse law, snapshot "
|
|
"immutability, render geometry, key universe, hold "
|
|
"demotion)",
|
|
"gofmt -l and go vet clean on tui/consent",
|
|
"go build ./... green in tui/",
|
|
"python scripts/check_research_gate.py sweep GREEN",
|
|
],
|
|
approval_ref="user:40-scale queue approval 2026-10-19",
|
|
contract_id=f"ADMIT-{SLUG}",
|
|
project_store=store,
|
|
project_id="rune",
|
|
)
|
|
print(json.dumps(env, indent=2, default=str)[:2400])
|
|
rc = 0 if env.get("success") else 1
|
|
if record_research_gate(marker) != 0:
|
|
return 1
|
|
return rc
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|