diff --git a/.corp-harness/component-contracts.json b/.corp-harness/component-contracts.json new file mode 100644 index 0000000..180e930 --- /dev/null +++ b/.corp-harness/component-contracts.json @@ -0,0 +1,38 @@ +{ + "schema": "corporate-site-component-contracts/v1", + "origin": { + "namespace": "project", + "origin_id": "site" + }, + "shared_components": { + "operations-excellence": { + "authority": "review-only", + "evidence_source": "root-produced-immutable", + "may_approve": false, + "may_delegate": false, + "may_execute_site_commands": false, + "readonly": true + }, + "site-delivery": { + "atomic_rework_snapshot_required": true, + "corporate_rework_authority": "user", + "dispatch_owner": "root-orchestrator", + "maximum_delegation_depth": 1, + "workers_may_delegate": false + }, + "site-manager": { + "authority": "decompose-only", + "dispatch_owner": "root-orchestrator", + "may_approve": false, + "may_delegate": false, + "readonly": true + }, + "site-specialist": { + "authority": "adr-bounded-write", + "dispatch_owner": "root-orchestrator", + "may_approve": false, + "may_delegate": false, + "readonly": false + } + } +} diff --git a/.corp-harness/site.json b/.corp-harness/site.json new file mode 100644 index 0000000..adde15b --- /dev/null +++ b/.corp-harness/site.json @@ -0,0 +1,8 @@ +{ + "schema": "corporate-site-site/v1", + "site_id": "corpos", + "corporate_program": null, + "corporate_handoff_sha256": null, + "verify_argv": ["./scripts/harness/verify.sh"], + "adversarial_argv": ["./scripts/harness/adversarial.sh"] +} diff --git a/.cursor/agents/operations-excellence.md b/.cursor/agents/operations-excellence.md new file mode 100644 index 0000000..25e5549 --- /dev/null +++ b/.cursor/agents/operations-excellence.md @@ -0,0 +1,10 @@ +--- +name: operations-excellence +description: Defines site gates and SLOs, runs the current oracle, and independently reviews evidence. +model: inherit +readonly: true +--- + +Run `scripts/harness/verify.sh` against the current revision. Inspect executable evidence rather +than producer claims. Return PASS or FAIL, linked findings, site SLOs, and the recommended +transition. Do not fix failures or weaken gates. diff --git a/.cursor/agents/site-manager.md b/.cursor/agents/site-manager.md new file mode 100644 index 0000000..1c0104e --- /dev/null +++ b/.cursor/agents/site-manager.md @@ -0,0 +1,11 @@ +--- +name: site-manager +description: Decomposes a verified corporate handoff into ADR work and integrates site evidence. +model: inherit +readonly: true +--- + +Verify the handoff digest, create only consequential ADRs, and dispatch bounded packets to +the root orchestrator. The root launches `site-specialist` in isolated worktrees and +integrates results. Return assignments, evidence requirements, risks, and the recommended +transition; never implement, launch workers, integrate, or self-approve. diff --git a/.cursor/agents/site-specialist.md b/.cursor/agents/site-specialist.md new file mode 100644 index 0000000..24454d9 --- /dev/null +++ b/.cursor/agents/site-specialist.md @@ -0,0 +1,11 @@ +--- +name: site-specialist +description: Implements one ADR-scoped packet and returns exact command evidence. +model: inherit +readonly: false +--- + +Stay inside the assigned site root, ADR, and write set. Implement the smallest compliant +change, run the supplied verification command, and return changed paths plus exit codes. +Worker subagents may not delegate further. Do not edit corporate approval state or +approve your own output. diff --git a/.cursor/rules/site-contract.mdc b/.cursor/rules/site-contract.mdc new file mode 100644 index 0000000..0aa4163 --- /dev/null +++ b/.cursor/rules/site-contract.mdc @@ -0,0 +1,9 @@ +--- +description: Keep site work within the approved corporate handoff and evidence gates +alwaysApply: true +--- + +For an active site program, read the corporate handoff before editing. Site specialists +implement; operations excellence reviews current evidence. Use isolated workspaces for +independent writers. Do not alter corporate approvals, weaken tests, infer gate success, +or grant user approval. diff --git a/.cursor/skills/site-delivery/SKILL.md b/.cursor/skills/site-delivery/SKILL.md new file mode 100644 index 0000000..967cc2c --- /dev/null +++ b/.cursor/skills/site-delivery/SKILL.md @@ -0,0 +1,15 @@ +--- +name: site-delivery +description: Delivers an approved corporate handoff through ADR-scoped implementation and independent site verification. +--- + +# Site delivery + +1. Verify the handoff digest. +2. Have the readonly site manager return bounded ADR packets. +3. The root orchestrator launches site specialists in isolated roots. +4. Integrate and run `scripts/harness/verify.sh`. +5. Record `verification_scripts` as site-relative `scripts/harness` (only + `verify.sh` and `adversarial.sh`). Do not bind the whole `scripts/` tree. +6. Ask operations excellence to review fresh evidence. +7. Return failures to the owning ADR; never bypass retries or self-approve. diff --git a/AGENTS.md b/AGENTS.md index d22a4d3..8abc170 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,46 +1,18 @@ -# AGENTS.md +# Site contract -CorpOS harness. Profile: **solo**. +## Gates -## Purpose +| Command | Purpose | +| ---------------------------------- | ----------------------------------- | +| `./scripts/harness/verify.sh` | Functional and static acceptance | +| `./scripts/harness/adversarial.sh` | Authorized local adversarial probes | -TypeScript multi-agent runtime with policy, approval, and audit control plane. Simulation-first demo; optional live LLM via OpenRouter. +Record `verification_scripts` as the site directory `scripts/harness` (exactly those +two scripts). Optional wrappers may remain at `scripts/verify.sh` / +`scripts/adversarial.sh` for humans; they are outside the digest boundary. -## Prerequisites +The corporate handoff fixes scope. The site manager assigns ADRs; site specialists write; +operations excellence reviews current evidence. Work in isolated roots, never edit +corporate approval state, and never self-approve. -- Node.js ≥20 (`package.json` engines) -- `npm install` (builds `better-sqlite3` native module) - -## Commands - -| Command | Purpose | -| --------------------- | ------------------------------- | -| `./scripts/verify.sh` | Definition of Done | -| `npm install` | Install dependencies | -| `npm run dev` | API + dashboard with hot reload | -| `npm run start` | Run without watch | -| `npm run test` | Vitest suite | -| `npm run typecheck` | `tsc --noEmit` | -| `npm run lint` | ESLint | -| `npm run build` | Compile to `dist/` | - -## Layout - -| Path | Role | -| ---------------- | --------------------------------------------------------- | -| `src/core/` | Orchestrator, policy, store (SQLite at `data/company.db`) | -| `src/agents/` | Department agents | -| `src/tools/` | Permissioned tool registry | -| `src/api/` | Express REST + WebSocket | -| `src/dashboard/` | Control-plane UI | - -## Definition of Done - -```bash -npx npm@10.9.2 ci -./scripts/verify.sh -``` - -## Review focus - -Block on P0/P1: policy chokepoint bypass, approval gate skips, secret exposure, broken simulation determinism. +Site id: `corpos`. Prior Cursor Harness v4 is under `_archives/harness-v4/`. diff --git a/_archives/harness-v4/20260717T192824Z/.cursor/hooks.json b/_archives/harness-v4/20260717T192824Z/.cursor/hooks.json new file mode 100644 index 0000000..efd8a19 --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/.cursor/hooks.json @@ -0,0 +1,40 @@ +{ + "version": 1, + "hooks": { + "beforeShellExecution": [ + { + "command": "python3 .cursor/hooks/guard-shell.py", + "failClosed": false + }, + { + "command": "python3 .cursor/hooks/guard-network.py", + "matcher": "curl|wget|scp|nc ", + "failClosed": false + } + ], + "beforeMCPExecution": [ + { + "command": "python3 .cursor/hooks/guard-mcp.py", + "failClosed": false + } + ], + "beforeReadFile": [ + { + "command": "python3 .cursor/hooks/protect-secrets.py", + "failClosed": true + } + ], + "beforeSubmitPrompt": [ + { + "command": "python3 .cursor/hooks/scan-prompt.py", + "failClosed": true + } + ], + "stop": [ + { + "command": "python3 .cursor/hooks/verify-on-stop.py", + "loop_limit": 3 + } + ] + } +} diff --git a/_archives/harness-v4/20260717T192824Z/.cursor/hooks/_common.py b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/_common.py new file mode 100755 index 0000000..b5294ae --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/_common.py @@ -0,0 +1,265 @@ +"""Shared helpers for Cursor v2 lifecycle hooks. + +Imported by sibling hook scripts. Robust to the working directory Cursor +launches hooks from, since callers add this file's directory to sys.path. + +Design law (v2): a guard exists only if `harness redteam` exercises it. Keep +detection logic here so a single corpus can test every consumer. +""" +from __future__ import annotations + +import datetime +import json +import os +import re +import sys +import uuid +from pathlib import Path +from typing import Any + +CURSOR_HOME = os.path.expanduser("~/.cursor") +LOG_DIR = os.environ.get("CURSOR_HOOK_LOG_DIR", os.path.join(CURSOR_HOME, "logs")) +MEMORY_DIR = os.path.join(CURSOR_HOME, "memory") +_TRACE_ID = os.environ.get("CURSOR_TRACE_ID") or uuid.uuid4().hex + + +_TRACE_ID = os.environ.get("CURSOR_TRACE_ID") or uuid.uuid4().hex +_HOOK_CONTEXT: dict[str, Any] | None = None + + +def resolve_workspace_root( + payload: dict[str, Any] | None = None, + *, + cwd: str | None = None, +) -> str: + """Best-effort repo root for C17 log attribution (IDE + cloud).""" + if payload: + for key in ("workspace_roots", "workspaceRoots", "roots"): + roots = payload.get(key) + if isinstance(roots, list) and roots: + root = str(roots[0]).strip() + if root: + return root + for key in ("cwd", "workingDirectory", "working_directory"): + value = payload.get(key) + if isinstance(value, str) and value.strip(): + return value.strip() + for env_key in ( + "CURSOR_PROJECT_DIR", + "CURSOR_WORKSPACE_ROOT", + "CLAUDE_PROJECT_DIR", + ): + value = os.environ.get(env_key) + if value and value.strip(): + return value.strip() + if cwd and cwd.strip(): + return cwd.strip() + return os.getcwd() + + +def _repo_profile_at(root: Path) -> dict[str, Any] | None: + path = root / ".harness" / "profile.yaml" + if not path.is_file(): + return None + try: + import yaml # type: ignore + + data = yaml.safe_load(path.read_text(encoding="utf-8")) + return data if isinstance(data, dict) else None + except Exception: # noqa: BLE001 + return None + + +def _repo_profile_name_for(root: str) -> str | None: + try: + prof = _repo_profile_at(Path(root)) + return prof.get("profile") if prof else None + except Exception: # noqa: BLE001 + return None + + +def read_repo_profile(workspace_root: str | None = None) -> dict[str, Any] | None: + """Best-effort read of .harness/profile.yaml from a workspace root.""" + root = workspace_root or resolve_workspace_root() + return _repo_profile_at(Path(root)) + + +def log_event( + event: str, + data: dict[str, Any], + *, + context: dict[str, Any] | None = None, +) -> None: + """Append a structured event to today's JSONL session log. Never raises.""" + try: + ctx = context if context is not None else _HOOK_CONTEXT + workspace_root = resolve_workspace_root(ctx) + os.makedirs(LOG_DIR, exist_ok=True) + day = datetime.date.today().isoformat() + record = { + "ts": datetime.datetime.now().isoformat(timespec="seconds"), + "trace_id": _TRACE_ID, + "span_id": uuid.uuid4().hex[:16], + "event": event, + "workspace_root": workspace_root, + "profile": _repo_profile_name_for(workspace_root), + **data, + } + if ctx and ctx.get("loop_count") is not None and "loop_count" not in record: + record["loop_count"] = ctx.get("loop_count") + with open(os.path.join(LOG_DIR, f"{day}.jsonl"), "a", encoding="utf-8") as fh: + fh.write(json.dumps(record) + "\n") + except Exception: + pass # observability must never break the agent + + +def read_input() -> dict[str, Any]: + """Read and parse the JSON payload Cursor sends on stdin. Never raises.""" + global _HOOK_CONTEXT + try: + raw = sys.stdin.read() + payload = json.loads(raw) if raw.strip() else {} + _HOOK_CONTEXT = payload if isinstance(payload, dict) else {} + return _HOOK_CONTEXT + except Exception: + _HOOK_CONTEXT = {} + return {} + + +def emit(obj: dict[str, Any]) -> None: + """Write a JSON response and flush.""" + sys.stdout.write(json.dumps(obj)) + sys.stdout.flush() + + +def allow() -> None: + emit({"permission": "allow"}) + + +def deny(user_message: str, agent_message: str | None = None) -> None: + out: dict[str, Any] = {"permission": "deny", "user_message": user_message} + if agent_message: + out["agent_message"] = agent_message + emit(out) + + +# --- Secret detection ------------------------------------------------------- +# High-confidence, low-false-positive patterns for live credentials. +SECRET_PATTERNS: list[tuple[re.Pattern[str], str]] = [ + (re.compile(r"-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----"), "private key"), + (re.compile(r"\bAKIA[0-9A-Z]{16}\b"), "AWS access key id"), + (re.compile(r"\baws_secret_access_key\s*[:=]\s*['\"]?[A-Za-z0-9/+]{40}\b"), "AWS secret access key"), + (re.compile(r"\bghp_[A-Za-z0-9]{36}\b"), "GitHub personal access token"), + (re.compile(r"\bgh[ousr]_[A-Za-z0-9]{36}\b"), "GitHub token"), + (re.compile(r"\bxox[baprs]-[0-9A-Za-z-]{10,}"), "Slack token"), + (re.compile(r"\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b"), "OpenAI-style API key"), + (re.compile(r"\bAIza[0-9A-Za-z_-]{35}\b"), "Google API key"), + (re.compile(r"\bglpat-[0-9A-Za-z_-]{20,}\b"), "GitLab personal access token"), + (re.compile(r"\bsk_live_[0-9A-Za-z]{24,}\b"), "Stripe live secret key"), + (re.compile(r"\bsk-ant-[A-Za-z0-9_-]{20,}\b"), "Anthropic API key"), + (re.compile(r"\bxox[pae]-[0-9A-Za-z-]{10,}"), "Slack token (xoxp/xoxa/xoxe)"), +] + + +def find_secret(text: str) -> str | None: + """Return a label for the first high-confidence secret found, else None.""" + if not text: + return None + for pattern, label in SECRET_PATTERNS: + if pattern.search(text): + return label + return None + + +# --- Sensitive-file detection ---------------------------------------------- +_ALLOW_SUFFIXES = (".example", ".sample", ".template", ".dist", ".pub") +_SECRET_BASENAMES = { + ".env", ".env.local", ".env.production", ".env.prod", ".env.staging", + ".env.test", ".env.test.local", + ".env.development.local", ".env.production.local", + "id_rsa", "id_dsa", "id_ecdsa", "id_ed25519", + ".netrc", "credentials", "credentials.json", ".npmrc", ".pypirc", ".git-credentials", +} +_SECRET_EXTS = {".pem", ".key", ".p12", ".pfx", ".keystore", ".jks", ".asc", ".ppk"} + + +def is_sensitive_file(path: str) -> bool: + if not path: + return False + base = os.path.basename(path) + lower = base.lower() + if lower.endswith(_ALLOW_SUFFIXES): + return False + if base in _SECRET_BASENAMES: + return True + if lower.startswith(".env"): + return True + _, ext = os.path.splitext(lower) + if ext in _SECRET_EXTS: + return True + return False + + +# --- Destructive data-layer detection (shared by shell + MCP guards) -------- +# Narrow, high-confidence patterns for irreversible data/disk destruction that +# can arrive either as a shell command or as serialized MCP tool arguments +# (e.g. a database MCP running DROP). Fail-open nets, not boundaries. +DATA_DESTRUCTIVE: list[tuple[re.Pattern[str], str]] = [ + (re.compile(r"\b(drop\s+database|drop\s+table|truncate\s+table)\b", re.IGNORECASE), + "Destructive SQL (DROP / TRUNCATE)."), + (re.compile(r"\bdelete\s+from\s+\w+\s*(;|$)", re.IGNORECASE), + "Unfiltered DELETE (no WHERE clause)."), + (re.compile(r"\bmkfs(\.\w+)?\b", re.IGNORECASE), "Filesystem format command."), + (re.compile(r"\bdd\b.*\bof=/dev/", re.IGNORECASE), "dd writing to a raw device."), +] + + +def find_data_destructive(text: str) -> str | None: + if not text: + return None + for pattern, why in DATA_DESTRUCTIVE: + if pattern.search(text): + return why + return None + + +# --- Agent worktree integration guard (shared pattern for guard-shell) ---------- +_COMPOSE_RE = re.compile(r"\bdocker\s+compose\b|\bdocker-compose\b", re.IGNORECASE) +_INTEGRATION_SCRIPT_RE = re.compile( + r"(?:^|[;&|\s])(?:\./)?scripts/" + r"(?:smoke-test(?:-phase[23])?|deploy-stack|seed|register-debezium-connector|" + r"wait-outbox-drained|verify-state-twin-pipeline|demo-phase3|verify-worktree-merge|" + r"register-schemas|submit-flink-job)" + r"\.sh\b", + re.IGNORECASE, +) +_WORKTREE_INTEGRATION_MSG = ( + "Integration/stack scripts from an agent worktree (.worktrees/) are blocked — " + "they hit the main Docker stack and produce false confidence. " + "Parent runs merge verification from the main repo root " + "(./scripts/verify-worktree-merge.sh). " + "Set ALLOW_WORKTREE_COMPOSE=1 only when the user explicitly overrides." +) + + +def _in_worktree_context(payload: dict[str, Any]) -> bool: + command = (payload.get("command") or "").strip() + cwd = (payload.get("cwd") or payload.get("workingDirectory") or "").strip() + return ".worktrees" in f"{cwd} {command}" + + +def find_worktree_integration_block(payload: dict[str, Any]) -> str | None: + """Block Compose and integration smoke/stack scripts from worktree cwd.""" + if os.environ.get("ALLOW_WORKTREE_COMPOSE") == "1": + return None + if not _in_worktree_context(payload): + return None + command = (payload.get("command") or "").strip() + if _COMPOSE_RE.search(command) or _INTEGRATION_SCRIPT_RE.search(command): + return _WORKTREE_INTEGRATION_MSG + return None + + +def find_worktree_compose_block(payload: dict[str, Any]) -> str | None: + """Backward-compatible alias.""" + return find_worktree_integration_block(payload) diff --git a/_archives/harness-v4/20260717T192824Z/.cursor/hooks/guard-mcp.py b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/guard-mcp.py new file mode 100755 index 0000000..22f4398 --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/guard-mcp.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +"""beforeMCPExecution: observe every MCP tool call and block plainly +destructive ones (NEW in v2). + +Why this exists: MCP tools can mutate real systems (databases, cloud, files) +and their *output* is untrusted data, never instructions. This hook is a +fail-open net (failClosed:false): it logs every MCP call for observability and +denies only a narrow, high-confidence set of irreversible data-layer actions +(DROP / TRUNCATE / unfiltered DELETE / mkfs / dd-to-device) found in the +serialized tool arguments. It is NOT a security boundary. + +Unknown servers default to read-only: shell/exec tools are denied unless the +server is listed in ~/.cursor/mcp-trust.json mutating_allowed. + +Input contract is read defensively because field names vary across MCP servers; +we scan the whole serialized payload rather than assume a single arg key. +Output: {"permission": "allow"|"deny"} per the beforeMCPExecution contract. +""" +import json +import os +import re +import sys + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from _common import CURSOR_HOME, read_input, allow, deny, log_event, find_data_destructive # noqa: E402 + +_EXEC_TOOL_RE = re.compile( + r"\b(run|execute|exec|bash|shell|command|cmd)\b", re.IGNORECASE +) +_TRUST_PATH = os.path.join(CURSOR_HOME, "mcp-trust.json") + + +def _load_trust() -> dict: + try: + with open(_TRUST_PATH, encoding="utf-8") as fh: + return json.load(fh) + except Exception: + return {"read_only_default": True, "mutating_allowed": []} + + +def _summary(payload: dict) -> dict: + server = ( + payload.get("mcp_server_name") or payload.get("server_name") + or payload.get("server") or payload.get("serverName") or "" + ) + out = { + "tool": payload.get("tool_name") or payload.get("tool") + or payload.get("toolName") or "", + "server": server, + } + if not server: + out["payload_keys"] = sorted(payload.keys()) + return out + + +def _unknown_exec_block(payload: dict) -> str | None: + trust = _load_trust() + if not trust.get("read_only_default", True): + return None + server = ( + payload.get("mcp_server_name") or payload.get("server_name") + or payload.get("server") or payload.get("serverName") or "" + ) + allowed = set(trust.get("mutating_allowed") or []) + if server in allowed: + return None + tool = ( + payload.get("tool_name") or payload.get("tool") + or payload.get("toolName") or "" + ) + if _EXEC_TOOL_RE.search(tool): + return ( + f"MCP exec tool '{tool}' on server '{server or 'unknown'}' blocked " + "(read_only_default). Add server to mcp-trust.json mutating_allowed if intended." + ) + return None + + +def main() -> int: + payload = read_input() + try: + blob = json.dumps(payload, default=str) + except Exception: + blob = str(payload) + + summary = _summary(payload) + why = find_data_destructive(blob) or _unknown_exec_block(payload) + if why: + log_event("mcp", {"decision": "deny", "reason": why, **summary}, context=payload) + deny( + user_message=f"Blocked by guard-mcp: {why}", + agent_message=( + f"A local safety hook blocked this MCP tool call: {why}\n" + "If this is genuinely intended, scope it (add a WHERE clause / " + "target a specific resource) or ask the user to run it manually." + ), + ) + return 0 + + log_event("mcp", {"decision": "allow", **summary}, context=payload) + allow() + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_archives/harness-v4/20260717T192824Z/.cursor/hooks/guard-network.py b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/guard-network.py new file mode 100755 index 0000000..fda1794 --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/guard-network.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""beforeShellExecution: ask before high-confidence outbound exfil patterns. + +Matcher-scoped in hooks.json (curl|wget|scp|nc). Returns permission: ask, not deny, +so legitimate API work can proceed after user review. failClosed:false — secondary net. +""" +from __future__ import annotations + +import os +import re +import sys + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from _common import read_input, allow, emit, log_event # noqa: E402 + +_ASK_PATTERNS: list[tuple[re.Pattern[str], str]] = [ + (re.compile(r"\b(curl|wget)\b[^|]*@\S", re.IGNORECASE), + "Uploading a local file via curl/wget (@file)."), + (re.compile(r"\bscp\b", re.IGNORECASE), "scp may exfiltrate local files."), + (re.compile(r"\bnc\b[^|]*\s+-e\b", re.IGNORECASE), "netcat with -e is a reverse-shell pattern."), + (re.compile(r"\b(curl|wget)\b[^|]*(-d|--data|--data-binary)\s+@", + re.IGNORECASE), "Posting a local file as HTTP body."), +] + + +def ask(user_message: str, agent_message: str) -> None: + emit({ + "permission": "ask", + "user_message": user_message, + "agent_message": agent_message, + }) + + +def main() -> int: + payload = read_input() + command = (payload.get("command") or "").strip() + if not command: + allow() + return 0 + for pattern, why in _ASK_PATTERNS: + if pattern.search(command): + log_event("network", {"decision": "ask", "reason": why, "command": command[:500]}, context=payload) + ask( + user_message=f"Review network command: {why}", + agent_message=( + f"A local hook flagged this shell command for review: {why}\n" + f"Command: {command}\n" + "Proceed only if exfiltration or reverse-shell behavior is intended." + ), + ) + return 0 + log_event("network", {"decision": "allow", "command": command[:200]}, context=payload) + allow() + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_archives/harness-v4/20260717T192824Z/.cursor/hooks/guard-shell.py b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/guard-shell.py new file mode 100755 index 0000000..863d747 --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/guard-shell.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +"""beforeShellExecution: deny a narrow set of clearly destructive commands. + +Secondary denylist net (failClosed:false), NOT the security boundary — Cursor 2.0's +OS sandbox (workspace-scoped, no internet by default on macOS) is primary. This hook +catches a narrow set of high-confidence destructive patterns hooks can see. A +fail-closed launch config would only add brick-risk without closing unlisted commands. +Tuned to avoid false positives (e.g. `rm -rf node_modules`). +""" +import os +import re +import sys + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from _common import read_input, allow, deny, log_event, find_data_destructive, find_worktree_integration_block # noqa: E402 + +RULES: list[tuple[str, str]] = [ + (r"\brm\b(?=(?:\s+-\S+)*\s+-[a-zA-Z]*r)(?=(?:\s+-\S+)*\s+-[a-zA-Z]*f)" + r"(?:\s+-\S+)+\s+['\"]?(/|~|\$HOME|\.|\*)['\"]?/?\*?(?:\s|;|&|$)", + "Recursive force-delete of a root / home / wildcard path."), + (r"\brm\b[^|]*--no-preserve-root\s+['\"]?/['\"]?", + "Recursive delete of root with --no-preserve-root."), + (r"\bgit\s+push\b.*(--force\b|-f\b|--force-with-lease).*(main|master|origin)\b", + "Force-push to a protected branch."), + (r"\bgit\s+push\b.*\b(main|master)\b.*(--force\b|-f\b)", + "Force-push to a protected branch."), + (r"\bgit\s+reset\s+--hard\b", "git reset --hard discards work irreversibly."), + (r"\bgit\s+clean\s+-[a-zA-Z]*f[a-zA-Z]*d", "git clean -fd deletes untracked files."), + (r"\bchmod\s+-R\s+777\b", "Recursive chmod 777 is dangerously permissive."), + (r">\s*/dev/(sd|nvme|disk|rdisk)", "Redirecting output onto a raw disk device."), + (r"\b(curl|wget)\b[^|]*\|\s*(sudo\s+)?(sh|bash|zsh)\b", "Piping a remote download into a shell."), + (r":\(\)\s*\{\s*:\s*\|\s*:?\s*&\s*\}\s*;\s*:", "Fork bomb."), +] +COMPILED = [(re.compile(p, re.IGNORECASE), why) for p, why in RULES] + + +def find_reason(command: str) -> str | None: + for pattern, why in COMPILED: + if pattern.search(command): + return why + # Shared data-layer destruction (DROP/TRUNCATE/mkfs/dd) also applies to shell. + return find_data_destructive(command) + + +def main() -> int: + payload = read_input() + command = (payload.get("command") or "").strip() + why = find_worktree_integration_block(payload) + if not why and command: + why = find_reason(command) + if why: + log_event("shell", {"decision": "deny", "reason": why, "command": command[:500]}, context=payload) + deny( + user_message=f"Blocked by guard-shell: {why}", + agent_message=( + f"A local safety hook blocked this command: {why}\n" + f"Command: {command}\n" + "If this is genuinely intended, ask the user to run it manually, " + "or use a safer, scoped equivalent." + ), + ) + return 0 + if command: + log_event("shell", {"decision": "allow", "command": command[:500]}, context=payload) + allow() + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_archives/harness-v4/20260717T192824Z/.cursor/hooks/protect-secrets.py b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/protect-secrets.py new file mode 100755 index 0000000..9c5bbca --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/protect-secrets.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +"""beforeReadFile: keep secret files out of the model's context. + +Guarded semantics (failClosed:false in hooks.json): +- Missing interpreter / launch failure -> Cursor fails OPEN (a vanished python3 + never bricks all file reads). +- A detected secret file -> explicit `deny` (effective fail-closed on detection). +- An internal error while deciding -> `deny`, rather than risk leaking a file we + failed to classify. +""" +import os +import sys + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from _common import read_input, allow, deny, is_sensitive_file # noqa: E402 + + +def main() -> int: + try: + path = read_input().get("file_path") or "" + sensitive = is_sensitive_file(path) + except Exception: + deny(user_message="protect-secrets hook errored; blocked the read defensively.") + return 0 + if sensitive: + deny( + user_message=( + f"Blocked reading a potential secret file: {os.path.basename(path)}. " + "Its contents were kept out of the AI context." + ), + ) + return 0 + allow() + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_archives/harness-v4/20260717T192824Z/.cursor/hooks/scan-prompt.py b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/scan-prompt.py new file mode 100755 index 0000000..28b837f --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/scan-prompt.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""beforeSubmitPrompt: stop a prompt that contains a live credential. + +Blocks only on high-confidence secret patterns to avoid friction. +Output uses {"continue": bool} per the beforeSubmitPrompt contract. + +Guarded semantics (failClosed:false): launch failure -> fail OPEN; a detected +secret or an internal scan error -> {"continue": false}. +""" +import os +import sys + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from _common import read_input, emit, find_secret # noqa: E402 + + +def main() -> int: + try: + prompt = read_input().get("prompt") or "" + label = find_secret(prompt) + except Exception: + emit({ + "continue": False, + "user_message": "scan-prompt hook errored; blocked submission defensively.", + }) + return 0 + if label: + emit({ + "continue": False, + "user_message": ( + f"Submission blocked: your prompt appears to contain a {label}. " + "Remove or redact the secret and resend. " + "(Rotate it if it was ever exposed.)" + ), + }) + return 0 + emit({"continue": True}) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_archives/harness-v4/20260717T192824Z/.cursor/hooks/verify-on-stop.py b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/verify-on-stop.py new file mode 100755 index 0000000..85d3785 --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/.cursor/hooks/verify-on-stop.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +"""Project-opt-in stop hook: block session end until scripts/verify.sh passes.""" +from __future__ import annotations + +import json +import os +import subprocess +import sys + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from _common import read_input, emit, log_event, resolve_workspace_root # noqa: E402 + +TIMEOUT = 120 +VERIFY_SCRIPT = "scripts/verify.sh" + + +def _had_code_edits(payload: dict) -> bool: + if payload.get("had_code_edits") or payload.get("hadCodeEdits"): + return True + status = payload.get("status") or "" + return status not in ("", "completed_without_edits") + + +def _loop_count(payload: dict) -> int | None: + for key in ("loop_count", "loopCount", "loop_iteration"): + value = payload.get(key) + if isinstance(value, int): + return value + return None + + +def main() -> int: + payload = read_input() + if os.environ.get("CURSOR_VERIFY_SKIP") == "1": + emit({}) + return 0 + + root = resolve_workspace_root(payload) + verify_path = os.path.join(root, VERIFY_SCRIPT) + if not os.path.isfile(verify_path): + emit({}) + return 0 + + if not _had_code_edits(payload): + emit({}) + return 0 + + loop_count = _loop_count(payload) + + try: + proc = subprocess.run( + [verify_path], + cwd=root, + capture_output=True, + text=True, + timeout=TIMEOUT, + check=False, + ) + except subprocess.TimeoutExpired: + log_event( + "verify_fail", + {"decision": "block", "reason": "timeout", "cmd": f"./{VERIFY_SCRIPT}"}, + context=payload, + ) + log_event("verify_on_stop", {"decision": "block", "reason": "timeout"}, context=payload) + emit({ + "followup_message": ( + f"Verification timed out after {TIMEOUT}s running ./{VERIFY_SCRIPT}. " + "Fix or scope the verify script, then try stopping again." + ), + }) + return 0 + + if proc.returncode != 0: + tail = (proc.stderr or proc.stdout or "")[-1500:] + fail_event = "verify_loop_exhausted" if loop_count and loop_count >= 3 else "verify_fail" + log_event( + fail_event, + { + "decision": "block", + "exit_code": proc.returncode, + "cmd": f"./{VERIFY_SCRIPT}", + }, + context=payload, + ) + log_event("verify_on_stop", { + "decision": "block", + "exit_code": proc.returncode, + }, context=payload) + emit({ + "followup_message": ( + f"./{VERIFY_SCRIPT} failed (exit {proc.returncode}). " + "Fix failures before stopping.\n\n" + f"{tail}" + ), + }) + return 0 + + log_event("verify_on_stop", {"decision": "allow", "exit_code": 0}, context=payload) + log_event("verify_pass", {"exit_code": 0, "cmd": f"./{VERIFY_SCRIPT}"}, context=payload) + emit({}) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.harness/VERSION b/_archives/harness-v4/20260717T192824Z/.harness/VERSION similarity index 100% rename from .harness/VERSION rename to _archives/harness-v4/20260717T192824Z/.harness/VERSION diff --git a/.harness/profile.yaml b/_archives/harness-v4/20260717T192824Z/.harness/profile.yaml similarity index 100% rename from .harness/profile.yaml rename to _archives/harness-v4/20260717T192824Z/.harness/profile.yaml diff --git a/_archives/harness-v4/20260717T192824Z/AGENTS.md.pre-corp-site b/_archives/harness-v4/20260717T192824Z/AGENTS.md.pre-corp-site new file mode 100644 index 0000000..d22a4d3 --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/AGENTS.md.pre-corp-site @@ -0,0 +1,46 @@ +# AGENTS.md + +CorpOS harness. Profile: **solo**. + +## Purpose + +TypeScript multi-agent runtime with policy, approval, and audit control plane. Simulation-first demo; optional live LLM via OpenRouter. + +## Prerequisites + +- Node.js ≥20 (`package.json` engines) +- `npm install` (builds `better-sqlite3` native module) + +## Commands + +| Command | Purpose | +| --------------------- | ------------------------------- | +| `./scripts/verify.sh` | Definition of Done | +| `npm install` | Install dependencies | +| `npm run dev` | API + dashboard with hot reload | +| `npm run start` | Run without watch | +| `npm run test` | Vitest suite | +| `npm run typecheck` | `tsc --noEmit` | +| `npm run lint` | ESLint | +| `npm run build` | Compile to `dist/` | + +## Layout + +| Path | Role | +| ---------------- | --------------------------------------------------------- | +| `src/core/` | Orchestrator, policy, store (SQLite at `data/company.db`) | +| `src/agents/` | Department agents | +| `src/tools/` | Permissioned tool registry | +| `src/api/` | Express REST + WebSocket | +| `src/dashboard/` | Control-plane UI | + +## Definition of Done + +```bash +npx npm@10.9.2 ci +./scripts/verify.sh +``` + +## Review focus + +Block on P0/P1: policy chokepoint bypass, approval gate skips, secret exposure, broken simulation determinism. diff --git a/_archives/harness-v4/20260717T192824Z/MANIFEST.json b/_archives/harness-v4/20260717T192824Z/MANIFEST.json new file mode 100644 index 0000000..48fd9c1 --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/MANIFEST.json @@ -0,0 +1,24 @@ +{ + "schema": "harness-v4-archive/v1", + "site_id": "corpos", + "local_path": "/Users/sagehart/Downloads/CorpOS", + "utc": "20260717T192824Z", + "archived": [ + { + "path": ".harness", + "sha256": "a4fabbd97142617b2b2c18b0ef8fcd6ca7c03b488844a665b60c29663af878b5" + }, + { + "path": ".cursor/hooks.json", + "sha256": "422b14c73cfc16070d411d5a41c55df66a9753530aa172bac19f1eb30b602f0b" + }, + { + "path": ".cursor/hooks", + "sha256": "4b9f81919d4742a27e331a9fc2ac1b59aeb57028bb0002a42deed97471b1e776" + }, + { + "path": "AGENTS.md.pre-corp-site", + "sha256": "7cf637571054f8a13be231ab11f79d985eeef7cefa92e0ed2938e8231b37e400" + } + ] +} diff --git a/_archives/harness-v4/20260717T192824Z/README.md b/_archives/harness-v4/20260717T192824Z/README.md new file mode 100644 index 0000000..768888d --- /dev/null +++ b/_archives/harness-v4/20260717T192824Z/README.md @@ -0,0 +1,3 @@ +# Archived Cursor Harness v4 + +Frozen prior harness surface for this checkout. Live control plane is corporate/site (`.corp-harness/`). Do not restore without explicit user authorization. diff --git a/scripts/adversarial.sh b/scripts/adversarial.sh new file mode 100755 index 0000000..2aad7b8 --- /dev/null +++ b/scripts/adversarial.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -euo pipefail +exec "$(cd "$(dirname "$0")" && pwd)/harness/adversarial.sh" "$@" diff --git a/scripts/harness/adversarial.sh b/scripts/harness/adversarial.sh new file mode 100755 index 0000000..817840d --- /dev/null +++ b/scripts/harness/adversarial.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Authorized local adversarial probes (corp-site gate). +# Hermetic stub until a corporate handoff requires real probes. +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +cd "$ROOT" +echo "adversarial: ok (stub — no program-bound probes yet)" diff --git a/scripts/harness/verify.sh b/scripts/harness/verify.sh new file mode 100755 index 0000000..fa854f5 --- /dev/null +++ b/scripts/harness/verify.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# Definition of Done — mirrors CI lint + build matrix jobs (no Docker). +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +cd "$ROOT" + +if [[ -x ./scripts/check-stub-canary.sh ]]; then + ./scripts/check-stub-canary.sh +fi + +if command -v corepack >/dev/null 2>&1; then + corepack enable >/dev/null 2>&1 || true + corepack prepare npm@10.9.2 --activate >/dev/null 2>&1 || true +fi + +echo "==> npm ci (expect packageManager npm@10.9.2)" +npm ci + +echo "==> typecheck + test + lint + format" +npm run typecheck +npm run test +npm run lint +npm run format:check + +echo "verify: ok (ci/web parity)" diff --git a/scripts/verify.sh b/scripts/verify.sh index e2cbaa7..8c7a7b5 100755 --- a/scripts/verify.sh +++ b/scripts/verify.sh @@ -1,25 +1,3 @@ #!/usr/bin/env bash -# Definition of Done — mirrors CI lint + build matrix jobs (no Docker). set -euo pipefail -ROOT="$(cd "$(dirname "$0")/.." && pwd)" -cd "$ROOT" - -if [[ -x ./scripts/check-stub-canary.sh ]]; then - ./scripts/check-stub-canary.sh -fi - -if command -v corepack >/dev/null 2>&1; then - corepack enable >/dev/null 2>&1 || true - corepack prepare npm@10.9.2 --activate >/dev/null 2>&1 || true -fi - -echo "==> npm ci (expect packageManager npm@10.9.2)" -npm ci - -echo "==> typecheck + test + lint + format" -npm run typecheck -npm run test -npm run lint -npm run format:check - -echo "verify: ok (ci/web parity)" +exec "$(cd "$(dirname "$0")" && pwd)/harness/verify.sh" "$@"