sid-harness 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. sid_harness-0.3.0/PKG-INFO +229 -0
  2. sid_harness-0.3.0/README.md +209 -0
  3. sid_harness-0.3.0/editors/README.md +46 -0
  4. sid_harness-0.3.0/editors/vscode/README.md +32 -0
  5. sid_harness-0.3.0/editors/vscode/extension.js +395 -0
  6. sid_harness-0.3.0/editors/vscode/package.json +120 -0
  7. sid_harness-0.3.0/pyproject.toml +42 -0
  8. sid_harness-0.3.0/setup.cfg +4 -0
  9. sid_harness-0.3.0/sid_harness/__init__.py +13 -0
  10. sid_harness-0.3.0/sid_harness/__main__.py +4 -0
  11. sid_harness-0.3.0/sid_harness/_native.py +1639 -0
  12. sid_harness-0.3.0/sid_harness/brave_proof.py +246 -0
  13. sid_harness-0.3.0/sid_harness/bridge.py +851 -0
  14. sid_harness-0.3.0/sid_harness/cli.py +937 -0
  15. sid_harness-0.3.0/sid_harness/client.py +161 -0
  16. sid_harness-0.3.0/sid_harness/companion.py +151 -0
  17. sid_harness-0.3.0/sid_harness/config.py +68 -0
  18. sid_harness-0.3.0/sid_harness/context/__init__.py +40 -0
  19. sid_harness-0.3.0/sid_harness/context/index.py +267 -0
  20. sid_harness-0.3.0/sid_harness/context/retrieval.py +74 -0
  21. sid_harness-0.3.0/sid_harness/editor.py +231 -0
  22. sid_harness-0.3.0/sid_harness/gateway.py +106 -0
  23. sid_harness-0.3.0/sid_harness/git_write.py +598 -0
  24. sid_harness-0.3.0/sid_harness/local_workspace.py +421 -0
  25. sid_harness-0.3.0/sid_harness/loop.py +394 -0
  26. sid_harness-0.3.0/sid_harness/lsp.py +598 -0
  27. sid_harness-0.3.0/sid_harness/policy/__init__.py +44 -0
  28. sid_harness-0.3.0/sid_harness/policy/repo_policy.py +626 -0
  29. sid_harness-0.3.0/sid_harness/receipt.py +142 -0
  30. sid_harness-0.3.0/sid_harness/runner.py +468 -0
  31. sid_harness-0.3.0/sid_harness/selftest.py +149 -0
  32. sid_harness-0.3.0/sid_harness/session/__init__.py +33 -0
  33. sid_harness-0.3.0/sid_harness/session/bounds.py +140 -0
  34. sid_harness-0.3.0/sid_harness/session/diff_gate.py +93 -0
  35. sid_harness-0.3.0/sid_harness/session/session.py +427 -0
  36. sid_harness-0.3.0/sid_harness/session/store.py +88 -0
  37. sid_harness-0.3.0/sid_harness/tools/__init__.py +52 -0
  38. sid_harness-0.3.0/sid_harness/tools/mcp_client.py +285 -0
  39. sid_harness-0.3.0/sid_harness/tools/plan.py +138 -0
  40. sid_harness-0.3.0/sid_harness/tools/registry.py +159 -0
  41. sid_harness-0.3.0/sid_harness/tools/skills.py +185 -0
  42. sid_harness-0.3.0/sid_harness/tools/subagents.py +112 -0
  43. sid_harness-0.3.0/sid_harness/tui.py +96 -0
  44. sid_harness-0.3.0/sid_harness/workspace.py +107 -0
  45. sid_harness-0.3.0/sid_harness.egg-info/PKG-INFO +229 -0
  46. sid_harness-0.3.0/sid_harness.egg-info/SOURCES.txt +67 -0
  47. sid_harness-0.3.0/sid_harness.egg-info/dependency_links.txt +1 -0
  48. sid_harness-0.3.0/sid_harness.egg-info/entry_points.txt +2 -0
  49. sid_harness-0.3.0/sid_harness.egg-info/requires.txt +5 -0
  50. sid_harness-0.3.0/sid_harness.egg-info/top_level.txt +1 -0
  51. sid_harness-0.3.0/tests/test_bridge.py +70 -0
  52. sid_harness-0.3.0/tests/test_cli.py +86 -0
  53. sid_harness-0.3.0/tests/test_client.py +80 -0
  54. sid_harness-0.3.0/tests/test_editor_integration.py +393 -0
  55. sid_harness-0.3.0/tests/test_git_write.py +438 -0
  56. sid_harness-0.3.0/tests/test_live_smoke.py +45 -0
  57. sid_harness-0.3.0/tests/test_local_fs.py +412 -0
  58. sid_harness-0.3.0/tests/test_native_parity.py +90 -0
  59. sid_harness-0.3.0/tests/test_project_rules_wiring.py +183 -0
  60. sid_harness-0.3.0/tests/test_repo_context.py +180 -0
  61. sid_harness-0.3.0/tests/test_repo_policy.py +371 -0
  62. sid_harness-0.3.0/tests/test_selftest.py +27 -0
  63. sid_harness-0.3.0/tests/test_session.py +323 -0
  64. sid_harness-0.3.0/tests/test_shell_tool_vendored.py +162 -0
  65. sid_harness-0.3.0/tests/test_test_execution.py +217 -0
  66. sid_harness-0.3.0/tests/test_tools.py +569 -0
  67. sid_harness-0.3.0/tests/test_wiring.py +257 -0
  68. sid_harness-0.3.0/tests/test_workspace.py +51 -0
  69. sid_harness-0.3.0/tests/test_write_bridge.py +408 -0
@@ -0,0 +1,229 @@
1
+ Metadata-Version: 2.4
2
+ Name: sid-harness
3
+ Version: 0.3.0
4
+ Summary: SID first-party local coding harness (CLI/TUI) — drives the SID native loop against SID's OpenAI-compatible /v1.
5
+ License: Proprietary
6
+ Project-URL: Homepage, https://superintelligencedog.com
7
+ Project-URL: Documentation, https://superintelligencedog.com/docs
8
+ Project-URL: Source, https://superintelligencedog.com
9
+ Keywords: sid,coding-agent,cli,harness
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Environment :: Console
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ Provides-Extra: publish
17
+ Requires-Dist: build>=1.2; extra == "publish"
18
+ Requires-Dist: twine>=6.0; extra == "publish"
19
+ Requires-Dist: sigstore>=3.0; extra == "publish"
20
+
21
+ # sid-harness — SID first-party local coding client (v1)
22
+
23
+ A small CLI/TUI client that runs a coding task through **SID's own native
24
+ loop** against SID's OpenAI-compatible `/v1`. Running a model on your desktop no
25
+ longer requires a third-party coding harness: SID *is* the harness.
26
+
27
+ - **One engine.** The loop, its four-tool contract, and its path denylist are
28
+ the gateway's `app/native_agent.py`, vendored **verbatim** into the package as
29
+ `sid_harness/_native.py` — one loop, mirrored, and kept byte-identical by a
30
+ parity test. Never reimplemented.
31
+ - **One backend.** SID routes, meters, and caps every call under **your** key.
32
+ No aggregator, no other provider SDK.
33
+ - **One command.**
34
+
35
+ ```bash
36
+ sid setup # verify your key via /v1/me, save it, pick a dir
37
+ sid run --task "Fix the off-by-one in add()." --dir ./my-project
38
+ ```
39
+
40
+ Output: the workspace selection, the model + diff, the final response, and a
41
+ **run receipt** written to `<dir>/.sid/runs/<run_id>.json` (override with
42
+ `--receipt`). The CLI prints the receipt as a `file://` link.
43
+
44
+ ## Install / run
45
+
46
+ No third-party dependencies (stdlib only), and no monorepo checkout — the
47
+ package is self-contained. Either:
48
+
49
+ ```bash
50
+ pipx run --spec infra/sid-harness sid run --task "..." --dir ./proj # install + run
51
+ pipx install infra/sid-harness # or install the `sid` console script
52
+ pip install infra/sid-harness # plain pip works too
53
+ # or run straight from the tree:
54
+ python -m sid_harness run --task "..." --dir ./proj
55
+ ```
56
+
57
+ The loop ships in the package, so nothing under `infra/sid-gateway` is needed at
58
+ runtime. The one optional seam that does use the gateway is `--context`
59
+ (repo-scale retrieval over `app.rag`); it is discovered when a gateway checkout
60
+ is present and overridable with `SID_HARNESS_GATEWAY_PATH`. Every other command
61
+ works with no checkout.
62
+
63
+ ## First run
64
+
65
+ `sid setup` verifies the key against `GET /v1/me`, then writes
66
+ `~/.sid/config.json` (owner-only) with the key, base URL, and your default
67
+ project directory. Later commands read that file when the env var or flag is
68
+ absent, so `sid run --task "..."` works with no `export` and no `--dir`.
69
+ Override the location with `SID_CONFIG_PATH`.
70
+
71
+ ```bash
72
+ sid setup --dir ./my-project # non-interactive: key from SID_API_KEY
73
+ sid setup --api-key "<your-key>" --dir . # or pass it explicitly
74
+ ```
75
+
76
+ Maintainers publish the signed wheel with `scripts/publish_sid_harness.sh`
77
+ (Sigstore attestations via `twine upload --attestations`). Public install
78
+ commands are wired into the landing/docs pages only after the PyPI probe
79
+ returns 200; the commands above remain the source-tree install until then.
80
+
81
+ ## Commands
82
+
83
+ ```bash
84
+ sid run --task "<goal>" --dir <path> [--model auto] [--verify] [--write] [--json]
85
+ sid run ... --git-write [--git-branch NAME] [--git-message MSG] [--no-pr] # opt-in branch/commit/PR (SUB-95)
86
+ sid run ... --context [--context-k N] # prepend repo-scale retrieved context (SUB-55)
87
+ sid run ... --mcp "<server cmd>" # expose an MCP server's tools (SUB-56, repeatable)
88
+ sid run ... --bounds-config <file> # override loop bounds (SUB-58)
89
+ sid run ... --test-cmd "python -m pytest -q" # run the approved tests locally (SUB-80)
90
+ sid tui --dir <path> # interactive terminal loop, same engine
91
+ sid status --dir <path> [--diff] # local git/worktree status (read-only)
92
+ sid session start|resume|replay # durable local sessions (SUB-58)
93
+ sid tools [--mcp "<server cmd>"] [--json] # list the loop's tool contract
94
+ sid policy --dir <path> [--json] # show the platform worktree/gate policy
95
+ sid lsp [--dir <path>] # LSP: compiler diagnostics -> loop (SUB-96)
96
+ sid apply --dir <path> --receipt <p> [--approve] # apply an approved run receipt
97
+ sid editor install [--target-dir <p>] [--force] # one-command VS Code install
98
+ sid selftest [--receipt <path>] # one loop turn against a local stub endpoint
99
+ ```
100
+
101
+ Common options: `--base-url` (env `SID_BASE_URL`, default
102
+ `https://superintelligencedog.com/v1`), `--api-key` (env `SID_API_KEY`),
103
+ `--routing-profile` (default `agent`), `--criteria` / `--out-of-scope`
104
+ (repeatable), `--max-tokens`, `--reasoning-effort`, `--receipt`, `--quiet`.
105
+
106
+ `--verify` reviews the produced diff through the gateway's existing
107
+ `POST /v1/verify/patch` — the harness does not carry a second verify path.
108
+
109
+ `--write` applies the loop's changed files to the **real working tree**
110
+ (SUB-54). It is off by default (read-only). Deletions are never applied. Inside
111
+ the platform repo, a source write from the MAIN checkout is refused by the repo
112
+ policy (SUB-57), which delegates to the platform's own Gate 31.
113
+
114
+ `--git-write` is the explicit opt-in that finishes the coder loop (SUB-95):
115
+ create a branch (`--git-branch`, default `sid/<run_id>`), commit **only** the
116
+ files that `--write` applied, push that branch, and open a pull request with
117
+ `gh` (`--git-base`, `--no-pr` to skip). Each step asks for its own approval;
118
+ `--approve` pre-approves the steps for non-interactive use, and without a
119
+ terminal or `--approve` every step fails closed. The path hard-refuses
120
+ `main`/`master` (including sub-refs), never force-pushes, and the receipt's
121
+ `git_write` block names the branch, commit SHA, and PR URL. Without
122
+ `--git-write` the harness remains read-only and never commits or pushes.
123
+
124
+ `--test-cmd` is the human-approved test command (SUB-80). The CLI splits it into
125
+ an **argv list** and executes it with `subprocess` in the `--dir` root —
126
+ never through a shell. The runner must be allowlisted (`python -m pytest`,
127
+ `pytest`, `python -m unittest`, `npm test`, `yarn/pnpm test`, `cargo test`,
128
+ `go test`), argv may not point outside the workspace, and the run is bounded
129
+ (timeout + output capture). The receipt records `tests_executed`, the test
130
+ backend, exit code, and pass/fail. Nothing is committed or pushed.
131
+
132
+ ## What v1 is (and is not)
133
+
134
+ **Is:** a bounded workspace loaded from `--dir`, the existing native loop, SID as
135
+ the only model backend, and a written run receipt. As of SUB-54 the workspace is
136
+ a **local driver**: real file read/write (`--write`), real `git` **status/diff**
137
+ (read-only — `sid status`), worktree awareness (linked worktree vs main
138
+ checkout), and a `.gitignore` filter layered on the shared `native_agent._safe_path`
139
+ secret/VCS/dependency denylist. The receipt records the git block and the files
140
+ written.
141
+
142
+ **Also wired (SUB-55/56/57/58):** repo-scale **context** (`--context` indexes the
143
+ whole tree and prepends sanitized, data-boundaried retrieval — reuses the
144
+ gateway's `app.rag`), the **tool ecosystem** (`sid_harness.tools`: a registry
145
+ over the one loop, an MCP stdio/HTTP client, a skills loader, a plan/todo gate,
146
+ subagent fan-out — reachable via `sid run --mcp` and `sid tools`), **durable
147
+ sessions** (`sid session`), configurable **bounds** (`--bounds-config`), and
148
+ **repo policy** (a write from the platform MAIN checkout is refused).
149
+
150
+ **Tests (SUB-80):** with `--test-cmd`, the loop's `run_approved_tests` tool and
151
+ the final verification step execute the approved argv locally against the
152
+ workspace root; the receipt records backend/exit/passed and
153
+ `tests_executed: true`. Without an approved command the receipt stays
154
+ `tests_executed: false` — never a claim. By default the harness **never commits
155
+ and never pushes**; only the explicit `--git-write` opt-in branches, commits,
156
+ pushes a feature branch, and opens a PR (SUB-95), and it never touches
157
+ main/master.
158
+
159
+ ## Localhost bridge (for the web Studio)
160
+
161
+ The web Studio runs in a browser and cannot read your disk (Brave also blocks the
162
+ File System Access API by default). Claude Code / Codex / OpenCode avoid this by
163
+ running a local process with filesystem tools. The **desktop companion** is that
164
+ local process for the Studio, and it removes the old URL/token paste:
165
+
166
+ ```bash
167
+ # one click: starts the loopback bridge, then opens the Studio already paired
168
+ python -m sid_harness companion --dir C:\Users\jerry\JB # read-only
169
+ python -m sid_harness companion --dir C:\Users\jerry\JB --write # write available
170
+ # the Studio shows "Enable write access" until the user explicitly grants it
171
+ ```
172
+
173
+ The companion binds **127.0.0.1 only**, exchanges a per-launch pairing code (in
174
+ the URL fragment, never a server log) for the bearer token, and accepts browser
175
+ requests only from the SID origins. The workspace is fixed to `--dir`. The loop
176
+ reads the **real tree on demand** (`list_files` / `read_file`), not a snapshot.
177
+
178
+ Write mode is opt-in twice: `--write` makes it *available*, and the user then
179
+ clicks **Enable write access** in the Studio (a per-session grant). Applying a
180
+ change requires the exact proposal the bridge generated and the user reviewed:
181
+ the digest is bound, every path goes through the shared secret/VCS denylist plus
182
+ an atomic all-or-nothing write, and a receipt lands in
183
+ `~/.sid/bridge/receipts/apply_*.json`. Endpoints: `GET /health`; `POST /pair`,
184
+ `/grant-write`, `/revoke-write`, `/run` `{task, model?, test_argv?}` (with
185
+ `X-SID-Api-Key`), and `/apply` `{proposal_id, digest}`. The browser cannot choose
186
+ the model backend or run tests without the write grant.
187
+
188
+ Installers (Windows/macOS/Linux, private venv + login autostart) and the
189
+ sign/verify chain live in `install/`. `install/prove_brave_apply.py` drives the
190
+ whole pair → grant → run → review → apply path in real Brave headless and checks
191
+ the disk plus the receipt.
192
+
193
+ The Studio ships the client half: a **Local bridge** control in the composer
194
+ shows the paired workspace and read-only/write state; `pairFromLocation()` takes
195
+ the companion's one-click code from the URL fragment, a Chat turn routes to
196
+ `POST {url}/run`, and the receipt (model, tools, tests, diff, changed, final
197
+ response) plus the real workspace preview render in place. **Enable write
198
+ access** posts the explicit grant, and **Apply** posts the reviewed proposal id
199
+ and digest. It fails closed and names the reason when the bridge is unreachable
200
+ or the pairing is stale — there is no silent fallback to the remote gateway. The harness CLI (`sid run` /
201
+ `sid tui`) remains the full-parity product (including `--write`); the Studio's
202
+ bridge path is read-only.
203
+
204
+ ## Editor integration + LSP diagnostics (SUB-96)
205
+
206
+ The VS Code extension under `editors/vscode` is a thin client over this same
207
+ engine: **SID: Open Coding Session** runs `sid session start`, **Show Proposed
208
+ Diff** opens the receipt's diff, **Approve and Apply** calls `sid apply` (the
209
+ same `LocalWorkspace` + repo-policy write path), and **Attach Selection as
210
+ Context** prepends the editor selection to the next task.
211
+
212
+ ```bash
213
+ python -m sid_harness editor install # one command; reload VS Code
214
+ ```
215
+
216
+ `sid lsp` is the diagnostics server. It publishes real Python compiler
217
+ diagnostics (`compile`) on open/change/save and accepts diagnostics forwarded
218
+ from VS Code's other language servers through `sid/diagnostics`. The merged feed
219
+ is written to `<workspace>/.sid/diagnostics.json`; `sid run` and `sid session`
220
+ prepend a data-boundaried `COMPILER DIAGNOSTICS` block to the task and record
221
+ `diagnostics: {count, sources, path}` on the receipt. `--no-diagnostics` opts
222
+ out for one run. No model call, no tool contract, and no write path are added by
223
+ the LSP — it is a diagnostic source for the one loop.
224
+
225
+ ## Scope guards
226
+ - SID stays the only model backend (no aggregator).
227
+ - No new pricing surface; your plan's unit is unchanged.
228
+ - No reimplemented verify/scan — the harness calls the gateway's.
229
+ - No vendor/model name is hardcoded into a rule, script default, or gate.
@@ -0,0 +1,209 @@
1
+ # sid-harness — SID first-party local coding client (v1)
2
+
3
+ A small CLI/TUI client that runs a coding task through **SID's own native
4
+ loop** against SID's OpenAI-compatible `/v1`. Running a model on your desktop no
5
+ longer requires a third-party coding harness: SID *is* the harness.
6
+
7
+ - **One engine.** The loop, its four-tool contract, and its path denylist are
8
+ the gateway's `app/native_agent.py`, vendored **verbatim** into the package as
9
+ `sid_harness/_native.py` — one loop, mirrored, and kept byte-identical by a
10
+ parity test. Never reimplemented.
11
+ - **One backend.** SID routes, meters, and caps every call under **your** key.
12
+ No aggregator, no other provider SDK.
13
+ - **One command.**
14
+
15
+ ```bash
16
+ sid setup # verify your key via /v1/me, save it, pick a dir
17
+ sid run --task "Fix the off-by-one in add()." --dir ./my-project
18
+ ```
19
+
20
+ Output: the workspace selection, the model + diff, the final response, and a
21
+ **run receipt** written to `<dir>/.sid/runs/<run_id>.json` (override with
22
+ `--receipt`). The CLI prints the receipt as a `file://` link.
23
+
24
+ ## Install / run
25
+
26
+ No third-party dependencies (stdlib only), and no monorepo checkout — the
27
+ package is self-contained. Either:
28
+
29
+ ```bash
30
+ pipx run --spec infra/sid-harness sid run --task "..." --dir ./proj # install + run
31
+ pipx install infra/sid-harness # or install the `sid` console script
32
+ pip install infra/sid-harness # plain pip works too
33
+ # or run straight from the tree:
34
+ python -m sid_harness run --task "..." --dir ./proj
35
+ ```
36
+
37
+ The loop ships in the package, so nothing under `infra/sid-gateway` is needed at
38
+ runtime. The one optional seam that does use the gateway is `--context`
39
+ (repo-scale retrieval over `app.rag`); it is discovered when a gateway checkout
40
+ is present and overridable with `SID_HARNESS_GATEWAY_PATH`. Every other command
41
+ works with no checkout.
42
+
43
+ ## First run
44
+
45
+ `sid setup` verifies the key against `GET /v1/me`, then writes
46
+ `~/.sid/config.json` (owner-only) with the key, base URL, and your default
47
+ project directory. Later commands read that file when the env var or flag is
48
+ absent, so `sid run --task "..."` works with no `export` and no `--dir`.
49
+ Override the location with `SID_CONFIG_PATH`.
50
+
51
+ ```bash
52
+ sid setup --dir ./my-project # non-interactive: key from SID_API_KEY
53
+ sid setup --api-key "<your-key>" --dir . # or pass it explicitly
54
+ ```
55
+
56
+ Maintainers publish the signed wheel with `scripts/publish_sid_harness.sh`
57
+ (Sigstore attestations via `twine upload --attestations`). Public install
58
+ commands are wired into the landing/docs pages only after the PyPI probe
59
+ returns 200; the commands above remain the source-tree install until then.
60
+
61
+ ## Commands
62
+
63
+ ```bash
64
+ sid run --task "<goal>" --dir <path> [--model auto] [--verify] [--write] [--json]
65
+ sid run ... --git-write [--git-branch NAME] [--git-message MSG] [--no-pr] # opt-in branch/commit/PR (SUB-95)
66
+ sid run ... --context [--context-k N] # prepend repo-scale retrieved context (SUB-55)
67
+ sid run ... --mcp "<server cmd>" # expose an MCP server's tools (SUB-56, repeatable)
68
+ sid run ... --bounds-config <file> # override loop bounds (SUB-58)
69
+ sid run ... --test-cmd "python -m pytest -q" # run the approved tests locally (SUB-80)
70
+ sid tui --dir <path> # interactive terminal loop, same engine
71
+ sid status --dir <path> [--diff] # local git/worktree status (read-only)
72
+ sid session start|resume|replay # durable local sessions (SUB-58)
73
+ sid tools [--mcp "<server cmd>"] [--json] # list the loop's tool contract
74
+ sid policy --dir <path> [--json] # show the platform worktree/gate policy
75
+ sid lsp [--dir <path>] # LSP: compiler diagnostics -> loop (SUB-96)
76
+ sid apply --dir <path> --receipt <p> [--approve] # apply an approved run receipt
77
+ sid editor install [--target-dir <p>] [--force] # one-command VS Code install
78
+ sid selftest [--receipt <path>] # one loop turn against a local stub endpoint
79
+ ```
80
+
81
+ Common options: `--base-url` (env `SID_BASE_URL`, default
82
+ `https://superintelligencedog.com/v1`), `--api-key` (env `SID_API_KEY`),
83
+ `--routing-profile` (default `agent`), `--criteria` / `--out-of-scope`
84
+ (repeatable), `--max-tokens`, `--reasoning-effort`, `--receipt`, `--quiet`.
85
+
86
+ `--verify` reviews the produced diff through the gateway's existing
87
+ `POST /v1/verify/patch` — the harness does not carry a second verify path.
88
+
89
+ `--write` applies the loop's changed files to the **real working tree**
90
+ (SUB-54). It is off by default (read-only). Deletions are never applied. Inside
91
+ the platform repo, a source write from the MAIN checkout is refused by the repo
92
+ policy (SUB-57), which delegates to the platform's own Gate 31.
93
+
94
+ `--git-write` is the explicit opt-in that finishes the coder loop (SUB-95):
95
+ create a branch (`--git-branch`, default `sid/<run_id>`), commit **only** the
96
+ files that `--write` applied, push that branch, and open a pull request with
97
+ `gh` (`--git-base`, `--no-pr` to skip). Each step asks for its own approval;
98
+ `--approve` pre-approves the steps for non-interactive use, and without a
99
+ terminal or `--approve` every step fails closed. The path hard-refuses
100
+ `main`/`master` (including sub-refs), never force-pushes, and the receipt's
101
+ `git_write` block names the branch, commit SHA, and PR URL. Without
102
+ `--git-write` the harness remains read-only and never commits or pushes.
103
+
104
+ `--test-cmd` is the human-approved test command (SUB-80). The CLI splits it into
105
+ an **argv list** and executes it with `subprocess` in the `--dir` root —
106
+ never through a shell. The runner must be allowlisted (`python -m pytest`,
107
+ `pytest`, `python -m unittest`, `npm test`, `yarn/pnpm test`, `cargo test`,
108
+ `go test`), argv may not point outside the workspace, and the run is bounded
109
+ (timeout + output capture). The receipt records `tests_executed`, the test
110
+ backend, exit code, and pass/fail. Nothing is committed or pushed.
111
+
112
+ ## What v1 is (and is not)
113
+
114
+ **Is:** a bounded workspace loaded from `--dir`, the existing native loop, SID as
115
+ the only model backend, and a written run receipt. As of SUB-54 the workspace is
116
+ a **local driver**: real file read/write (`--write`), real `git` **status/diff**
117
+ (read-only — `sid status`), worktree awareness (linked worktree vs main
118
+ checkout), and a `.gitignore` filter layered on the shared `native_agent._safe_path`
119
+ secret/VCS/dependency denylist. The receipt records the git block and the files
120
+ written.
121
+
122
+ **Also wired (SUB-55/56/57/58):** repo-scale **context** (`--context` indexes the
123
+ whole tree and prepends sanitized, data-boundaried retrieval — reuses the
124
+ gateway's `app.rag`), the **tool ecosystem** (`sid_harness.tools`: a registry
125
+ over the one loop, an MCP stdio/HTTP client, a skills loader, a plan/todo gate,
126
+ subagent fan-out — reachable via `sid run --mcp` and `sid tools`), **durable
127
+ sessions** (`sid session`), configurable **bounds** (`--bounds-config`), and
128
+ **repo policy** (a write from the platform MAIN checkout is refused).
129
+
130
+ **Tests (SUB-80):** with `--test-cmd`, the loop's `run_approved_tests` tool and
131
+ the final verification step execute the approved argv locally against the
132
+ workspace root; the receipt records backend/exit/passed and
133
+ `tests_executed: true`. Without an approved command the receipt stays
134
+ `tests_executed: false` — never a claim. By default the harness **never commits
135
+ and never pushes**; only the explicit `--git-write` opt-in branches, commits,
136
+ pushes a feature branch, and opens a PR (SUB-95), and it never touches
137
+ main/master.
138
+
139
+ ## Localhost bridge (for the web Studio)
140
+
141
+ The web Studio runs in a browser and cannot read your disk (Brave also blocks the
142
+ File System Access API by default). Claude Code / Codex / OpenCode avoid this by
143
+ running a local process with filesystem tools. The **desktop companion** is that
144
+ local process for the Studio, and it removes the old URL/token paste:
145
+
146
+ ```bash
147
+ # one click: starts the loopback bridge, then opens the Studio already paired
148
+ python -m sid_harness companion --dir C:\Users\jerry\JB # read-only
149
+ python -m sid_harness companion --dir C:\Users\jerry\JB --write # write available
150
+ # the Studio shows "Enable write access" until the user explicitly grants it
151
+ ```
152
+
153
+ The companion binds **127.0.0.1 only**, exchanges a per-launch pairing code (in
154
+ the URL fragment, never a server log) for the bearer token, and accepts browser
155
+ requests only from the SID origins. The workspace is fixed to `--dir`. The loop
156
+ reads the **real tree on demand** (`list_files` / `read_file`), not a snapshot.
157
+
158
+ Write mode is opt-in twice: `--write` makes it *available*, and the user then
159
+ clicks **Enable write access** in the Studio (a per-session grant). Applying a
160
+ change requires the exact proposal the bridge generated and the user reviewed:
161
+ the digest is bound, every path goes through the shared secret/VCS denylist plus
162
+ an atomic all-or-nothing write, and a receipt lands in
163
+ `~/.sid/bridge/receipts/apply_*.json`. Endpoints: `GET /health`; `POST /pair`,
164
+ `/grant-write`, `/revoke-write`, `/run` `{task, model?, test_argv?}` (with
165
+ `X-SID-Api-Key`), and `/apply` `{proposal_id, digest}`. The browser cannot choose
166
+ the model backend or run tests without the write grant.
167
+
168
+ Installers (Windows/macOS/Linux, private venv + login autostart) and the
169
+ sign/verify chain live in `install/`. `install/prove_brave_apply.py` drives the
170
+ whole pair → grant → run → review → apply path in real Brave headless and checks
171
+ the disk plus the receipt.
172
+
173
+ The Studio ships the client half: a **Local bridge** control in the composer
174
+ shows the paired workspace and read-only/write state; `pairFromLocation()` takes
175
+ the companion's one-click code from the URL fragment, a Chat turn routes to
176
+ `POST {url}/run`, and the receipt (model, tools, tests, diff, changed, final
177
+ response) plus the real workspace preview render in place. **Enable write
178
+ access** posts the explicit grant, and **Apply** posts the reviewed proposal id
179
+ and digest. It fails closed and names the reason when the bridge is unreachable
180
+ or the pairing is stale — there is no silent fallback to the remote gateway. The harness CLI (`sid run` /
181
+ `sid tui`) remains the full-parity product (including `--write`); the Studio's
182
+ bridge path is read-only.
183
+
184
+ ## Editor integration + LSP diagnostics (SUB-96)
185
+
186
+ The VS Code extension under `editors/vscode` is a thin client over this same
187
+ engine: **SID: Open Coding Session** runs `sid session start`, **Show Proposed
188
+ Diff** opens the receipt's diff, **Approve and Apply** calls `sid apply` (the
189
+ same `LocalWorkspace` + repo-policy write path), and **Attach Selection as
190
+ Context** prepends the editor selection to the next task.
191
+
192
+ ```bash
193
+ python -m sid_harness editor install # one command; reload VS Code
194
+ ```
195
+
196
+ `sid lsp` is the diagnostics server. It publishes real Python compiler
197
+ diagnostics (`compile`) on open/change/save and accepts diagnostics forwarded
198
+ from VS Code's other language servers through `sid/diagnostics`. The merged feed
199
+ is written to `<workspace>/.sid/diagnostics.json`; `sid run` and `sid session`
200
+ prepend a data-boundaried `COMPILER DIAGNOSTICS` block to the task and record
201
+ `diagnostics: {count, sources, path}` on the receipt. `--no-diagnostics` opts
202
+ out for one run. No model call, no tool contract, and no write path are added by
203
+ the LSP — it is a diagnostic source for the one loop.
204
+
205
+ ## Scope guards
206
+ - SID stays the only model backend (no aggregator).
207
+ - No new pricing surface; your plan's unit is unchanged.
208
+ - No reimplemented verify/scan — the harness calls the gateway's.
209
+ - No vendor/model name is hardcoded into a rule, script default, or gate.
@@ -0,0 +1,46 @@
1
+ # SID editor integration
2
+
3
+ A VS Code extension that drives the **same** SID engine as `sid run`, `sid tui`,
4
+ and the Studio bridge. It does not carry a second loop, a second tool contract,
5
+ or a second write path.
6
+
7
+ ## One install command
8
+
9
+ ```bash
10
+ python -m sid_harness editor install
11
+ # or, when the console script is on PATH:
12
+ sid editor install
13
+ ```
14
+
15
+ That copies `editors/vscode` into VS Code's extensions directory as
16
+ `sid.sid-harness-<version>`. Reload VS Code to activate it. Set `SID_API_KEY` in
17
+ the environment VS Code inherits (and optionally `sid.command` / `sid.testCommand`
18
+ in Settings). Re-run with `--force` to refresh an existing install.
19
+
20
+ ## What the extension does
21
+
22
+ | Command | Engine path |
23
+ |---|---|
24
+ | `SID: Open Coding Session` | `sid session start` (the one native loop) |
25
+ | `SID: Show Proposed Diff` | the run receipt's `diff` |
26
+ | `SID: Approve and Apply` | `sid apply --approve` (same `LocalWorkspace` + repo policy write path) |
27
+ | `SID: Attach Selection as Context` | prepends the selection to the next session task |
28
+ | `SID: Push Diagnostics to Session` | forwards VS Code diagnostics to `sid lsp` |
29
+
30
+ The extension also starts `sid lsp --dir <workspace>` automatically. The server
31
+ publishes real Python compiler diagnostics (`compile`) and ingests diagnostics
32
+ from every other language server in VS Code through `sid/diagnostics`. It writes
33
+ the merged feed to `<workspace>/.sid/diagnostics.json`; the loop reads that file
34
+ and prepends a data-boundaried `COMPILER DIAGNOSTICS` block to the task, and the
35
+ receipt records `diagnostics: {count, sources, path}`. Use `--no-diagnostics` to
36
+ opt out for one run.
37
+
38
+ ## Install from a source checkout
39
+
40
+ ```bash
41
+ cd infra/sid-harness
42
+ python -m sid_harness editor install
43
+ ```
44
+
45
+ `SID_HARNESS_EXTENSION_PATH` overrides extension discovery (for a packaged
46
+ install). No `vsce`, npm dependency, or marketplace account is required.
@@ -0,0 +1,32 @@
1
+ # SID Harness for VS Code
2
+
3
+ Drive SID's first-party coding loop without leaving the editor.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ python -m sid_harness editor install
9
+ ```
10
+
11
+ Reload VS Code. The `SID:` commands appear in the Command Palette.
12
+
13
+ ## Requirements
14
+
15
+ - The `sid` harness installed (`pip install sid-harness`) and on `PATH`, or set
16
+ `sid.command` to its executable.
17
+ - `SID_API_KEY` in the environment VS Code inherits.
18
+ - Open a folder; SID works on that folder only.
19
+
20
+ ## Commands
21
+
22
+ - **SID: Open Coding Session** — runs `sid session start` and shows the result.
23
+ - **SID: Show Proposed Diff** — opens the receipt's diff in a diff editor.
24
+ - **SID: Approve and Apply** — asks for confirmation, then calls `sid apply`
25
+ (the same write path and repo policy as the CLI).
26
+ - **SID: Attach Selection as Context** — includes the selected text in the next
27
+ session task.
28
+ - **SID: Push Diagnostics to Session** — forwards VS Code diagnostics now.
29
+
30
+ `sid lsp` starts with the extension (Settings → SID → `autoStartLsp`). It feeds
31
+ compiler and language-server diagnostics into every session through the same
32
+ loop the CLI and Studio use.