Replay what the organization knew at any date within 2025. See who decided, why, and which fictional records support it. Switch roles to reveal enforced access boundaries—not a chatbot with unrestricted access.
+
+
12fictional human staff
+
3teams
+
1human-supervised research agent
+
0live connectors or actions
+
+
+
+
+
+
+
+
+
+
Role selection is a local presentation simulation, not user authentication. All people, messages, tasks, and evidence below are invented.
+
+
+
Visible decisions—
+
Visible evidence—
+
Visible events—
+
As-of date—
+
+
+
+
Company timeline
Facts · decisions · outcomes
+
Loading fictional history…
+
+
+
Decision ledger
Who · what · why · evidence
+
Loading decisions…
+
+
+
Authority & access
P2C policy receipts
+
—
+
+
READ and PROPOSE are policy capabilities, not executable buttons. APPROVE/EXECUTE cannot be performed by the agent.
+
+
+
Organization & managed agent
Director → people/teams → memory → agent
+
+
Human-reviewed proposals
+
+
+
+
+
+
+
+
diff --git a/demo/company_twin_client_demo.py b/demo/company_twin_client_demo.py
new file mode 100644
index 00000000..cecf8528
--- /dev/null
+++ b/demo/company_twin_client_demo.py
@@ -0,0 +1,219 @@
+"""Local, synthetic-only client showcase over the existing P2A/P2C/P2D stack.
+
+This is a presentation adapter: no new memory engine, policy evaluator,
+external connector, model invocation, or execution authority.
+Launch from a verified source checkout:
+ python -B -m demo.company_twin_client_demo --check
+ python -B -m demo.company_twin_client_demo
+"""
+from __future__ import annotations
+
+import argparse
+from copy import deepcopy
+from http import HTTPStatus
+import json
+from pathlib import Path
+from typing import Any
+
+from continuityos.company_twin import load_dataset
+from continuityos.company_twin_console import (
+ _ConsoleHandler, build_snapshot, make_server, validate_bundle,
+)
+from continuityos.company_twin_policy import ACTIONS
+
+ROOT = Path(__file__).resolve().parent.parent
+BASE_FIXTURE = ROOT / "examples" / "company_twin" / "northstar_labs_2025.json"
+HTML_FILE = Path(__file__).with_suffix(".html")
+DEMO_PORT = 8769
+DEMO_PERIOD = ("2025-01-01T00:00:00Z", "2025-12-31T23:59:59Z")
+TENANT = "tenant:northstar-synthetic-demo"
+
+# Exactly twelve fictional humans (including one director), plus one managed agent.
+# Every human belongs to a single organizational slot, not to a real directory.
+PEOPLE = (
+ ("alice", "Alice Chen", "DIRECTOR", None, "Director"),
+ ("bob", "Bob Reyes", "WORKER", "sales", "Sales Lead"),
+ ("maya", "Maya Ford", "WORKER", "sales", "Account Executive"),
+ ("pavel", "Pavel Neri", "WORKER", "sales", "Growth Analyst"),
+ ("sue", "Sue Calder", "WORKER", "sales", "Customer Success"),
+ ("dana", "Dana Moore", "WORKER", "product", "Product Operations / Finance"),
+ ("lena", "Lena Vale", "WORKER", "product", "Product Designer"),
+ ("iris", "Iris Reed", "WORKER", "product", "Product Research"),
+ ("owen", "Owen Park", "WORKER", "product", "Product Manager"),
+ ("cara", "Cara Ionescu", "WORKER", "engineering", "Engineering Lead"),
+ ("eli", "Eli Hart", "WORKER", "engineering", "Backend Engineer"),
+ ("felix", "Felix Rowan", "WORKER", "engineering", "Quality Engineer"),
+)
+AUTHOR_BY_DECISION = {
+ "dec_jan_smb": "alice",
+ "dec_mar_pause_paid": "bob",
+ "dec_jun_hiring_freeze": "dana",
+ "dec_sep_resume_paid": "bob",
+ "dec_nov_deprecate_v1": "owen",
+}
+FAKE_SOURCES = (
+ # id, kind, title, timestamp, scope, source_authority_id, source_ref
+ ("ev_demo_sales_mail", "email", "Sales email: partners request a smaller pilot",
+ "2025-03-16T09:00:00Z", "team:sales", "auth_drive", "synthetic://mail/sales-mar"),
+ ("ev_demo_eng_task", "task", "Task ENG-104: review onboarding regression",
+ "2025-04-22T10:00:00Z", "team:engineering", "auth_github", "synthetic://tasks/ENG-104"),
+ ("ev_demo_sales_task", "task", "Task SALES-17: qualify partner opportunities",
+ "2025-09-16T08:00:00Z", "team:sales", "auth_crm", "synthetic://tasks/SALES-17"),
+ ("ev_demo_product_mail", "email", "Product email: friction in trial activation",
+ "2025-10-12T10:00:00Z", "team:product", "auth_drive", "synthetic://mail/product-oct"),
+)
+FAKE_EVENTS = (
+ ("evt_demo_sales_mail", "Sales reviewed fictional partner requests",
+ "2025-03-17T10:00:00Z", "team:sales", "ent_sales", "ev_demo_sales_mail"),
+ ("evt_demo_eng_task", "Engineering assigned onboarding regression review",
+ "2025-04-23T13:00:00Z", "team:engineering", "ent_eng", "ev_demo_eng_task"),
+ ("evt_demo_sales_task", "Sales started partner qualification task",
+ "2025-09-16T12:00:00Z", "team:sales", "ent_sales", "ev_demo_sales_task"),
+ ("evt_demo_product_mail", "Product collected synthetic trial feedback",
+ "2025-10-13T12:00:00Z", "team:product", "ent_product_team", "ev_demo_product_mail"),
+)
+
+
+def build_demo_bundle() -> dict[str, Any]:
+ """Decorate the already-qualified 2025 P2A fixture; P2C/P2D do actual governance."""
+ memory = deepcopy(load_dataset(BASE_FIXTURE))
+ if memory["organization"].get("synthetic") is not True:
+ raise ValueError("DEMO_REQUIRES_SYNTHETIC_ORGANIZATION")
+ if (memory["period"]["start"], memory["period"]["end"]) != DEMO_PERIOD:
+ raise ValueError("DEMO_SOURCE_PERIOD_DRIFT")
+
+ names = {pid: name for pid, name, *_ in PEOPLE}
+ original = {item["id"]: item for item in memory["principals"]}
+ if set(original) != {"alice", "bob", "cara", "dana"}:
+ raise ValueError("DEMO_SOURCE_PRINCIPALS_DRIFT")
+ principals = []
+ actors = []
+ grants = []
+ all_scopes = ["company", "team:sales", "team:product", "team:engineering",
+ "restricted:finance"]
+ for pid, name, role, team, title in PEOPLE:
+ scopes = list(all_scopes) if role == "DIRECTOR" else ["company", "team:" + team]
+ if pid == "dana":
+ scopes.append("restricted:finance")
+ principals.append({"id": pid, "name": name, "role": role, "scopes": scopes})
+ actor = {"id": "actor:" + pid, "principal_id": pid, "actor_kind": "HUMAN",
+ "role": role, "name": name, "job_title": title, "scopes": list(scopes)}
+ if team:
+ actor.update(team_id=team, manager_actor_id="actor:alice")
+ actors.append(actor)
+ grants.append({"id": "grant:" + pid, "actor_id": actor["id"],
+ "actions": sorted(ACTIONS) if role == "DIRECTOR" else ["READ", "PROPOSE"],
+ "scopes": list(scopes)})
+
+ robot_id = "agent_atlas"
+ principals.append({"id": robot_id, "name": "Atlas Research Agent",
+ "role": "AGENT", "scopes": ["company", "team:engineering"]})
+ actors.append({"id": "actor:" + robot_id, "principal_id": robot_id,
+ "name": "Atlas Research Agent", "actor_kind": "AGENT", "role": "AGENT",
+ "team_id": "engineering", "scopes": ["company", "team:engineering"],
+ "manager_actor_id": "actor:cara"})
+ memory["principals"] = principals
+
+ for decision in memory["decisions"]:
+ pid = AUTHOR_BY_DECISION.get(decision["id"])
+ if pid is None:
+ raise ValueError("DEMO_UNATTRIBUTED_DECISION")
+ decision["decided_by_principal"] = pid
+ decision["decided_by_name"] = names[pid]
+ # The historical rationale and evidence references stay unchanged.
+
+ for rid, kind, title, when, scope, authority, ref in FAKE_SOURCES:
+ memory["evidence"].append({"id": rid, "kind": kind, "title": title,
+ "recorded_at": when, "scope": scope, "truth_class": "EVIDENCE",
+ "source_authority_id": authority, "source_ref": ref})
+ for rid, title, when, scope, entity, evidence in FAKE_EVENTS:
+ memory["events"].append({"id": rid, "title": title, "occurred_at": when,
+ "scope": scope, "truth_class": "FACT", "entity_ids": [entity],
+ "evidence_ids": [evidence]})
+
+ policy = {"schema_version": "company-twin-p2c/1", "tenant_id": TENANT,
+ "actors": actors, "grants": grants,
+ "delegations": [{
+ "id": "delegation:atlas-research",
+ "grantor_actor_id": "actor:alice",
+ "grantee_actor_id": "actor:" + robot_id,
+ "actions": ["READ", "PROPOSE"], "scopes": ["team:engineering"],
+ "parent_id": None, "expires_at": "2026-01-01T00:00:00Z",
+ "revoked": False,
+ }], "explicit_denies": [], "revoked_delegation_ids": []}
+ bundle = {"schema_version": "company-twin-console-bundle/1",
+ "memory": memory, "policy": policy,
+ "proposals": [{
+ "id": "proposal:atlas-regression",
+ "actor_principal_id": robot_id, "scope": "team:engineering",
+ "classification": "INTERNAL", "created_at": "2025-09-20T10:00:00Z",
+ "status": "PENDING_HUMAN_REVIEW",
+ "summary": "Suggest a regression checklist for onboarding. No action executed.",
+ }],
+ "runtime": {"mode": "SYNTHETIC_LOCAL_DEMO", "read_only": True,
+ "twin_baseline": "P2A-P2D", "execution_authority": "NONE",
+ "can_execute": False}}
+ validate_bundle(bundle)
+ if (sum(actor["actor_kind"] == "HUMAN" for actor in actors) != 12
+ or {actor["team_id"] for actor in actors if "team_id" in actor} !=
+ {"sales", "product", "engineering"}):
+ raise ValueError("DEMO_ORGANIZATION_SHAPE_INVALID")
+ return bundle
+
+
+class ClientDemoHandler(_ConsoleHandler):
+ """Reuse the existing GET /api/snapshot and HTTP write-deny policy unchanged."""
+
+ def _send_html(self, *, head_only: bool = False) -> None:
+ body = HTML_FILE.read_bytes()
+ self.send_response(HTTPStatus.OK)
+ self.send_header("Content-Type", "text/html; charset=utf-8")
+ self.send_header("Content-Length", str(len(body)))
+ self.send_header("Cache-Control", "no-store")
+ self.send_header("X-Content-Type-Options", "nosniff")
+ self.send_header("Content-Security-Policy",
+ "default-src 'none'; connect-src 'self'; "
+ "script-src 'unsafe-inline'; style-src 'unsafe-inline'; "
+ "base-uri 'none'; form-action 'none'")
+ self.end_headers()
+ if not head_only:
+ self.wfile.write(body)
+
+
+def make_demo_server(*, host: str = "127.0.0.1", port: int = DEMO_PORT):
+ server = make_server(host=host, port=port, bundle=build_demo_bundle())
+ server.RequestHandlerClass = ClientDemoHandler
+ return server
+
+
+def main(argv: list[str] | None = None) -> int:
+ parser = argparse.ArgumentParser(description="Fictional Northstar Labs Company Twin showcase")
+ parser.add_argument("--host", default="127.0.0.1")
+ parser.add_argument("--port", type=int, default=DEMO_PORT)
+ parser.add_argument("--check", action="store_true", help="Offline smoke; do not start HTTP")
+ args = parser.parse_args(argv)
+ if args.check:
+ bundle = build_demo_bundle()
+ early = build_snapshot(bundle, principal_id="alice", as_of="2025-03-31T23:59:59Z")
+ late = build_snapshot(bundle, principal_id="alice", as_of="2025-12-31T23:59:59Z")
+ robot = build_snapshot(bundle, principal_id="agent_atlas", as_of="2025-12-31T23:59:59Z")
+ print(json.dumps({"status": "PASS", "synthetic": True,
+ "human_count": 12, "teams": 3,
+ "early_decisions": early["counts"]["decisions"],
+ "late_decisions": late["counts"]["decisions"],
+ "agent_can_execute": robot["capabilities"]["EXECUTE"]["allowed"]},
+ sort_keys=True))
+ return 0
+ server = make_demo_server(host=args.host, port=args.port)
+ print(f"SYNTHETIC DEMO ONLY · http://{args.host}:{server.server_address[1]}/")
+ try:
+ server.serve_forever()
+ except KeyboardInterrupt:
+ pass
+ finally:
+ server.server_close()
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/docs/COMPANY_TWIN_CLIENT_DEMO_R1.md b/docs/COMPANY_TWIN_CLIENT_DEMO_R1.md
new file mode 100644
index 00000000..85b438df
--- /dev/null
+++ b/docs/COMPANY_TWIN_CLIENT_DEMO_R1.md
@@ -0,0 +1,103 @@
+# Company Twin Client Demo R1 — Northstar Labs (FICTIONAL)
+
+**Status:** local synthetic-only client showcase candidate / not production admitted.
+**Git baseline:** protected master `517c7b48e270a3077e53d890e907c9cb2b3ce491` (tree `fcb37ef8d9af2c349a62c576b5634798881a7fbe`).
+**Scope:** one isolated demo branch and one PR (Draft until checks and review-ready gate); no merge, deploy, scheduler/TPM, live connectors, real model, external API, or real data.
+
+## Product in one sentence
+
+ContinuityOS reconstructs a company's evidence-backed history and decisions at a selected point in time, with Director / Worker / Managed-Agent access constraints. The example company **Northstar Labs** is entirely fictional.
+
+## What this actually uses
+
+- **P2A** `continuityos.company_twin.load_dataset/replay` and the existing `northstar_labs_2025.json` 12-month synthetic fixture.
+- **P2C** `continuityos.company_twin_policy.evaluate` via the existing P2D `build_snapshot`: tenant/scope/role/delegation checks.
+- **P2D** `continuityos.company_twin_console.make_server` and its existing GET `/api/snapshot`, HEAD, HTTP-405 write denials, loopback-only bind and unchanged policy filtering.
+- **New demo-only presentation adapter:** `demo/company_twin_client_demo.py`, standalone HTML page, synthetic actor/grant metadata, synthetic emails/tasks, human-authored demo decision attribution.
+- **P2B ingestion and P2E live/self-pilots are not executed**. The new synthetic email/task records are P2A-compatible fixtures, not real connectors.
+- **Person Twin #211 is already merged**; demo does not consume new #212–#215 features or modify the Person Twin production/evidence path.
+
+This PR adds NO new memory/policy/agent/runtime core and modifies NO existing tracked files.
+
+## 10-minute client walkthrough
+
+| Time | Action | Observable result |
+| --- | --- | --- |
+| 0–1 min | Open Northstar Labs view as **Alice Chen / Director** | 12 fictional humans, 3 teams, one managed research agent |
+| 1–3 min | Scroll the company timeline | Synthetic documents, email/task events, decisions and outcomes covering 2025 |
+| 3–5 min | Open Decision Ledger | For each authorized decision: date, fictional decision author, rationale, evidence title(s), ACTIVE/SUPERSEDED status |
+| 5–7 min | Click **Mar 31**, then **Dec 31** | Replayed authorized decision/event set changes; March's paid-acquisition pause becomes SUPERSEDED by the September partner-qualified decision |
+| 7–9 min | Switch **Director → Bob (Sales) → Cara (Engineering) → Atlas Agent** | Sales cannot see restricted finance or engineering; agent sees scoped engineering data and READ/PROPOSE but not APPROVE/EXECUTE |
+| 9–10 min | Show pending Atlas proposal and policy status | Proposal needs human review; no external action, approval, or execution endpoint exists |
+
+Dates are selectable within **2025**, the period of the provided historical dataset. Dates outside this dataset are not claimed to be supported.
+
+## Local demo commands (local execution, no cloud dependencies)
+
+From a clean verified source checkout on Windows or Linux:
+
+```powershell
+python -B -m demo.company_twin_client_demo --check
+python -B -m demo.company_twin_client_demo
+```
+
+Open `http://127.0.0.1:8769/`. Use Ctrl+C to stop. Server refuses non-loopback bindings. Port may be changed with `--port 0` for tests or `--port 8770` for another local session.
+
+Bounded local tests, without auto-loading extra pytest plugins and without writing cache or bytecode:
+
+```powershell
+$env:PYTHONDONTWRITEBYTECODE='1'
+$env:PYTEST_DISABLE_PLUGIN_AUTOLOAD='1'
+python -B -m pytest -q -p no:cacheprovider tests/test_company_twin_client_demo.py tests/test_company_twin.py tests/test_company_twin_policy.py tests/test_company_twin_console.py tests/test_company_twin_ingest.py
+```
+
+No need for Docker, browser extensions, SSH, API keys, a paid model, or credentials.
+
+## Wheel-only qualification boundary
+
+The client presentation adapter lives under `demo/` in a source checkout; it is
+**not packaged into the core ContinuityOS wheel**. CI tests the demo from the
+clean source and editable checkout. When the isolated wheel-only runner copies
+the `tests/` directory without `demo/`, this exact new demo-test module is
+**explicitly skipped** after checking that no source file is available; existing
+wheel-portable P2A/P2C/P2D test coverage remains required. A wheel skip is
+recorded as SKIP, never PASS. This is an intentional packaging boundary, not a
+silent fallback or a claim that the installed wheel serves the demo.
+## Truth and authorization claims
+
+- **SYNTHETIC DATA ONLY**. Names, company, emails, tasks, source references, roles and decision authors are made up.
+- All evidence is marked `EVIDENCE`, history is `FACT`, interpretation stays `INFERENCE`.
+- Decision `decided_by_name` and `decided_by_principal` are **fictional demo metadata**; they are not cryptographically signed, authentic user identities, verified approvals, or a proof of source authorship.
+- The role selector **simulates viewpoints; it is not authentication**. It is never advertised as a production identity/SSO gate.
+- P2A's replay covers only existing dates and applies explicit record scope. P2D intersects P2A with P2C and hides unauthorized rows, IDs and decision lineage.
+- Agent is assigned a named human manager plus an explicit Director-issued, time-limited delegation to `team:engineering`; `READ/PROPOSE` are authorized *policy classes*, not HTTP mutation endpoints.
+- Every actual HTTP write method (`POST/PUT/PATCH/DELETE`) is rejected. `EXECUTE` does not exist as a P2C action, and `can_execute=false` in runtime and governance outputs.
+- External network isolation is a *design boundary of the demo package*, not an OS-level sandbox claim. Server listens only on loopback; the code never fetches real sources or calls LLMs.
+- No real ContinuityOS, Robert, client, Gmail, Drive, Slack, GitHub, finance, secrets, private repos or other protected data enter the fixture.
+
+## Verification and release
+
+A customer demo should only be called ready after deterministic local tests and a live local 10-minute walkthrough (browser visual quality / client presentation) are checked. An offline HTTP smoke is not a production penetration test.
+
+### Verified CI on exact reviewed HEAD (2026-10-16)
+
+The exact reviewed code HEAD `82bb250c36e25c35df8890c29c5d920dc4e4c3a8` completed all five GitHub checks with **SUCCESS**:
+- `review-gates` [run 38837817465](https://github.com/bitmaster162/continuityos/actions/runs/38837817465): Ubuntu / Python 3.11 **SUCCESS** and Windows / Python 3.11 **SUCCESS**.
+- `CodeQL` [run 38837817437](https://github.com/bitmaster162/continuityos/actions/runs/38837817437): CodeQL **SUCCESS**, Analyze Python **SUCCESS**.
+- `P0 Unified Shadow Continuity` [run 38837817510](https://github.com/bitmaster162/continuityos/actions/runs/38837817510): offline-shadow-continuity **SUCCESS**.
+
+Ubuntu source/editable: 2502 passed / 67 skipped; isolated wheel: 2419 passed / 118 skipped. Windows source/editable: 2510 passed / 59 skipped; isolated wheel: 2420 passed / 117 skipped. Each test mode also recorded 870 passing subtests. Wheel-only deliberately skips the checkout-only demo test; it does not mark that module as passed.
+
+These checks are evidence for the **named HEAD only**. After the documentation-only follow-up commit, all required checks must complete successfully on the **new exact HEAD** before Draft is changed to Ready for review. Full CI is not permission to merge. Merge requires a separate human decision bound to base/head/tree and ordinary merge-commit method. Do not bypass protected-master requirements. No manual workflow reruns, merges, releases, deployment or branch deletion are authorized by this document.
+
+**Historical planning estimate (not an elapsed-time claim):** initially 1–2 focused engineering days for the fixture/presentation/tests and 0.5–1 additional day for visual review. The demo implementation and the listed exact-HEAD CI now exist; client presentation signoff, fresh new-HEAD checks, human review and merge authorization remain separate gates.
+
+## Stop conditions
+
+- Git base/head tree changes unexpectedly, or tracked files outside the four new demo/test/docs files change.
+- Any real input, production authorization, external connection or delegated agent EXECUTE emerges.
+- A non-loopback host is requested.
+- Any P2A/P2C/P2D permission regression is observed.
+- CI absent, failed, or not associated with the current exact HEAD: keep as Draft/HOLD until all required checks pass. Never treat a prior-head success as current-head qualification, or call this production-qualified.
+
+Unchanged / on HOLD: H3 PR #209/#210, Person Twin PR #212–#215, production admission C0/T11/T12 and all capital/TPM/Scheduler authority.
diff --git a/tests/test_company_twin_client_demo.py b/tests/test_company_twin_client_demo.py
new file mode 100644
index 00000000..1d679316
--- /dev/null
+++ b/tests/test_company_twin_client_demo.py
@@ -0,0 +1,195 @@
+"""Bounded offline tests for the fictional Northstar Labs client walkthrough."""
+from __future__ import annotations
+
+import json
+from pathlib import Path
+import threading
+from urllib.error import HTTPError
+from urllib.request import Request, urlopen
+
+import pytest
+
+from continuityos.company_twin_console import CompanyTwinConsoleError, build_snapshot
+# The client showcase is intentionally a source-checkout-only presentation
+# adapter, not part of the independently installed ContinuityOS wheel.
+# The wheel-only runner copies tests into an isolated suite with no demo/
+# directory. Skip this one source-only test module there; do not mask an
+# import defect when the expected demo source file is present.
+try:
+ from demo.company_twin_client_demo import (
+ BASE_FIXTURE, HTML_FILE, PEOPLE, build_demo_bundle, make_demo_server,
+ )
+except ModuleNotFoundError as exc:
+ source_demo = Path(__file__).resolve().parent.parent / "demo" / "company_twin_client_demo.py"
+ if exc.name != "demo" or source_demo.is_file():
+ raise
+ pytest.skip("source-checkout-only client demo is absent from installed wheel",
+ allow_module_level=True)
+
+
+@pytest.fixture(scope="module")
+def bundle():
+ return build_demo_bundle()
+
+
+def snapshot(bundle, principal: str, at: str = "2025-12-31T23:59:59Z"):
+ return build_snapshot(bundle, principal_id=principal, as_of=at)
+
+
+def test_fixture_is_pinned_2025_synthetic_and_has_no_real_connectors(bundle):
+ assert BASE_FIXTURE.name == "northstar_labs_2025.json"
+ assert bundle["memory"]["organization"]["synthetic"] is True
+ assert bundle["runtime"]["read_only"] is True
+ assert bundle["runtime"]["can_execute"] is False
+ assert bundle["runtime"]["execution_authority"] == "NONE"
+ assert bundle["memory"]["period"] == {
+ "start": "2025-01-01T00:00:00Z", "end": "2025-12-31T23:59:59Z"
+ }
+ assert all("synthetic" in record["source_ref"]
+ for record in bundle["memory"]["evidence"])
+ assert all(not str(p["id"]).startswith("principal_") for p in bundle["memory"]["principals"])
+
+
+def test_12_humans_three_teams_and_one_supervised_agent(bundle):
+ policy = bundle["policy"]
+ humans = [actor for actor in policy["actors"] if actor["actor_kind"] == "HUMAN"]
+ agents = [actor for actor in policy["actors"] if actor["actor_kind"] == "AGENT"]
+ assert len(PEOPLE) == len(humans) == 12
+ assert len(agents) == 1
+ assert [a["role"] for a in humans].count("DIRECTOR") == 1
+ assert {p["team_id"] for p in humans if "team_id" in p} == {
+ "sales", "product", "engineering"
+ }
+ assert agents[0]["manager_actor_id"] == "actor:cara"
+ assert len(bundle["memory"]["principals"]) == 13
+ assert len(policy["delegations"]) == 1
+ assert set(policy["delegations"][0]["actions"]) == {"READ", "PROPOSE"}
+ assert policy["delegations"][0]["scopes"] == ["team:engineering"]
+
+
+def test_historical_replay_changes_and_decision_lineage_is_authorized(bundle):
+ march = snapshot(bundle, "alice", "2025-03-31T23:59:59Z")
+ december = snapshot(bundle, "alice")
+ assert march["counts"]["decisions"] == 2
+ assert december["counts"]["decisions"] == 5
+ assert march["counts"]["events"] < december["counts"]["events"]
+ assert any(d["id"] == "dec_mar_pause_paid" and d["replay_status"] == "ACTIVE"
+ for d in march["decisions"])
+ assert any(d["id"] == "dec_mar_pause_paid" and d["replay_status"] == "SUPERSEDED"
+ for d in december["decisions"])
+ assert december["decision_lineages"]["dec_sep_resume_paid"] == [
+ "dec_sep_resume_paid", "dec_mar_pause_paid"
+ ]
+ names = {p["id"]: p["name"] for p in bundle["memory"]["principals"]}
+ for d in december["decisions"]:
+ assert d["decided_by_name"] == names[d["decided_by_principal"]]
+ assert d["rationale"] and d["evidence_ids"]
+ assert december["organization"]["synthetic"] is True
+
+
+def test_sales_cannot_read_engineering_or_restricted_finance(bundle):
+ director = snapshot(bundle, "alice")
+ sales = snapshot(bundle, "bob")
+ evidence_dir = {r["id"] for r in director["evidence"]}
+ evidence_sales = {r["id"] for r in sales["evidence"]}
+ assert "ev_jun_cash" in evidence_dir
+ assert "ev_jun_cash" not in evidence_sales
+ assert "ev_demo_eng_task" not in evidence_sales
+ assert "ev_demo_sales_mail" in evidence_sales
+ assert "ev_demo_sales_task" in evidence_sales
+ assert all(not item["scope"].startswith("restricted:") for item in sales["decisions"])
+
+
+def test_agent_delegation_is_read_propose_only_and_managed_by_human(bundle):
+ agent = snapshot(bundle, "agent_atlas")
+ assert agent["actor"]["actor_kind"] == "AGENT"
+ assert agent["actor"]["manager"]["name"] == "Cara Ionescu"
+ assert agent["capabilities"]["READ"]["allowed"] is True
+ assert agent["capabilities"]["PROPOSE"]["allowed"] is True
+ for action in ("APPROVE", "DELEGATE", "REVOKE", "DELETE", "EXPORT", "EXECUTE"):
+ assert agent["capabilities"][action]["allowed"] is False
+ assert agent["governance"] == {
+ "execution_authority": "NONE",
+ "can_execute": False,
+ "can_trade": False,
+ "capital_permission": "DENY",
+ }
+ assert len(agent["proposals"]) == 1
+ assert agent["proposals"][0]["status"] == "PENDING_HUMAN_REVIEW"
+ assert all(x["scope"] == "team:engineering" for x in agent["evidence"])
+ assert not agent["lifecycle_previews"]
+
+
+def test_no_agent_authorization_after_delegation_expiry(bundle):
+ # P2C evaluates expiry at the requested time; the demo itself ends in 2025.
+ changed = json.loads(json.dumps(bundle))
+ changed["policy"]["delegations"][0]["expires_at"] = "2025-07-01T00:00:00Z"
+ denied = snapshot(changed, "agent_atlas")
+ assert denied["capabilities"]["READ"]["allowed"] is False
+ assert denied["capabilities"]["PROPOSE"]["allowed"] is False
+ assert denied["counts"]["evidence"] == 0
+ assert denied["proposals"] == []
+
+
+def test_director_worker_and_robot_see_different_actor_graph(bundle):
+ director = snapshot(bundle, "alice")
+ worker = snapshot(bundle, "bob")
+ robot = snapshot(bundle, "agent_atlas")
+ assert len(director["organization_graph"]["nodes"]) == 13
+ assert len(worker["organization_graph"]["nodes"]) < 13
+ names = {n["name"] for n in robot["organization_graph"]["nodes"]}
+ assert "Cara Ionescu" in names and "Atlas Research Agent" in names
+ assert "Dana Moore" not in names
+
+
+def test_source_aware_synthetic_email_and_task_timeline(bundle):
+ dates = {x["id"] for x in snapshot(bundle, "alice")["timeline"]}
+ assert "evt_demo_eng_task" in dates
+ assert "evt_demo_product_mail" in dates
+ assert "evt_demo_sales_task" in dates
+ kinds = {r["kind"] for r in bundle["memory"]["evidence"]}
+ assert {"email", "task"}.issubset(kinds)
+
+
+def test_no_external_dependencies_or_unmarked_demo_screen():
+ html = HTML_FILE.read_text(encoding="utf-8")
+ assert "Synthetic demo" in html and "Fictional company" in html
+ assert "not user authentication" in html.lower() or "not user authentication" in html
+ assert "textContent" in html
+ assert "