diff --git a/Cargo.lock b/Cargo.lock index f7d9599f147..0fb931fd9f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -592,9 +592,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.10.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cairo-rs" @@ -1240,11 +1240,10 @@ checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "powerfmt", "serde_core", ] @@ -1578,7 +1577,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -2820,7 +2819,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi 0.5.2", "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3722,9 +3721,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-derive" @@ -4937,7 +4936,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4964,9 +4963,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", @@ -5647,9 +5646,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.44" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" dependencies = [ "filetime", "libc", @@ -5672,7 +5671,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix 1.1.2", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -5857,24 +5856,23 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-funcs" @@ -5893,9 +5891,9 @@ dependencies = [ [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" dependencies = [ "num-conv", "time-core", @@ -7355,7 +7353,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] diff --git a/docs/sourceos/ADR_035_BOUNDARY_TRANSITIONS.md b/docs/sourceos/ADR_035_BOUNDARY_TRANSITIONS.md new file mode 100644 index 00000000000..2ea530e2f9a --- /dev/null +++ b/docs/sourceos/ADR_035_BOUNDARY_TRANSITIONS.md @@ -0,0 +1,184 @@ +# TurtleTerm ADR-035 Boundary Transitions and System-Action Transcript + +## Decision + +TurtleTerm adopts the `prophet-platform` ADR-035 transparent fault attribution contract family. +All system-level actions that cross a process, filesystem, or network boundary emit a typed +`BoundaryTransition` record. Faults are attributed via `FaultEnvelope`. Engine identity is +declared via `EngineManifest`. These records are consumed by sourceos-syncd, agentplane, and +the TurtleTerm operator console. + +## Scope (issue TurtleTerm #17) + +This document covers TurtleTerm's binding to ADR-035 for: + +1. PTY spawn (`process-spawn` boundary) +2. File access for configuration / lua scripts / fonts (`file-read` boundary) +3. Network access for SSH and MUX connections (`network-fetch` boundary) +4. GPU/compositor surface allocation (`render-emit` boundary) +5. Clipboard read/write (`clipboard-read` / `clipboard-write` boundaries) + +## EngineManifest — TurtleTerm + +```json +{ + "id": "urn:srcos:engine-manifest:turtleterm:2026", + "specVersion": "0.1.0", + "engineKind": "terminal-helper", + "engineId": "turtleterm", + "version": "20241230-1", + "declaredBoundaries": [ + "process-spawn", + "file-read", + "network-fetch", + "render-emit", + "clipboard-read", + "clipboard-write" + ], + "allowedInputKinds": [ + "text/x-shellcommand", + "text/x-luascript", + "application/x-ssh-config" + ], + "sideEffectPolicy": "allowed-with-receipt", + "networkEgressPolicy": "policy-gated", + "sandboxKind": "ambient-user-session", + "capabilityContractRef": "urn:srcos:capability-contract:turtleterm:2026", + "orgPolicyRef": "urn:srcos:org-policy:default:2026" +} +``` + +## BoundaryTransition Fixtures + +### PTY spawn (process-spawn, admitted) + +```json +{ + "id": "urn:srcos:boundary-transition:turtleterm:pty-spawn-20260718T120000Z", + "specVersion": "0.1.0", + "engineRef": "urn:srcos:engine-manifest:turtleterm:2026", + "boundaryKind": "process-spawn", + "direction": "egress", + "decision": "admitted", + "policyDecisionRef": "urn:srcos:policy-decision:turtleterm-pty-spawn-admit-20260718", + "commandToken": "bash", + "argsRedacted": true, + "observedAt": "2026-07-18T12:00:00Z" +} +``` + +### SSH connect (network-fetch, policy-gated — admitted) + +```json +{ + "id": "urn:srcos:boundary-transition:turtleterm:ssh-20260718T120100Z", + "specVersion": "0.1.0", + "engineRef": "urn:srcos:engine-manifest:turtleterm:2026", + "boundaryKind": "network-fetch", + "direction": "egress", + "decision": "admitted", + "policyDecisionRef": "urn:srcos:policy-decision:turtleterm-ssh-admit-20260718", + "targetOriginRedacted": true, + "observedAt": "2026-07-18T12:01:00Z" +} +``` + +### Lua script file-read (file-read, admitted) + +```json +{ + "id": "urn:srcos:boundary-transition:turtleterm:lua-file-read-20260718T120200Z", + "specVersion": "0.1.0", + "engineRef": "urn:srcos:engine-manifest:turtleterm:2026", + "boundaryKind": "file-read", + "direction": "ingress", + "decision": "admitted", + "policyDecisionRef": "urn:srcos:policy-decision:turtleterm-lua-read-admit-20260718", + "pathRedacted": true, + "observedAt": "2026-07-18T12:02:00Z" +} +``` + +### Clipboard write (clipboard-write, suppressed — org policy) + +```json +{ + "id": "urn:srcos:boundary-transition:turtleterm:clipboard-write-20260718T120300Z", + "specVersion": "0.1.0", + "engineRef": "urn:srcos:engine-manifest:turtleterm:2026", + "boundaryKind": "clipboard-write", + "direction": "egress", + "decision": "suppressed", + "suppressionReason": "org policy: clipboard-write denied in restricted session", + "policyDecisionRef": "urn:srcos:policy-decision:turtleterm-clipboard-deny-20260718", + "observedAt": "2026-07-18T12:03:00Z" +} +``` + +## FaultEnvelope Fixtures + +### PTY spawn failure (non-fatal — fallback to degraded mode) + +```json +{ + "id": "urn:srcos:fault-envelope:turtleterm:pty-spawn-fail-20260718T130000Z", + "specVersion": "0.1.0", + "engineRef": "urn:srcos:engine-manifest:turtleterm:2026", + "faultClass": "render-failure", + "severity": "non-fatal", + "boundaryTransitionRef": "urn:srcos:boundary-transition:turtleterm:pty-spawn-fail-20260718T130000Z", + "recoveryAction": "emit-receipt-and-exit", + "recoveryOutcome": "succeeded", + "humanReviewRequired": false, + "observedAt": "2026-07-18T13:00:00Z", + "note": "PTY spawn failed (shell not found); TurtleTerm emitted a terminal receipt and displayed error pane." +} +``` + +### SSH policy violation (fatal) + +```json +{ + "id": "urn:srcos:fault-envelope:turtleterm:ssh-policy-violation-20260718T140000Z", + "specVersion": "0.1.0", + "engineRef": "urn:srcos:engine-manifest:turtleterm:2026", + "faultClass": "policy-violation", + "severity": "fatal", + "boundaryTransitionRef": "urn:srcos:boundary-transition:turtleterm:ssh-denied-20260718T140000Z", + "policyDecisionRef": "urn:srcos:policy-decision:turtleterm-ssh-deny-20260718", + "recoveryAction": "refuse-start", + "recoveryOutcome": "succeeded", + "humanReviewRequired": true, + "humanReviewRef": "urn:srcos:review-request:turtleterm-ssh-policy-20260718", + "observedAt": "2026-07-18T14:00:00Z", + "note": "Org policy denied SSH connection to non-allowlisted host. Session terminated. Human review queued." +} +``` + +## System-Action Transcript Integration + +TurtleTerm emits a machine-readable `system-action-transcript.jsonl` alongside each terminal +session. Each line is a `BoundaryTransition` or `FaultEnvelope` JSON object. The transcript is: + +- Written to `~/.local/share/turtleterm/transcripts/.jsonl` +- Consumed by `sourceos-syncd` for state integrity tracking +- Forwarded to `agentplane` when a governed agent session is active +- Never contains raw PTY content, credentials, or clipboard payloads + +### Transcript line ordering + +``` +EngineManifest (once, at session start) +BoundaryTransition[process-spawn] (for each PTY spawn) +BoundaryTransition[file-read]* (for config/lua/font loads) +BoundaryTransition[network-fetch]* (for SSH/MUX connections) +BoundaryTransition[render-emit]* (for GPU surface allocations) +FaultEnvelope* (for any fault) +``` + +## Related + +- `schemas/agent-harness-terminal-receipts.schema.json` — terminal receipt schema +- `docs/sourceos/AGENT_HARNESS_TERMINAL_RECEIPTS.md` — receipt capture contract +- sourceos-shell `docs/adr-035-examples.md` — reference fixtures across shell engines +- sourceos-spec `CapabilityContract.json` — capability declaration schema diff --git a/docs/sourceos/REASONING_RUN_TASK_TREE.md b/docs/sourceos/REASONING_RUN_TASK_TREE.md new file mode 100644 index 00000000000..91f7c37633d --- /dev/null +++ b/docs/sourceos/REASONING_RUN_TASK_TREE.md @@ -0,0 +1,87 @@ +# TurtleTerm: Superconscious ReasoningRun Task Tree and Evidence Rendering + +## Purpose (issue TurtleTerm #6) + +Superconscious emits governed recursive reasoning artifacts. SourceOS reasoning contracts +are being promoted into `SourceOS-Linux/sourceos-spec`. TurtleTerm should render these +as an operator-facing trace/evidence console within the terminal session pane. + +## Design + +### Rendering surface + +TurtleTerm renders ReasoningRun traces in a dedicated split pane alongside the active terminal. +The pane is: + +- Opened by `Ctrl+Shift+R` or via the command palette: `Open ReasoningRun trace` +- Populated from the local `~/.local/share/turtleterm/reasoning//` directory +- Updated live when the active session is backed by an agentplane-governed agent + +### Data format + +Each ReasoningRun is a JSONL file: + +``` +.jsonl +``` + +Each line is one of: +- `{"kind": "run-start", "run_ref": "...", "agent_ref": "...", "goal_ref": "...", "started_at": "..."}` +- `{"kind": "step", "step_index": N, "step_kind": "premise|inference|conclusion|fork", "confidence": 0.0–1.0, "suppress_mutation": true|false}` +- `{"kind": "run-end", "outcome": "success|failure|suppressed", "confidence": 0.0–1.0, "receipt_ref": "..."}` +- `{"kind": "fault", "fault_class": "...", "severity": "fatal|non-fatal", "suppress_mutation": true}` + +### Example JSONL trace + +```jsonl +{"kind": "run-start", "run_ref": "urn:srcos:reasoning-run:sc:20260718T100000Z", "agent_ref": "urn:srcos:agent:superconscious:2026", "goal_ref": "urn:srcos:goal:patch-review:20260718", "started_at": "2026-07-18T10:00:00Z"} +{"kind": "step", "step_index": 0, "step_kind": "premise", "confidence": 0.97, "suppress_mutation": false} +{"kind": "step", "step_index": 1, "step_kind": "inference", "confidence": 0.91, "suppress_mutation": false} +{"kind": "step", "step_index": 2, "step_kind": "conclusion", "confidence": 0.88, "suppress_mutation": false, "policy_decision_ref": "urn:srcos:policy-decision:sc-mutation-admit-20260718"} +{"kind": "run-end", "outcome": "success", "confidence": 0.88, "receipt_ref": "urn:srcos:receipt:sc:20260718T100015Z"} +``` + +### Pane layout + +``` +┌─────────────────────────────────────────────────────────┐ +│ ReasoningRun Trace — urn:srcos:reasoning-run:sc:2026... │ +├───────────────────────────────────────────────┬─────────┤ +│ Step Kind Confidence Suppress │ Status │ +│ 0 premise 0.97 ✗ │ │ +│ 1 inference 0.91 ✗ │ success │ +│ 2 conclusion 0.88 ✗ │ │ +├───────────────────────────────────────────────┴─────────┤ +│ Outcome: success Confidence: 0.88 Receipt: ↗ │ +└─────────────────────────────────────────────────────────┘ +``` + +- `suppress_mutation=true` steps are highlighted in amber +- `fault` lines are highlighted in red +- Confidence < 0.70 triggers a visual warning indicator +- `run-end` with `receipt_ref` shows a clickable `↗` link to the evidence record + +## Integration boundary + +- TurtleTerm reads ReasoningRun JSONL files; it does NOT generate them +- Superconscious is the sole authority for writing ReasoningRun artifacts +- AgentPlane delivers the artifacts to the local path during governed sessions +- TurtleTerm never exposes raw step content — only kind, confidence, and suppress flag + +## Implementation status + +The rendering pane is currently a stub. The data model and JSONL format are defined here. +The live implementation requires: + +1. AgentPlane delivering JSONL to `~/.local/share/turtleterm/reasoning/` +2. A Lua event hook watching that directory for new files +3. A Rust pane renderer reading the JSONL and emitting the table above + +Tracking: issue TurtleTerm #6. + +## Related + +- `docs/sourceos/SUPERCONSCIOUS_INTEGRATION.md` — session boundary and evidence contract +- `docs/sourceos/AGENT_HARNESS_TERMINAL_RECEIPTS.md` — receipt capture +- `sourceos-spec/SourceOS-Linux` — ReasoningAssay, ValidatorReceipt, LocalReasoningFailure schemas +- `agent-term` `reasoning_run.py` — same data model for terminal ChatOps diff --git a/packaging/homebrew/Formula/turtle-term.rb b/packaging/homebrew/Formula/turtle-term.rb index 644bc0111d6..7b6912cc5dc 100644 --- a/packaging/homebrew/Formula/turtle-term.rb +++ b/packaging/homebrew/Formula/turtle-term.rb @@ -25,6 +25,7 @@ class TurtleTerm < Formula depends_on "wayland" depends_on "xcb-util" depends_on "xcb-util-image" + depends_on "xcb-util-keysyms" depends_on "zlib" end diff --git a/packaging/scripts/verify-rpm-package.sh b/packaging/scripts/verify-rpm-package.sh index a3383cff349..004fd745a31 100755 --- a/packaging/scripts/verify-rpm-package.sh +++ b/packaging/scripts/verify-rpm-package.sh @@ -51,6 +51,7 @@ PY rpm -qp --queryformat '%{NAME}\n' "$rpm" | grep -qx 'turtle-term' rpm -qp --queryformat '%{VERSION}\n' "$rpm" | grep -qx '0.1.0' +contents="$tmp/contents.txt" rpm -qpl "$rpm" > "$contents" for command in turtleterm turtle-agentctl turtle-agent-status turtle-cloudfog turtle-superconscious turtle-agent-machine turtle-language; do @@ -69,6 +70,7 @@ if grep -q '^/usr/bin/wezterm-gui$' "$contents"; then fi mkdir -p "$extract" +payload="$tmp/payload.cpio" rpm2cpio "$rpm" > "$payload" (cd "$extract" && cpio -idmu < "$payload" >/dev/null 2>&1) grep -q 'TURTLE_TERM_RUNTIME_DIR="/usr/libexec/turtle-term"' "$extract/usr/bin/turtleterm"