Single source of truth for ALL agents (human or AI) working on this repository. Read this file completely before making any change. If reality and this file diverge, fix the divergence in the same PR (code or doc — whichever is wrong).
Last verified against main: v3.28.0 (2026-06-30) — 10 new features (context meter, voice input, decision memory, TUI collapsible, background agents, spec-driven dev, session sharing, plugin system, MCP auto-install, LSP auto-configure) CEO Audit: Score 100, A+, 48/48 gates, 0 unapproved findings, 0 rot-risk. Test suite green and environment-independent.
SIN-Code (formerly SIN-Code-Bundle) is the flagship product of the
OpenSIN-Code organization: a verification-first, self-improving coding
agent shipped as a single Go binary (sin-code), with a Python companion
package (sin / sin serve).
It is simultaneously:
- A coding-agent CLI (
sin-code chat,sin-code -p "...") — interactive REPL/TUI and headless one-shot mode, like Claude Code / Codex CLI, but with a mandatory correctness gate before any task is reported done. - A unified MCP server (
sin-code serve/sin-serve) — 52+ semantic tools consumable by ANY agent (Claude Code, Codex, opencode, our own loop, WebUI-v2). - A multi-agent orchestrator — DAG dispatcher with critic, adversary, governor, episodic memory, confidence scoring, blame/impact analysis, cartographer.
- A bounded-autonomous system (v3.5.0) — goal queue, cron/file triggers, skill-lifecycle manager; the daemon runs goals end-to-end with hard safety invariants.
Unique selling point (never compromise this): every completed task MUST pass the verification gate (PoC proof or Oracle check) before the agent reports success. No other coding agent in the world enforces this.
- NOT a fork of opencode.
OpenSIN-Code/OpenSIN-Codewas an opencode fork and is ARCHIVED (Phase 1, 2026-06-12). Never copy code from it, never reference it as a dependency. - NOT related to Code-Swarm. That is a separate product, out of scope.
- NOT a place to vendor tool implementations that live in their own repos (see ecosystem map, section 5).
- NOT the WebUI. WebUI-v2 lives in its own repo
(
/Users/jeremy/dev/sin-code-web-ui-v2) and is wired viasin-code serveover stdio +@ai-sdk/mcp. The WebUI PR cycle is owned by a separate agent — never edit WebUI-v2 from this repo's agent loop.
NEVER run build/test/lint on normal GitHub Actions runners. This org uses
n8n + OpenSIN-AI/sin-github-action exclusively (webhook secret
N8N_CI_WEBHOOK_URL); all real work executes on the OCI free-tier VM.
The only permitted runs-on: ubuntu-latest job is the ~2s curl delegation
step itself. Docs: docs.opensin.ai/best-practices/ci-cd-n8n
sin-code ships as ONE static Go binary. CGO_ENABLED=0. SQLite via
modernc.org/sqlite only. No runtime dependencies beyond the binary itself.
The agent loop must never report task success while verify_mode != "off"
and the gate has not passed. Default verify_mode is "poc". The
daemon refuses to start without --verify-cmd (autonomy requires a
gate).
Stop-gate (loop engineering, decoupled completion authority): when a
Definition-of-Done contract is present (internal/goalcontract), the worker's
"done" is necessary but NOT sufficient. After the verify-gate passes, an
independent stop-gate (internal/stopgate) confirms the contract — deterministic
checks first (fail-closed: ANY failed check blocks, including predicates), then a
strong/equal LLM judge (SIN_EVALUATOR_MODEL, fallback worker model) for
non-mechanical criteria. A green judge can never override a red deterministic
check. Rejection re-injects the open criteria and forces continued work. All of
this is opt-in and fail-safe: nil stop-gate / empty contract / no contract flag
preserves exact legacy single-gate behavior.
Tool coverage gate (issue #248): the runtime ToolCoverageEnforcer in
internal/agentloop/ is part of the verification gate. When required_tools
are configured and the model completes a run without invoking every required
tool, or when a forbidden_tools entry was invoked, the loop rejects the
completion and re-injects the violation as open criteria. The enforcer is
fail-closed and race-safe (M7).
Daemon loop-engineering flags: --max-continuations (checkpoint+resume past
--max-turns instead of aborting, bounded), --max-depth (sub-goal nesting via
the spawn_subgoal tool), --no-contract (disable Definition-of-Done, revert to
single verify-gate). Discovery: goal discover [--dry-run] and the discover
trigger type turn TODO/FIXME markers and MASTER_TODO.md items into deduplicated
goals. Env vars: SIN_EVALUATOR_MODEL, SIN_EVALUATOR_BASE_URL,
SIN_EVALUATOR_API_KEY.
Headless sandbox mandate (issue #420): every sin-code chat -p,
sin-code chat --json, and sin-code daemon invocation routes sin_bash
through sandbox.Command (landlock on Linux, seatbelt on macOS, bubblewrap
where available). The OS-level isolation is on by default — there is no
turn-off flag that survives audit. --no-sandbox exists on chat as an
explicit, WARN-emitting escape hatch for debugging; the daemon has no such
opt-out (it is headless by mandate). A bare sh -c fallback in
sin_bash is reserved for non-headless REPL mode only when the operator
opts out and never for headless / autonomous runs.
Every tool call goes through the permission engine
(allow / ask / deny). In headless mode, ask resolves to deny
unless --yolo is passed. The daemon is always headless — it cannot
self-escalate permissions.
Headless-mode sandbox baseline (issue #420): the permission engine
gates which tools the LLM may call; the sandbox baseline (M3 above)
crates what those tools can do at the OS level. In headless mode
(-p, --json, daemon) the two layers stack — M4 denies a
destructive tool that the operator would have refused interactively,
and the sandbox confines any tool M4 did approve to the workspace
roots. A second sh -c exit in sin_bash is treated as a defect —
see the audit table in §10 of CHANGELOG.md for the remaining
operator-controlled sh -c paths (verify-cmd, hooks.json
command hooks, *.spec.md verify: directives).
v3.9.0 bridge additions (default policies, see
cmd/sin-code/internal/permission_defaults.go):
| Tool pattern | Policy | Layer | Reason |
|---|---|---|---|
vane__* |
allow | research (Bridged-External) | read-only citations, sandboxed |
superpowers__* |
allow | methodology (obra) | already local, just registered |
dox__* |
allow | context (agent0ai) | protocol check, read-only |
gh_query |
allow | contributing (Bridged-External) | read-only: issue/pr/release/workflow-run/repo |
gh_health |
allow | contributing (Bridged-External) | PATH + auth probe, no side effects |
gh_execute |
ask | contributing (Bridged-External) | mutating ops require human confirmation (M4) |
fusion__tournament |
ask | autonomy (Fusion) | spawns sub-agents, costs money |
fusion__status |
allow | autonomy (Fusion) | read-only tournament status |
fusion__config |
allow | autonomy (Fusion) | read-only config query |
notion__notion_read_* |
allow | productivity (Bridged-External) | read-only Notion: workspaces, pages, databases, blocks, comments, users |
notion__notion_write_* |
ask | productivity (Bridged-External) | mutating Notion: create/update/archive pages, append/delete blocks, comments |
notion__notion_raw_cli |
ask | productivity (Bridged-External) | raw CLI escape hatch — arbitrary subcommands (M4) |
github.com/OpenSIN-Code/SIN-Code (since v3.0.0). The old path
.../SIN-Code-Bundle must not appear in any new code, config, or doc.
The tool router always prefers semantic SIN tools over naive equivalents:
sin_edit over string-replace, SCKG navigation over blind file reads,
EFM environments over ad-hoc mocks.
The orchestrator and any goroutine-using subsystem MUST be verified under
go test -race before merge. The 2026-06-12 v3.0.0 migration surfaced three
real races in internal/orchestrator/dispatcher.go; treat any unguarded
shared-field mutation as a merge blocker.
NEVER write code that uses a library, framework, SDK, or API without first consulting context7 for up-to-date documentation. This is a hard gate — agents that skip this step produce code with hallucinated APIs, stale signatures, and deprecated patterns.
The mandatory pre-code sequence is:
context7__resolve-library-id→ identify the librarycontext7__query-docs→ fetch current docs for the specific API/topicsin_web_search→ supplement with real-world usage examples, edge cases, and community knowledge that docs may not cover- THEN write code
Exceptions (narrow): pure logic with no external dependencies, standard library only, or the user explicitly says "just code it" / "no docs needed". When in doubt, always look it up. The cost of a 2-second docs query is negligible compared to the cost of shipping broken code.
The skill-multimodal-web-tools skill (v3.28.0+) documents the full
5-layer tool inventory and decision tree. context7 is Layer 5 and is
marked as required_tools in the skill frontmatter.
SIN-Code-WebUI-v2 (separate repo, Next.js 16)
AI SDK 6 + @ai-sdk/mcp (stdio)
│ spawns
▼
SIN-CODE-CLI (this repo, cmd/sin-code)
├─ sin-code chat ← interactive REPL + headless one-shot
├─ sin-code sessions ← list/show/rm/fork/tree resumable sessions (parent_id lineage)
├─ sin-code mcp ← list|status|call (debug ecosystem skills)
├─ sin-code goal ← enqueue autonomous goals (v3.5.0)
├─ sin-code daemon ← autonomous worker: lease → verify → learn
├─ sin-code skill ← install/status ecosystem skills (v3.5.0)
├─ sin-code serve ← unified MCP server (52+ tools)
├─ sin-code tui ← standalone TUI binary (live footer/token/cost, v3.24.0)
├─ sin-code webui ← WebUI serve mode
├─ sin-code gh ← v3.9.0: GitHub bridge (3-tier policy)
├─ sin-code hub ← v3.12.0: tool catalog hub
├─ sin-code ledger ← v3.13.0: semantic session ledger
├─ sin-code summary ← v3.13.0: session auto-summary
├─ sin-code compress ← v3.18.0: deterministic + LLM compaction (issue #172)
├─ sin-code audit ← v3.18.0: repo-wide complexity audit (issue #180)
├─ sin-code ceo-audit ← v3.18.0: 48-gate CEO audit with complexity gate (issue #180)
├─ sin-code review ← v3.19.0: ponytail complexity review (issue #179)
├─ sin-code image-graph ← v3.20.0: SOTA ECharts chart generation (bar/line/pie/area)
├─ sin-code catalog ← v3.18.0: unified tool catalog
└─ 90+ subcommands (v3.25.0)
│
▼
┌──────────────────────────────────────────┐
│ AUDIT LAYER (v3.18.0) │
│ • complexity — static + LLM judge (M3) │
│ • ceo-audit — 48 gates incl. complexity │
└──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ AGENT LOOP (agentloop) │
│ PLAN → ACT → VERIFY → DONE │
│ • Permission engine (allow/ask/deny) │
│ • Hook engine (24 lifecycle events) │
│ • Verify Gate (PoC/Oracle, M3) │
│ • Sessions: SQLite, resumable │
│ • Lessons: closed learning loop (v3.4) │
│ • MCP-Client: external servers │
└──────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
internal/llm Orchestrator MCP-Client
(provider) (DAG) (12 skills + Symfony)
│
├─ goal queue (autonomy, v3.5.0)
└─ skill manager (v3.5.0)
Agent loop state machine + learning loop:
PLAN ─► ACT ─► model claims done?
│
▼
VERIFY (PoC/Oracle) ← M3
│ pass │ fail
▼ ▼
DONE VERIFICATION FAILED
│ (report fed back
▼ as user turn — retry)
┌──────────────────┐
│ learning loop on │ ← v3.4.0: lessons pkg
│ verify.fail / │ records failures,
│ tool.error │ briefing on next run
└──────────────────┘
See ECOSYSTEM.md for the complete inventory with integration status and
sync rules. Single-line summary:
| Layer | Repos | Integration |
|---|---|---|
| Agent + Tool plane | SIN-Code (this repo) | The product |
| Web frontend | SIN-Code-WebUI-v2 (/Users/jeremy/dev/sin-code-web-ui-v2) |
Spawns sin-code serve; follows releases |
| Multi-agent fan-out | SIN-Code-Orchestration | External MCP server |
| Verification & analysis (issue #28) | SCKG-Tool, IBD-Tool, PoC-Tool, ADW-Tool, EFM-Tool, Oracle-Tool, Symfony-Lens | CLI subprocess + MCP |
| Code intelligence | Simone-MCP | External MCP server (AST/LSP) |
| Browser automation | SIN-Browser-Tools | External MCP server (106 tools) |
| Skills (12) | websearch, scheduler, goalmode, grillme, marketplace, codocs, contextbridge, honcho, frontend, mcpbuilder, browser, simone | External MCP servers (registry.go) |
| LLM backends | SIN-Code-FireworksAI-OpenCode-Config | Agent profiles (profiles/*.toml) |
| Distribution | homebrew-sin | goreleaser pushes formula sin-code |
| Infra | Infra-SIN-OpenCode-Stack | Deployment |
| Archived — never use | OpenSIN-Code, SIN-Code-Bundle-Web, 6 long-name duplicates, coder-SIN-Qwen | Do not reference |
| Out of scope | Code-Swarm | Separate product |
SIN-Code/
├── AGENTS.md ← this file (single source of truth)
├── README.md
├── CHANGELOG.md
├── ECOSYSTEM.md ← complete org inventory + sync rules
├── go.mod ← module github.com/OpenSIN-Code/SIN-Code
├── .goreleaser.yaml
├── .github/workflows/
│ ├── ceo-audit.yml ← n8n delegation (mandate M1) + profile-verify job (issue #175)
│ ├── release.yml ← goreleaser + brew tap
│ └── ecosystem-sync.yml ← prevents registry/permission/ECOSYSTEM drift
├── install.sh ← 27-line curl|bash shim → `sin-code install` (issue #170)
├── install.ps1 ← PowerShell equivalent shim (issue #170)
├── profiles/ ← v3.4.0: agent profile TOML files
│ ├── fireworks.toml
│ └── qwen-relay.toml
├── docs/
│ ├── HOOKS.md
│ ├── LEARNING.md
│ ├── WEBUI.md ← WebUI-v2 backend contract
│ ├── mcp.json.example
│ └── agent-profiles/
│ └── sin-profile.md ← v3.18.0: single-source-of-truth per-agent profile (issue #175)
│
├── cmd/
│ ├── sin-code/ ← MAIN BINARY (90+ subcommands — v3.25.0)
│ │ ├── main.go ← cobra root; AddCommand for all subcommands
│ │ ├── commands.go ← command registration + shared helpers
│ │ ├── tui.go, webui_cmd.go
│ │ ├── chat_cmd.go ← v3.4.0: chat + -p headless
│ │ ├── chat_tools.go ← builtin toolset
│ │ ├── chat_tools_extra.go ← v3.5.0: sin_git_*, sin_test, sin_http_get
│ │ ├── chat_mcp.go ← combinedTool/combinedSpecs
│ │ ├── audit_cmd.go ← v3.18.0: repo-wide complexity audit (issue #180)
│ │ ├── review_cmd.go ← v3.19.0: `review --complexity` ponytail 5-tag review (issue #179)
│ │ ├── fusion_cmd.go ← v3.22.0: SIN Fusion benchmark/rank/recommend
│ │ ├── research_cmd.go ← v3.23.0: autonomous research report (issue #384)
│ │ ├── hub_cmd.go ← v3.12.0: tool catalog hub subcommand
│ │ ├── stack_cmd.go ← v3.8.0: unified install/doctor coordinator
│ │ ├── status_cmd.go ← readiness snapshot
│ │ ├── permission_defaults.go ← C4: default rules + MCP prefix policy
│ │ ├── security_scan_commands.go ← v3.24.0: merged security scan subcommands (secrets/SAST/SCA/SBOM/container)
│ │ └── internal/ ← 95 packages (v3.25.0) — key ones:
│ │ ├── agentloop/ ← PLAN→ACT→VERIFY→DONE loop
│ │ ├── session/ ← SQLite-backed resumable sessions
│ │ ├── permission/ ← allow/ask/deny engine
│ │ ├── verify/ ← mandatory PoC/Oracle gate
│ │ ├── mcpclient/ ← external MCP consumption
│ │ ├── hooks/ ← 24 lifecycle events
│ │ ├── hooklife/ ← v3.19.0: programmatic hook system + autoactivate
│ │ ├── commands/ ← custom slash commands
│ │ ├── lessons/ ← v3.4.0: closed learning loop
│ │ ├── learning/ ← learning commands + helpers
│ │ ├── autonomy/ ← v3.5.0: goal queue + triggers
│ │ ├── skillmgr/ ← v3.5.0: install/verify skills
│ │ ├── skilldist/ ← v3.17.0: marker-fenced skill distribution (issue #169)
│ │ ├── loopbuilder/ ← v3.4.0: shared factory (DRY)
│ │ ├── stopgate/ ← v3.x: decoupled completion authority
│ │ ├── goalcontract/ ← v3.x: Definition-of-Done contracts
│ │ ├── llm/ ← provider layer
│ │ ├── style/ ← v3.17.0: verbosity / compression mode renderer (issue #167)
│ │ ├── orchestrator/ ← DAG, critic, adversary, governor, cartographer
│ │ ├── memory/ ← store/search/embed
│ │ ├── compress/ ← v3.18.0: deterministic + LLM compaction (issue #172)
│ │ ├── mcpcompress/ ← v3.19.0: ponytail-tag compressor (issue #173)
│ │ ├── sindept/ ← v3.18.0: sin-debt marker scanner (issue #177)
│ │ ├── complexity/ ← v3.19.0: static ponytail complexity analyzer (issue #179)
│ │ ├── audit/ ← v3.18.0: CEO audit engine (issue #180)
│ │ ├── vane/ ← v3.8.0: HTTP bridge to Vane
│ │ ├── stack/ ← v3.8.0: unified install/doctor
│ │ ├── hub/ ← v3.12.0: static tool catalog
│ │ ├── ledger/ ← v3.13.0: semantic session ledger (SQLite)
│ │ ├── summary/ ← v3.13.0: deterministic session summary builder
│ │ ├── install/ ← v3.18.0: pure-stdlib release install (issue #170)
│ │ ├── profile/ ← v3.18.0: single-source-of-truth profile renderer (issue #175)
│ │ ├── eval/ ← v3.18.0: issue #75 eval + observability
│ │ ├── dataset/ ← v3.18.0: golden-dataset JSON parser
│ │ ├── trace/ ← v3.18.0: OpenTelemetry TracerProvider
│ │ ├── evalharness/ ← v3.18.0: 4-arm comparator (issue #171)
│ │ ├── modelperf/ ← v3.22.0: per-model performance registry (issue #395)
│ │ ├── fusion/ ← v3.22.0: SIN Fusion tournament
│ │ ├── ghbridge/ ← v3.9.0: GitHub bridge (3-tier policy)
│ │ ├── isolation/ ← v3.20.0: git-worktree primitives (issue #194)
│ │ ├── auto_mem/ ← v3.20.0: byte-stable MEMORY.md
│ │ ├── rules/ ← v3.20.0: path-scoped rule loader (issue #195)
│ │ ├── agentteams/ ← v3.20.0: file-locked agent-team mailbox (issue #203)
│ │ ├── imagegraph/ ← v3.20.0: SOTA ECharts chart generation
│ │ ├── testgate/ ← v3.21.0: test-first verify-loop tools
│ │ ├── testgen/ ← v3.21.0: test generation
│ │ ├── swebench/ ← v3.23.0: SWE-bench test suite (issue #363)
│ │ ├── security/ ← v3.24.0: Security Scanning V2
│ │ ├── vision/ ← v3.24.0: vision model for analyse-image (issue #423)
│ │ ├── telemetry/ ← v3.24.0: live progress / NDJSON events
│ │ ├── filemode/ ← v3.x: SIN_CODE_FILE_MODE policy
│ │ ├── sandbox/ ← v3.x: OS-level sandbox (landlock/seatbelt/bubblewrap)
│ │ ├── config/ ← unified config subsystem
│ │ ├── catalog/ ← v3.20.0: unified tool catalog
│ │ ├── circuitbreaker/← v3.x: circuit breaker pattern
│ │ ├── egress/ ← v3.x: egress filtering
│ │ ├── health/ ← v3.x: health checks
│ │ ├── adapters/ ← v3.x: store adapters
│ │ ├── wiring/ ← v3.x: dependency wiring
│ │ ├── chat/ ← v3.x: chat package
│ │ ├── dispatch/ ← v3.x: dispatch helpers
│ │ ├── meta/ ← v3.x: metadata
│ │ ├── logger/ ← v3.x: structured logging
│ │ ├── usage/ ← v3.x: token usage tracking
│ │ ├── resource/ ← v3.x: resource management
│ │ ├── rag/ ← v3.x: RAG helpers
│ │ ├── native_browser/← v3.x: native browser integration
│ │ ├── native_websearch/← v3.x: native web search
│ │ ├── websearch/ ← v3.x: web search
│ │ ├── autodev/ ← v3.x: autodev bridge
│ │ ├── autopilot/ ← v3.x: autopilot mode
│ │ ├── autopr/ ← v3.x: auto-PR
│ │ ├── autolevel/ ← v3.x: auto-leveling
│ │ ├── checkpoint/ ← v3.x: workspace checkpointing
│ │ ├── codegraph/ ← v3.x: code graph bridge
│ │ ├── coverdrohne/ ← v3.x: coverage drone
│ │ ├── dox/ ← v3.x: AGENTS.md hierarchy (dox protocol)
│ │ ├── grill/ ← v3.x: adversarial design review
│ │ ├── instinct/ ← v3.x: learned instincts
│ │ ├── prp/ ← v3.x: PRP workflow
│ │ ├── rtk/ ← v3.x: Rust Token Killer bridge
│ │ ├── spec/ ← v3.x: Spec-Layer contracts
│ │ ├── status/ ← v3.x: status snapshot
│ │ ├── triage/ ← v3.x: issue triage
│ │ ├── tui/ ← TUI runtime
│ │ ├── webui/ ← WebUI server
│ │ ├── apiweb/ ← v3.x: web API helpers
│ │ ├── assets/ ← v3.x: harvested assets
│ │ ├── attachments/ ← v3.x: file attachments
│ │ ├── lsp/ ← LSP integration
│ │ ├── notifications/ ← notification management
│ │ ├── todo/ ← issue tracker
│ │ ├── plugins/ ← plugin management
│ │ └── testutil/ ← test utilities
│ ├── sin-tui/ ← standalone TUI binary
│ ├── complexity-review.md ← v3.19.0: ponytail complexity review docs
│ └── mcp.json.example
│
├── SIN-Code-Container-Tool-Go/ ← vendored Go module at repo root (own go.mod)
├── SIN-Code-SAST-Tool/ ← vendored Go module at repo root (own go.mod)
├── SIN-Code-SBOM-Generator/ ← vendored Python module at repo root
├── SIN-Code-SBOM-Generator-Go/ ← vendored Go module at repo root (own go.mod)
├── SIN-Code-SCA-Tool-Go/ ← vendored Go module at repo root (own go.mod)
├── SIN-Code-Secrets-Scanner/ ← vendored Go module at repo root (own go.mod)
├── SIN-Code-Security-Bundle/ ← vendored Python sec-stack at repo root
└── CEO-AUDIT-REPORT-4-...md ← vendored reports/repos at repo root
│
├── src/sin_code_bundle/ ← Python companion: `sin` CLI + `sin-serve`
├── skills/ ← 41 bundled skills in category directories
│ ├── browser-skills/
│ ├── code-skills/
│ ├── debug-skills/
│ ├── design-skills/
│ ├── ecosystem-skills/
│ ├── github-skills/
│ ├── infrastructure-skills/
│ ├── memory-skills/
│ ├── multimodal-skills/
│ ├── planning-skills/
│ ├── process-skills/
│ └── shop-skills/
├── tests/ ← Go + Python tests
└── scripts/ ← validate_skill.py, ci-precheck.sh, build_changelog.sh, marketplace-*.sh, etc.
The four orchestrator sub-agents — Critic, Adversary, Governor,
Cartographer — emit caveman-style one-liners via Finding structs in
cmd/sin-code/internal/orchestrator/output_contract.go. The contract is
the prose layer; the structured result types (e.g. AdversaryResult.Attacks)
are unchanged.
One-liner shape (byte-stable, em-dash U+2014 separator):
<path>:<line> — <symbol> — <tag> — <hint> # c=<confidence>
5 closed tags (parallel to JuliusBrussee/ponytail):
| Tag | Meaning |
|---|---|
delete |
remove this code / path / symbol |
simplify |
inline, collapse, reduce |
rebuild |
rewrite from scratch |
risk |
blast radius, regression source |
verify |
needs human verification |
Hedging forbidden in Hint (closed set, case-folded):
you might, perhaps, could consider, maybe, i think, i would,
sort of, kind of, tends to, should probably, i'd suggest,
we should. VerifyFindings rejects every finding whose hint contains
any of these — the sub-agent loses the entire batch, not silently
passes.
Wired into: CriticResult.Findings (parsed from the last attempt's
prose; CriticResult.ParseErrors carries the per-line rejection trace),
AdversaryResult.Findings (derived from each Attack), GovernorResult.Findings
(one per Escalation, anchored at task://<ID>), Cartographer.Findings(k)
(top-k by PageRank, opt-in — k ≤ 0 yields empty). Byte-stability is a hard
prerequisite for downstream consumers (issue #168 ledger hashing,
orchestrator re-ingestion cost).
This file is distinct from contract.go, which owns the Intent Contract
(task-scope: allowed globs, frozen globs, forbidden patterns, blast radius).
Output-contract is the prose-shape contract; the two have no shared
types and no shared parser.
User-level ~/.config/sin/sin-code.toml, overridden by project-level
./.sin-code/config.toml (deep-merge, project wins). The TOML-like file uses
flat namespaced keys (e.g. llm.base_url, permissions.tools_allow) because
the parser is dependency-free (M2). Manage it with sin-code config:
init, show, validate, get, set, list, path. Secrets are masked
in show unless --plain is passed. See cmd/sin-code/internal/config.go
and config.doc.md for the full schema and validation rules.
Agent profiles (profiles/*.toml) are copied/symlinked into
~/.config/sin-code/agents/<name>/agent.toml. The bundled fireworks and
qwen-relay profiles set tools_allow to the full SIN tool surface and all
registered MCP prefixes (issue #249). Destructive SIN builtins (sin_bash,
sin_git_commit, sin_test_generate, sin_browser_navigate) are intentionally
omitted from the profile allow list so they remain at the default "ask" tier and
are still gated by the permission engine in headless mode (mandate M4).
Tool coverage config keys (issue #248):
| Config key | Type | Default | CLI equivalent |
|---|---|---|---|
agentloop.required_tools |
comma-separated list | [] |
--require-tools |
agentloop.forbidden_tools |
comma-separated list | [] |
--forbid-tools |
These are parsed by the stdlib TOML reader as flat strings and converted to
slices by cmd/sin-code/internal/config.go. They are forwarded through
loopbuilder.Config into agentloop.Loop.CoverageRequiredTools /
CoverageForbiddenTools and into spawned subagents.
Autonomous container execution config keys (issue #389):
| Config key | Type | Default | CLI equivalent |
|---|---|---|---|
autonomy.container.enabled |
bool | false |
--container |
autonomy.container.image |
string | "" |
--container-image |
When enabled, the daemon runs the verify command inside the container via
docker run --rm -v <workspace>:/workspace ... <image>. The Docker binary is an
external runtime dependency; the Go code has no CGO or Docker-SDK dependency (M2).
Session DB: ~/.local/share/sin-code/sessions.db (SQLite, modernc).
Schema: sessions(id, created_at, updated_at, title, parent_id) with
parent_id TEXT REFERENCES sessions(id) ON DELETE SET NULL (issue #194) —
recorded automatically by every Store.Fork/ForkEx invocation and walked
upward by Store.Tree. Idempotent ALTER TABLE migration for pre-#194 DBs.
Lessons DB: ~/.local/share/sin-code/lessons.db (SQLite, modernc).
Goal Queue DB: ~/.local/share/sin-code/goals.db (SQLite, modernc).
Ledger DB: ~/.local/share/sin-code/ledger.db (SQLite, modernc), overridable
via SIN_CODE_LEDGER.
Compress snapshots: ~/.local/share/sin-code/compress-snapshots/<plan-id>.json
(JSON, one file per Apply), overridable via SIN_CODE_SNAPSHOT_DIR. Each
snapshot is content-addressed (Plan.ID is plan-<sha256-prefix>) and is
the rollback artifact for sin-code compress rollback <id> (issue #172).
Chat tools that close the loop from code written to tests verified:
| Tool | Policy | Purpose |
|---|---|---|
sin_test |
allow | Run tests with -race, -cover, structured JSON output. |
sin_test_generate |
ask | Generate table-driven Go tests (mutating — writes files). |
sin_quality_gate |
allow | Pipeline: build → vet → test → optional staticcheck/gosec/govulncheck. |
sin_mutation |
allow | Wrap gremlins unleash if present on PATH. |
sin_fuzz |
allow | Run go test -fuzz targets. |
sin_property |
allow | Run property-based tests (rapid / testing/quick). |
Auto-generation: sin_write/sin_edit automatically invoke sin_test_generate
when SIN_AUTO_GENERATE_TESTS=1 is set or test.auto_generate = true is
configured. The default is off for performance/privacy.
Config keys:
| Config key | Type | Default | Used by |
|---|---|---|---|
test.coverage_threshold |
float (0–100) | 0 |
sin_quality_gate default |
test.mutation_threshold |
float (0–100) | 0 |
sin_mutation default |
test.auto_generate |
bool | false |
Auto-trigger sin_test_generate on writes |
test.timeout_seconds |
int | 300 |
Default timeout for test tools |
test.use_llm |
bool | false |
sin_test_generate calls configured LLM to fill cases |
Hook payload: tool.post events for sin_write/sin_edit now include the
edited file path in data.path and expose it as $SIN_HOOK_DATA_PATH to
command hooks.
| Config key | Type | Default | Used by |
|---|---|---|---|
fusion.enabled |
bool | false |
loopbuilder — enables tournament on verify.fail |
fusion.providers |
comma-separated list | ["minimax-m3", "kimi-k2p7-code-fast", "kimi-k2p7-code", "deepseek-v4-pro", "qwen-3p7-plus", "glm-5p2"] |
fireworks_pool — which models to fan out to |
fusion.max_cost_usd |
float | 5.0 |
tournament — USD kill-switch per invocation |
fusion.min_quorum |
int | 1 |
tournament — minimum passers before declaring winner |
fusion.per_provider_timeout_s |
int | 120 |
tournament — per-model wall-clock timeout |
fusion.difficulty_gate |
bool | true |
difficulty.go — filter stylistic failures to legacy retry |
fusion.oracle_mode |
bool | false |
loopbuilder — oracle-mode tournament with judge safety (issue #344) |
Oracle mode is opt-in and gated: it only activates when fusion.enabled = true, fusion.oracle_mode = true, and the gate is in oracle mode. Unlike PoC mode, oracle mode does not use first-pass-wins; all candidates run to completion, a single judge evaluates all outputs in randomized order, and the highest-scoring candidate wins. Default cost cap is tighter ($2.00) and fusion__oracle_tournament is ask policy (M4).
cmd/sin-code/internal/agentloop/compaction_types.go adds a mode-based
compaction layer on top of the legacy CompactionStrategy switch
(issue #278). The new API (Compect2(ctx, CompactInput) CompactResult)
honours mandate M3: verification evidence is always preserved
(agentloop.compaction_preserve_evidence=true by default).
| Config key | Type | Default | Used by |
|---|---|---|---|
agentloop.context_compaction |
enum | "off" |
loopbuilder — selects the new compaction mode (off|deterministic|llm|hybrid) |
agentloop.compaction_trigger |
enum | "tokens" |
agentloop — when the compactor fires (turns|tokens|both) |
agentloop.context_window |
int | 0 (auto) |
agentloop — effective token cap; 0 = CompactionMaxTokens * 4 |
agentloop.compaction_preserve_evidence |
bool | true |
agentloop — keep system prompt, first user goal, last N turns, role:tool messages, and any message matching VERIFICATION PASSED | VERIFICATION FAILED | NOT DONE | Open acceptance criteria |
agentloop.compaction_recent_turns |
int | 4 |
agentloop — number of recent human turns the retain rule keeps |
agentloop.compaction_max_tokens |
int | 8000 |
agentloop — token budget for compacted messages |
cmd/sin-code/internal/agentloop/session_context.go plus the store adapters
in cmd/sin-code/internal/loopbuilder/session_context_stores.go assemble a
unified markdown preamble from open todos, the previous session summary, and
the workspace/user MEMORY.md. The preamble is injected as a user message
before the Definition-of-Done preamble and the first user prompt, but only
when the session history is empty (i.e. a brand-new session) and the builder
returns a non-empty result. Errors from any store are non-fatal.
| Config key | Type | Default | Used by |
|---|---|---|---|
agentloop.session_context.enabled |
bool | true |
loopbuilder/chat — enables the unified session-start preamble |
Request-only compaction (mandate M3): when a non-off Mode is
selected, Loop.Run keeps the persisted msgs slice full in the
session DB and produces a deterministically compacted view for the
model via Compact2. The legacy Compact() API (used by
agentloop.compaction_strategy=… callers) remains unchanged for
backward compatibility.
Sidecar snapshots: lossy modes (llm, hybrid) write a
content-addressed JSON snapshot to
~/.local/share/sin-code/context-snapshots/<session-id-hash>/turn-NNNNN.json
(atomic temp+rename). The loop's persisted history stays complete; the
sidecar is the audit/rollback artifact and the surface that downstream
compressor_test.go-style golden harnesses consume (issue #172).
Byte-stability: every Compact2 output is byte-stable per
(input, Config) pair so the eval harness (issue #171), the four-arm
comparator, and the compress unit tests can pin deterministic
snapshots.
`cmd/sin-code/internal/modelperf/` — SQLite-backed per-model-per-category performance database that drives benchmark-based model selection for Fusion.
| Path | Purpose |
|---|---|
| `internal/modelperf/store.go` | SQLite store: upsert, recommend, ranking, categories |
| `internal/modelperf/benchmark.go` | Parallel benchmark runner across providers |
| `fusion_cmd.go` | `sin-code fusion benchmark/rank/recommend` subcommands |
Schema (`modelperf.db`, `~/.local/share/sin-code/modelperf.db`):
```sql CREATE TABLE model_perf ( id INTEGER PRIMARY KEY AUTOINCREMENT, model TEXT NOT NULL, category TEXT NOT NULL, dataset TEXT NOT NULL, pass_rate REAL NOT NULL, avg_latency_ms INTEGER DEFAULT 0, avg_cost_usd REAL DEFAULT 0, avg_tokens INTEGER DEFAULT 0, sample_count INTEGER DEFAULT 1, recorded_at TEXT NOT NULL, UNIQUE(model, category, dataset) ); ```
Score formula: `0.8 * pass_rate + 0.2 * (1 / (1 + avg_cost))`
Task categories (auto-detected from prompt keywords): `code-generation`, `debugging`, `planning`, `refactoring`, `review`, `documentation`, `security`.
Integration: loopbuilder opens modelperf.db, detects the task
category from Config.TaskDescription, queries recommendations, and
sorts providers: recommended first, then the rest. Cold-start (empty DB)
falls back to the full provider pool.
| Config key | Type | Default | CLI equivalent |
|---|---|---|---|
output.progress |
enum | "off" |
--progress |
output.progress_dest |
enum | "stderr" |
--progress-dest |
output.progress_file |
string | "" |
--progress-file |
When output.progress is not "off", the agent loop emits structured
NDJSON progress events (turn.start, tool.pre, tool.post,
verify.pass, verify.fail, task.complete, task.abort) to the
destination specified by output.progress_dest. The default destination
is stderr so the stable headless JSON contract on stdout remains
untouched. Tool events include only metadata (tool, output_bytes,
error); raw output is never echoed. Progress output is also wired into
sin-code daemon with goal_id and worker_id decoration.
The interactive TUI (sin-code tui) displays a persistent footer that
updates live during streaming and agent runs:
- Token/cost footer: live token count, estimated USD cost, and stream duration refresh every 250 ms while the model is streaming or a tool is running.
- Tool timing: every local tool invocation fires
Loop.ToolStartandLoop.ToolEndcallbacks carrying the elapsedduration. The TUI renders these in the tool tree and footer; headless mode forwards them through the sameProgressWriteras structured NDJSON events. - Esc interrupt: pressing
Escin the TUI chat input cancels the in-flight prompt/model request and stops the live ticker immediately.
The footer is read-only telemetry; it does not change tool behavior or the verification gate.
| Config key | Allowed values | Default |
|---|---|---|
llm.style |
default | verbose | normal | terse | ultra |
default |
The setting is read at startup and forwarded into
internal/style.RenderRules via wiring.Deps.Style and
learning.Learner.BeforeTurn. The renderer is dependency-free
(contributes bytes only) and is byte-stable per (mode, skillBody)
pair — a prerequisite for the system-prompt hash metric (issue #2).
default and verbose are pass-throughs (no ruleset injected);
normal, terse, ultra emit the caveman-derived ruleset that
drops pleasantries, hedging, and tool-call narration while preserving
every byte of code, URLs, paths, error strings, and func/var/
const names. Every ruleset carries the auto-clarity clause
that drops to normal prose around destructive, security-relevant, or
order-sensitive actions (mandate M3, the verification gate is sacred).
Headless JSON contract (stable API — never break without major bump):
{ "session_id": "…", "summary": "…", "verified": true, "turns": 12 }| Version | Status | Contents |
|---|---|---|
| v3.0.0 | ✅ SHIPPED | Bundle→SIN-Code rename, module-path migration, race-fix |
| v3.1.0 | ✅ SHIPPED | C1-C5: agentloop, session, verify, permission, mcpclient |
| v3.2.0 | ✅ SHIPPED | C7 hooks (24 events) + C8 slash commands |
| v3.4.0 | ✅ SHIPPED | Einstein Layer: closed learning loop, loopbuilder, MCP wiring, ECOSYSTEM.md |
| v3.5.0 | ✅ SHIPPED | Bounded Autonomy: goal queue, triggers, skillmgr, daemon |
| v3.6.0 | ✅ SHIPPED | Swarm mode, bootstrap-skill (self-extending), TUI v3.3.1 embed, WebUI-v2 HTTP API |
| v3.7.0 | ✅ SHIPPED | sin-code superpowers — obra/superpowers integration with supply-chain pinning + review-before-trust updates |
| v3.8.0 | ✅ SHIPPED | Vane HTTP-bridge (vane__* research), Stack consolidation (stack install/doctor across superpowers+dox+vane), 33 → 35 subcommands, Bridged-External + stdio MCP architecture, 47/47 ecosystem-sync gates green |
| v3.9.0 | ✅ SHIPPED | GitHub bridge (internal/ghbridge/, 3-tier policy: allow/ask/forbidden), gh subcommand (setup/doctor/run/surface/serve), 3 MCP tools (gh_query allow, gh_health allow, gh_execute ask), 35 → 36 subcommands, issue-first contributing workflow now agent-executable |
| v3.10.0 | ✅ SHIPPED | --version flag fix (#38), .gitignore for TUI runtime DB (#61), AGENTS.md rollout to 6 ecosystem repos (#40) |
| v3.11.0 | ✅ SHIPPED | sin update e2e self-update (#33), security + sbom MCP tools (#36), 36 → 36 subcommands |
| v3.12.0 | ✅ SHIPPED | Tool catalog hub (internal/hub/, hub_cmd.go), sin-code hub list/search/info, 36 → 37 subcommands, closes #35 |
| v3.13.0 | ✅ SHIPPED | Semantic Session Ledger (internal/ledger/, internal/summary/), sin-code ledger list/show, sin-code summary, deterministic auto-summaries with verification evidence, 37 → 39 subcommands, closes #43 |
| v3.14.0 | ✅ SHIPPED | Unified config subsystem (#34): sin-code config init/show/validate, expanded TOML schema, user + project deep merge, atomic writes, secret masking, 39 subcommands |
| v3.15.0 | ✅ SHIPPED | Go-native SCA Phase 1 (#41), race-flake hardening (#59) |
| v3.16.0 | ✅ SHIPPED | Forge integration (#37): sin forge command, sin status detection, 16th MCP tool in mcp_config |
| v3.17.0 | ✅ SHIPPED | TUI runtime DB .gitignore, MCP warning deduplication, marketplace update test hardening, skills 33 → 34 |
| v3.18.0 | ✅ SHIPPED | Memory compaction (internal/compress/, compress_cmd.go, issue #172): deterministic dedupe + byte-budget + sort, optional LLM summarization (`--strategy llm |
| v3.19.0 | ✅ SHIPPED | sin-code serve --compress-tools (issue #173): ponytail-tag compressor in internal/mcpcompress/ shrinks the 47-tool manifest on the wire. Tag set `delete |
| v3.20.0 | ✅ SHIPPED | Tool coverage, M6 enforcement, catalog, telemetry (issues #249, #253, #248, #250, #252, #251): agent profiles expose full sin_* + MCP prefix surface; system prompt injects SIN-tool preference fragment; runtime ToolCoverageEnforcer rejects missing/forbidden tool usage; ledger tools heatmap/coverage/unused; orchestrator planner emits mandatory ToolChain per intent; sin-code catalog unifies 49+ MCP tools, 17+ chat tools, and 14+ external MCP prefixes. sin-code image-graph — SOTA ECharts chart generation (bar/line/pie/area); skill-github-readme bundled. 42 subcommands, 40 bundled skills. |
| v3.21.0 | ✅ SHIPPED | Test-First Verify-Loop (RFC-test-automation.md): sin_test + sin_test_generate + sin_quality_gate + sin_mutation + sin_fuzz + sin_property; tool.post hook payload path; test.* config keys; evals/test-generation.json golden dataset. |
| v3.22.0 | ✅ SHIPPED | SIN Fusion v1 enhancements: Plan-Merge mode (issue #393 — N planners → judge merges → 1 coder → verify, preserves all insights); Oracle as default (issue #394 — quality over cost, was: PoC first-pass-wins); Model Performance Registry (issue #395 — modelperf.db, fusion benchmark/rank/recommend CLI, auto-wired into loopbuilder). Pre-existing fixes: llm/provider.go+recorder.go+stream.go ThinkingTokens + 8-arg RecordUsage; agentloop/compaction_helpers.go for compaction_types.go; vet fix in orchestrator/event_dispatch_test.go. |
| v3.23.0 | ✅ SHIPPED | v3.23.0 roadmap batch 1: autonomous research report (sin-code research, issue #384), SWE-bench test suite (issue #363), scientific research skill (issue #387), sin_apply_diff/sin_generate_diff chat tools (issue #365), dynamic MCP server discovery (sin-code mcp discover/add, issue #368). Also repaired main build drift from parallel-agent work. Remaining open: #364, #373, #374, #388, #389. |
| v3.24.0 | ✅ SHIPPED | TUI/agentloop/headless live progress: live tool timing + NDJSON progress + live token/cost footer (issue #424); Esc cancels in-flight TUI prompt; autonomy trigger loops exit promptly on context cancellation; test suite made environment-independent; sin-code analyse-image vision model (issue #423); Security Scanning V2 (secrets/SAST/SCA/SBOM/container/SARIF); Complexity cleanup: 55+ files merged, all analyzers fixed, scoring corrected, 0 unapproved findings, 0 rot-risk markers. |
| v3.25.0 | ✅ SHIPPED | 4 new subcommands: doctor (unified health check — 11 checks, Go/config/DBs/MCP/tools/CGO/module-path), diff (git diff with complexity + sin-debt overlay), benchmark (eval golden dataset runner with scoring report), tokens cost (cost projection + budget alerts from token ledger). 4 parallel subagents, 90 new tests. CEO Audit: Score 100, A+, 48/48 gates. |
| v3.26.0 | ✅ SHIPPED | sin_web_search chat tool — free DuckDuckGo web search (keyless, no API key needed) + optional Tavily/SerpAPI/Brave multi-provider engine. YouTube for AI Agents MCP integration — 9 YouTube tools (search, transcript, video info, channel videos/info, playlist, download, clip, highlight reel) with no YouTube Data API key. DuckDuckGo parser fix for real /ac/ endpoint format. MCP stdio subprocess context fix (process was killed after 3s connect timeout → context.Background()). MCP connect timeout 3s→10s. 4 god-files split: update.go 1747→371, chat_render.go 1107→307, chat_tools_extra.go 1126→192, loop.go 1009→465. No file over 1000 lines remains. |
| v3.27.0 | ✅ SHIPPED | vibe-notion MCP bridge — full Notion access (pages, databases, blocks, comments, users, workspaces) via Bridged-External pattern wrapping the vibe-notion npm CLI. 19 MCP tools (10 read auto-allowed, 8 write gated ask, 1 raw escape hatch). Act-as-user mode via token_v2 from browser session, or bot mode via NOTION_TOKEN. Registered in config.go (notionConfig), permission defaults in permission_defaults.go, bundled skill at skills/productivity-skills/skill-productivity-notion/. ECOSYSTEM.md updated. |
| v3.28.0 | ✅ SHIPPED | 10 features: Context Meter (#484 — visual token bar, 80% warn, 90% compact), Voice-to-Code (#481 — --voice flag, sox/ffmpeg + whisper), Decision Memory (#488 — SQLite architectural decisions, workspace-isolated, search), TUI Collapsible Output (#491 — Tab to expand/collapse tool output, 5-line preview), Background Agents (#479 — fire-and-forget async job manager), Spec-Driven Dev (#480 — EARS parser → architecture → code), Session Sharing (#482 — export/import JSON+HTML), Plugin System (#489 — unified registry MCP/skill/tool/hook), MCP Auto-Install (#490 — 12 known servers, discover/install/uninstall), LSP Auto-Configure (#492 — detect gopls/pyright/tsserver/rust-analyzer/clangd/lua/java). 5 new CLI subcommands: context, decision, background, spec-driven, share, mcp-install, lsp-config. 106 subcommands total. 43 new tests. |
Each release tag ⇒ goreleaser builds linux/darwin/windows × amd64/arm64,
updates homebrew-sin formula, and ships to GitHub Releases.
- Go 1.26+. Before EVERY commit:
go build ./... && go test ./... -race -count=1. The full suite is now green and environment-independent: Docker-dependent tests auto-skip when the daemon is unavailable; orchestrator, autonomy, security, and harvest tests no longer depend on ambient environment or timing. - Conventional commits (
feat:,fix:,docs:,feat!:for breaking). - Releases: tag push
vX.Y.Z⇒ goreleaser builds multi-arch + updates brew. - Never reduce test count or coverage. New loop code targets ≥80% coverage.
- Python side (
src/sin_code_bundle): ruff + pytest, same PR discipline. - Docs: every behavioral change updates docs/ + CHANGELOG.md in the same PR.
- AGENTS.md + ECOSYSTEM.md are kept in sync with the codebase (CI ecosystem-sync.yml enforces registry↔permission↔ECOSYSTEM agreement).
- File-mode policy (
SIN_CODE_FILE_MODE): write paths that would otherwise hard-code0o644go throughcmd/sin-code/internal/filemode.Default(). Operators can dial the mode down (e.g.0o600) for security-sensitive deployments by settingSIN_CODE_FILE_MODEto a valid octal string (0o600or0600form). The knob refuses group/other-write modes that would loosen the0o644baseline. Close-to-source exceptions stay tight:internal/update_manifest.gowrites the install manifest at0o600andinternal/index_store.gocreates the index dir at0o750.
- Binary:
sin-code. Brew formula:sin-code. MCP server name:sin. - The 52+ MCP tool names are a public API — renaming any is a breaking change (major bump + deprecation alias for one minor cycle).
- Tool prefixes for external MCP servers use
server__toolnamespacing (e.g.websearch__search,browser__navigate). - The catalog kinds (
agent,command,skill,hub,mcp,chat,external) and theinternal/orchestrator.ToolChaintype are public API surfaces for downstream tooling and tests. Adding kinds/tools is non-breaking; renaming or removing a kind is a major bump. - The string "SIN-Code-Bundle" may only appear in CHANGELOG history and migration notes — never in code, config, or new docs (mandate M5).
| Tool | Description |
|---|---|
sin_run_loop |
synchronous full-agent-loop delegation (PLAN→ACT→VERIFY→DONE). One call, one verified task. Blocks until completion. Returns {session_id, summary, verified, turns}. |
sin_goal_add |
enqueue a goal for autonomous execution by the daemon (async). Returns immediately with the goal ID. Supports contract criteria (activates stop-gate). |
sin_goal_list |
list goals in the queue, filterable by status (pending/running/verified/failed/exhausted). |
sin_goal_status |
show one goal's progress, attempts, and children (subtasks). |
sin_goal_complete |
mark a goal as verified/done. Maps to autonomy.Queue.Complete(). |
sin_run_loop is the synchronous delegation path; sin_goal_* is the asynchronous autonomy path. Both are consumable by any MCP client (opencode, Claude Code, Codex). The synchronous path runs in-process via
loopbuilder.Build(); the asynchronous path writes to theautonomy.QueueSQLite store for the daemon to pick up.
All bundled skills live under skills/<category>-skills/ and are named
skill-<category>-<descriptive-name>. Examples:
| Category | Directory | Skill name |
|---|---|---|
| Code | code-skills/ |
skill-code-audit, skill-code-build, skill-code-create |
| GitHub | github-skills/ |
skill-github-actions, skill-github-account, skill-github-app |
| Memory | memory-skills/ |
skill-memory-honcho, skill-memory-infisical |
| Process | process-skills/ |
skill-process-goal, skill-process-grill, skill-code-lazy |
| Productivity | productivity-skills/ |
skill-productivity-notion |
| Shop | shop-skills/ |
skill-shop-cj-dropshipping, skill-shop-stripe |
Each skill must contain:
SKILL.mdwith frontmatter (name,description,license,compatibility,metadata)context/,frameworks/,tasks/,templates/directoriesLICENSEfile
Skills ported from external repos (e.g. Infra-SIN-OpenCode-Stack,
DietrichGebert/ponytail → skill-code-lazy) must include
lifecycle: external and sources: in their metadata.
sin-code skill install <name> --agent <target> distributes a bundled
Skill artifact to one of eleven registered agent families. The single
source of truth is cmd/sin-code/internal/skilldist/Targets:
| Target | Format | Install path template (relative to $SIN_CODE_HOME) |
|---|---|---|
claude-code |
dir |
.claude/skills/<skill> |
opencode |
dir |
.config/opencode/skills/<skill> |
gemini |
dir |
.gemini/skills/<skill> |
codex |
rule |
.codex/rules/<skill>.md |
cursor |
rule |
.cursor/rules/<skill>.mdc |
windsurf |
rule |
.windsurf/rules/<skill>.md |
cline |
rule |
.clinerules/<skill>.md |
copilot |
marker |
.github/copilot-instructions.md |
aider |
rule |
.aider/conventions/<skill>.md |
continue |
rule |
.continue/rules/<skill>.md |
zed |
rule |
.zed/rules/<skill>.md |
Marker-fence contract. Every write for rule and marker Formats
goes through ParseMarkers so a subsequent install with the same
(target, skill) pair replaces the previously written block in place:
<!-- SIN-CODE-SKILL-START: <skill> -->
… rendered body …
<!-- SIN-CODE-SKILL-END: <skill> -->
The leading/trailing ASCII prefix SIN-CODE-SKILL is the rg-friendly
anchor. The trailing whitespace before <skill> on the END marker is
visual alignment only — ParseMarkers strips it on lookup, so any
strict matcher outside this package works too.
Public API surface. (Target.Name, Target.DisplayName) is exposed
via the --agent <name> flag. Adding a target is non-breaking; renaming
or removing one is a major bump. The sin-code skill list --json
output schema is also a public API — preferred-format changes go through
the same major-bump policy.
The canonical pattern is skill-<category>-<name> (i.e. the
middle token matches the directory category, e.g.
skill-process-lazy). skill-code-lazy is the v3.18.0
historical exception preserved for activation-keyword stability
(lazy_skill binds to the literal name as it appears in
SKILL.md:frontmatter.name). New bundled skills must follow the
canonical pattern; renaming skill-code-lazy would require a
major bump because the lazy_skill keyword is part of the
external activate-mode contract (issue #176).
Core: discover, execute, map, grasp, scout, harvest, orchestrate,
ibd, poc, sckg, adw, oracle, efm, spec-driven, mcp-install, lsp-config
Agents: chat, sessions (list|show|rm|fork|tree), mcp, goal, daemon,
skill, skills, swarm, superpowers, dox, vane, stack, gh, install,
hub, ledger, summary, autodev, compress, review, eval, trace,
profile, rtk, codegraph, spec, triage, catalog, compile-spec, grill,
subagent, auto-pr, checkpoint, rewind, debt, audit, ceo-audit,
cover, instinct, hooks, assets, evalset, prp, image-graph, status,
fusion, research, permission, tokens, analyse, analyse-image, auto,
background, context, decision, share
Frontend: serve, tui, webui
Lifecycle: memory, todo, notifications, orchestrator-run,
orchestrator-agents, orchestrator-plan, update
Utility: read, write, edit, lsp, plugin, index, security, sbom,
config, self-update, headroom, rules, tool-search
(v3.28.0: 106 subcommands.)
sin-code profile renders the single in-repo source
(docs/agent-profiles/sin-profile.md, ≤80 lines, KISS) into every
per-host-agent mirror file. The render is byte-stable per
(target, source) pair; the verify gate (sin-code profile verify)
refuses to pass whenever any mirror drifts off the source SHA. Adding
a target is non-breaking; renaming or removing one is a major bump.
The single source of truth for the table is
cmd/sin-code/internal/profile/target.go — keep the AGENTS.md row in
sync if the table moves.
| Target | Format | Install path (relative to repo root) |
|---|---|---|
| claude-code | dir | .claude/skills/sin-code/SKILL.md |
| opencode | dir | .config/opencode/skills/sin-code/SKILL.md |
| gemini | dir | .gemini/skills/sin-code/SKILL.md |
| codex | rule | .codex/rules/sin-code.md |
| cursor | rule | .cursor/rules/sin-code.mdc |
| windsurf | rule | .windsurf/rules/sin-code.md |
| cline | rule | .clinerules/sin-code.md |
| copilot | marker | .github/copilot-instructions.md |
| aider | rule | .aider/conventions/sin-code.md |
| continue | rule | .continue/rules/sin-code.md |
| zed | rule | .zed/rules/sin-code.md |
The four marker-fence outputs (rule + marker) wrap the body in
<!-- SIN-CODE-SKILL-START: sin-code --> … <!-- SIN-CODE-SKILL-END: sin-code -->
inside the file. The fence is byte-identical to the one
internal/skilldist uses (issue #169): the two systems share the
same anchor (SIN-CODE-SKILL) so a downstream parser finds both
per-skill bundles and per-profile mirrors with one regex. Profile
renders are idempotent (rerun with unchanged source = byte-identical
output), exactly as skilldist demands.
24 events: session.{start,resume,end}, turn.{start,end},
tool.{pre,post,denied,error}, permission.ask, verify.{pre,pass,fail},
agent.{spawn,complete}, critic.reject, adversary.finding,
governor.block, memory.{write,compact}, commit.{pre,post},
push.pre, task.{complete,abort}, compaction.pre,
goal.{enqueued,started,verified,exhausted} (v3.5.0),
trigger.fired (v3.5.0), skill.{installed,failed} (v3.5.0),
fusion.dispatch (v3.22.0, issue #290).
cmd/sin-code/internal/mcpcompress/ (introduced in v3.19.0) is the
canonical ponytail-tag compressor for sin-code serve --compress-tools.
The five canonical tags control which rules run:
| Tag | Rule | Drops |
|---|---|---|
delete |
DeleteHedges |
pleasantries / hedge adverbs ("safely", "carefully", "thoroughly", "robustly", "elegantly", "gracefully", "seamlessly", "effortlessly", "smoothly", "meticulously") |
stdlib |
StdlibPatterns |
redundant (via stdlib) parentheticals; "Go stdlib" / "Python stdlib" / "Rust stdlib" / "Java stdlib" / "JavaScript stdlib" / "TypeScript stdlib" adjectives |
native |
DropTrimEncouragement |
M6 tail clauses Always prefer over native X / Prefer sin_X over native Y; leading Use sin_X when possible, … encouragements |
yagni |
YagniPatterns |
speculative (experimental) / (TBD) / (TBA) / (reserved) / (may be deprecated …) parentheticals; bare TBD / TBA words |
shrink |
ShrinkExamples |
redundant (e.g. …) / (such as …) parenthetical examples |
Public API contract. The five tag strings are part of the public
configuration surface; renaming any is a major bump. The five Rule
constructor types (RuleDeleteHedges, RuleStdlibPatterns,
RuleDropTrimEncouragement, RuleYagniPatterns, RuleShrinkExamples)
are part of the public Go surface for downstream embeds; renaming is a
major bump. Adding a sixth rule is non-breaking. The sin-code serve --print-stats text-table format is part of the documented telemetry
surface — additions are non-breaking, removals/reorderings are major.
Byte-stability. Every Rule and the Pipeline are byte-stable per
(input, Pipeline) pair. The compressor_test.go golden suite is the
single source of truth — any rule regex / order change must update the
golden expectations in the same commit. This is a prerequisite for the
system-prompt hash metric (issue #2).
Names are immutable. The 52+ MCP tool Name field is public API
(§10). The compressor mutates Description only. CompressSpec
asserts this in TestCompressSpec_NameMutable.
Every intentional shortcut in source code is marked in-line with:
// sin-debt: <ceiling>, upgrade: <trigger>
// sin-debt: <ceiling> # upgrade clause is OPTIONAL but RECOMMENDED
- Recognised comment families:
//,#,--,/* … */,<!-- … -->. - The
upgrade:clause names the trigger to revisit; markers without it are rot-risk and surface in thedebt statsrot-risk table. - Authoring template: prefer the canonical reasons catalogued in
cmd/sin-code/internal/sindept/policy.go(DefaultReasons) and the upgrade triggers inUpgradeTriggers. Free-form text is allowed; pick from the catalogue when possible. - The scanner (
internal/sindept) and CLI (sin-code debt) read this format; the complexity auditor (issue #179) and audit-engine (issue #180) recognise it as an "approved shortcut" tag. - Byte-stable: the same source tree emits byte-identical reports
(
sin-code debt stats) so the four-arm comparator (issue #171) can pin its golden snapshot. - Policy file:
.sin-code/debt-policy.toml(seecmd/sin-code/debt_cmd.doc.md).
Seven phases for the second, programmatic hooking system:
| Phase | Verdict caps | Used by |
|---|---|---|
PreToolUse |
Block allowed | block-no-verify, config-protection, quality-gate |
PostToolUse |
Warn (aggregated) | post-edit-format, post-edit-typecheck, cost-tracker |
Stop |
Warn (aggregated) | suggest-compact |
SessionStart |
Warn (aggregated) | autoactivate-session-start (issue #176) |
SessionEnd |
Warn (aggregated) | (reserved) |
PreCompact |
Warn (aggregated) | suggest-compact (privacy-first) |
UserPrompt |
Warn (aggregated) | autoactivate-user-prompt (issue #176) |
Auto-activation hooks (v3.19.0, issue #176) wire through
Activator.Register(reg) and emit their rule body via the Decision.Message
field, returning Warn so the runner's aggregation surfaces it. Off by
default — privacy-first activation via --activate or
.sin-code/autoactivate.toml. See
cmd/sin-code/internal/hooklife/autoactivate/activator.doc.md.
- Read sections 3 (mandates) and 8 (roadmap) before any edit.
- Use the repo's own tools on itself when available (
sin-code servedogfooding). - One C-gap or one issue per PR. No drive-by refactors.
- If you cannot satisfy a mandate, STOP and report — do not work around it.
- WebUI-v2 is OUT OF SCOPE for this repo's agent loop. Edits to
/Users/jeremy/dev/sin-code-web-ui-v2belong to that repo's local agent.
The Go binary writes SQLite DBs to user-config directories by default (issue #265 / #62). Workspace isolation is keyed by a 12-char sha256 of the workspace's absolute path so two projects never share a row.
| Purpose | Path (relative to os.UserConfigDir()/sin-code/) |
Module | Issue |
|---|---|---|---|
| Lessons log | workspaces/<sha256-prefix12(abs(ws))>/lessons.db |
internal/tui/dbhome.go + agent_runner.go |
#265 |
| Session store | workspaces/<sha256-prefix12(abs(ws))>/sessions.db |
internal/tui/dbhome.go + agent_runner.go |
#265 |
| Code index | <root>/.sin-code/index.bin (per-project, intentional) |
internal/index_store.go |
n/a |
internal/session/store.go:DefaultPath() and
internal/lessons/store.go:DefaultPath() keep their
~/.local/share/sin-code/ shape for direct CLI use (sin-code sessions
without a workspace). The TUI agent runner resolves the home through
Config.DBHome (overridable in tests; default = os.UserConfigDir()).
These files are NOT inside the workspace tree and so cannot be
accidentally git add-ed. The legacy .gitignore rule (lines 64–65)
remains as a defence-in-depth for users who keep a pre-migration
working tree. Migration to add automatic move-from-old-path is
out of scope for issue #265.
SIN-Code ships a first-party eval pipeline + OpenTelemetry tracing that lets agents produce golden datasets, run them as CI gates, and inspect trajectories visually (Langfuse / Jaeger / Arize Phoenix).
| Path | Purpose |
|---|---|
cmd/sin-code/internal/trace/provider.go |
OTel TracerProvider bootstrap (stdout / OTLP-HTTP / noop) |
cmd/sin-code/internal/trace/hook_listener.go |
Decorator wrapper around *hooks.Engine that emits one span per Fire() |
cmd/sin-code/internal/dataset/dataset.go |
Pure-stdlib Golden Dataset JSON parser + validator |
cmd/sin-code/internal/dataset/runner.go |
Executes TestCases against the existing agentloop.Loop |
cmd/sin-code/internal/eval/judge.go |
LLM-as-a-Judge via internal/llm.Client |
cmd/sin-code/internal/eval/metrics.go |
Summary aggregation + JSON envelope for CI |
cmd/sin-code/internal/evalharness/arms.go |
v3.18.0 four-arm constructors (baseline / terse / lazy / <skill>) for issue #171 |
cmd/sin-code/internal/evalharness/comparator.go |
v3.18.0 Compare runner producing per-arm aggregates |
cmd/sin-code/internal/evalharness/prices.go |
v3.18.0 self-pricing price book (USD/1k tokens per model) |
cmd/sin-code/internal/evalharness/snapshot.go |
v3.18.0 deterministic snapshot round-trip (caveman evals/README.md §3) |
cmd/sin-code/eval_cmd.go |
sin-code eval run + eval compare + eval snapshot + eval diff (issue #171) |
cmd/sin-code/internal/evalharness/scorer.go |
Scorers: exact, contains, success, LLM-judge, composite, CompileAndRun |
cmd/sin-code/internal/evalharness/runner_extras.go |
Compile-and-run helpers (code extraction, sandboxed compile/run) |
cmd/sin-code/trace_cmd.go |
sin-code trace doctor — exporter-only sanity check |
evals/critical.json |
Example Golden Dataset (3 cases, no LLM needed) |
evals/three-arm-example.json |
v3.18.0 four-arm bench, 3 cases (issue #171) |
# Run a Golden Dataset (CI format)
sin-code eval run --dataset evals/critical.json \
--min-pass-rate 0.95 --json
# With tracing exported to OTLP (Langfuse / Jaeger / Phoenix)
sin-code eval run --dataset evals/critical.json \
--trace --trace-exporter otlp \
--trace-endpoint langfuse.local:4318
# LLM-as-a-Judge pass
sin-code eval run --dataset evals/critical.json \
--judge-model gpt-4o --judge-endpoint https://api.openai.com/v1
# Four-arm comparator (issue #171) — baseline / terse / lazy_skill / <user-skill>
sin-code eval run --dataset evals/three-arm-example.json \
--arm baseline,terse,lazy_skill,skill-code-create
sin-code eval compare --dataset evals/three-arm-example.json
sin-code eval snapshot --dataset evals/three-arm-example.json --out /tmp/snap.json
sin-code eval diff --snapshot /tmp/snap-base.json --snapshot-b /tmp/snap-head.json
# Compile-and-run scorer (ponytail correctness.js analog)
sin-code eval run --dataset evals/coding.json \
--scorer compile-and-run --language python \
--self-check "assert fizzbuzz(15) == 'FizzBuzz'"
# YAGNI mode: trivial one-liners accepted after compile-only
sin-code eval run --dataset evals/trivial.json \
--scorer compile-and-run --language python --skip-test
# Sanity-check the OTel exporter setup without a full eval
sin-code trace doctor --exporter stdout --emit-sample-spanThe comparator runs the same dataset against the four arms identified in the issue body:
| Arm | Reserved ID | SystemPrompt |
|---|---|---|
| baseline | __baseline__ |
empty (legacy single-arm behaviour) |
| terse | __terse__ |
"Answer concisely." |
| lazy skill | __lazy_skill__ |
terse-prefixed body of skill-code-lazy (issue #178) |
| user skill | <user-supplied> |
terse-prefixed body of the bundled skill named by --skill |
The honest delta between any candidate arm and the terse
arm is what reviewers grade on. Comparing a skill directly to the
baseline conflates the skill's content with the generic "be
terse" instruction; the four-arm harness isolates them.
The output matrix mirrors ponytail's
benchmarks/README.md:34-58:
| column | meaning |
|---|---|
pass_rate |
Passed / TotalCases |
med_LOC |
median lines of output across cases |
med_latency_ms |
median wall-clock per (case, arm) |
med_usd |
median USD cost (using prices.go price book) |
med_tokens |
median prompt + completion tokens |
med_score |
median Result.Score per arm |
Snapshots are deterministic JSON: the comparator sorts every arm, median-recomputes every cell, and writes the same bytes for the same input on every CI run (caveman evals/README.md §3 promise: "snapshot committed to git so CI runs are deterministic and free").
- M2 (single static binary, CGO_ENABLED=0): pure-Go OTel SDK at
go.opentelemetry.io/otel/sdk@v1.24.0plusstdouttrace+otlptracehttp. No CGO. - M4 (permission engine): eval/trace rules registered in
cmd/sin-code/internal/permission_defaults.go(eval__listallow,eval__runask,trace__doctorallow). - M5 (module path): the import path is
github.com/OpenSIN-Code/SIN-Code/cmd/sin-code/...everywhere. NoSIN-Code-Bundlereferences. - M7 (race-free): every new test passes
go test -race -count=1 ./cmd/sin-code/internal/{trace,dataset,eval,evalharness}/....
cmd/sin-code/internal/trace/provider.doc.md— exporter / sampler configuration surface.cmd/sin-code/internal/trace/hook_listener.doc.md— list of divergences between the issue's reference code and the actual hook API (the issue describes ahooks.Manager.On(...)API that does not exist; we use the decorator-on-Engine.Firepattern that matches the realhooks.go:108-143interface).cmd/sin-code/internal/dataset/dataset.doc.md— JSON schema contract.cmd/sin-code/internal/dataset/runner.doc.md— agent-loop API divergence notes (realLoop.Run(ctx, *session.Session, string)vs referenceLoop.Run(ctx, sessID, prompt, RunOptions)).cmd/sin-code/internal/eval/eval.doc.md— judge prompt + JSON contract;JudgeResultschema.cmd/sin-code/internal/evalharness/comparator.doc.md— four-armComparerunner, arm constructors, snapshot round-trip (issue #171).cmd/sin-code/internal/evalharness/snapshot.doc.md— deterministic matrix + diff (issue #171).cmd/sin-code/internal/evalharness/scorer.doc.md— scorer interface and built-in scorers (includingCompileAndRun).cmd/sin-code/internal/evalharness/runner_extras.doc.md— code-block extraction, per-language compile, and sandboxed self-check execution.docs/eval.md— user-facing guide forsin-code eval.evals/README.md— Golden Dataset catalog and schema quick reference..github/workflows/eval-n8n.yml— n8n-delegated CI for datasets (M1).