Skip to content

feat(cli,mcp): add simlock instructions, the rules an agent must follow - #150

Open
V3RON wants to merge 4 commits into
mainfrom
task/147
Open

V3RON wants to merge 4 commits into
mainfrom
task/147

Conversation

@V3RON

@V3RON V3RON commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

Closes #147

simlock instructions prints one Markdown block an operator pastes into an agent's system prompt: never call the platform tools, how to lease and renew, one lease per agent, no --allow-download, exit codes 10/11/13/14, how to reach the device and what is refused, and the four MCP tools. --json wraps it as {"instructions": ...}. The command never connects to or starts the daemon.

The MCP server serves the same text as the simlock://instructions resource (text/markdown). src/instructions/index.ts is the only copy.

The iOS and Android drivers now export their refusal constants (plus REFUSED_RUNTIME_OPERATION, which names a literal the iOS driver already used), so the unit test derives every refused verb from the drivers instead of a copy.

Done when

  • simlock instructions and --json behave as specified: e2e/agent-instructions.test.ts (stdout text, exit 0, no socket; JSON equals text; --bogus is USAGE/2).
  • simlock --help lists the command: USAGE banner in src/cli/index.ts.
  • An MCP client can read simlock://instructions: new case in e2e/mcp-session.test.ts (capability, list, read equals CLI stdout).
  • docs/CLI.md (new section, intro exception list, simlock mcp section) and README.md (Getting started, MCP integration) describe it.
  • pnpm check green on the branch; the slow lane was not run.

Review

Spec review: 12 findings over two rounds, 3 fixed. Code review: 13 findings over two rounds, 8 fixed.

Rejected:

  • instructions --help exits 0 though the spec says other flags are USAGE — every command answers --help, and simlock --help tells users to run simlock <command> --help.
  • The diff touches the driver modules, which Modules touched omits — the spec's test must read the drivers' refusal constants; the only non-export change names an existing literal, behaviour unchanged.
  • The text states CLI details beyond the Scope (--os, --timeout, --export-env, grant field names) — each was checked against docs/CLI.md, and an agent needs them to act on the Scope's lines.
  • The text names driver-owned env keys and verbs outside the drivers (architecture rule 2), and the CLI comment saying refusals live in the driver is now false — this is user-facing prose, as in docs/CLI.md; no code outside the drivers reads a key, and refusal enforcement still lives only in the drivers.
  • The "option before the subcommand" refusals are prose no test pins — the drivers express them as parsing functions, not constants; the test covers every refusal constant.
  • The exit-code list omits 12 — the spec limits it to 10, 11, 13, and 14.
  • pnpm check was not verified — it was run green; see the checklist.
  • Full e2e runs hit "stray daemon outlived daemon stop" teardown failures — only in tests this diff does not touch: 2 of the first 6 full runs on this branch, 0 of 5 on main, the last 4 on this branch green. Not diagnosed. e2e/README.md lists the same symptom as a known gap.

Written by an agent.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PvsMWpwkPBL4Zo2ppLTxDA


Generated by Claude Code

…llow

One static Markdown block, printed by `simlock instructions` (or as
`{"instructions": ...}` with `--json`) and served over MCP as the
`simlock://instructions` resource. The command never touches the daemon.

Closes #147

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PvsMWpwkPBL4Zo2ppLTxDA
Derive `runtime delete` and the caller-supplied scope flags from the iOS
driver's own constants, check the text against every tracked path, test
the command's --help and positional paths, and correct two claims in the
text: every leading simctl option is refused, and exit 13 names a lease
only when the conflict is a lease.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PvsMWpwkPBL4Zo2ppLTxDA
…actly

The adb line now says `--version`/`--help` alone still work and names the
bare `shell` refused when the device is remote; docs/CLI.md says
`instructions --help` prints usage rather than failing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PvsMWpwkPBL4Zo2ppLTxDA
…166)

Closes #157

`simlock setup [--project] [--tool <claude-code|codex>] [--json]` writes
`SKILL.md` into `<base>/.claude/skills/simlock/` and
`<base>/.codex/skills/simlock/`. The base is `$HOME` by default, or the
working directory with `--project`. The file is a two-line front matter
header, a blank line, then the `simlock instructions` text unchanged.
Every tool is checked before anything is written, so a file or symlink
at a `simlock` directory refuses the whole run (`SETUP_REFUSED`, exit
2). Stacked on #150; the base becomes `main` when that merges.

## Completion conditions

- [ ] Rules load as a skill in each tool: e2e finds `SKILL.md` at the
documented paths. **Not checked by hand**, for either Claude Code or
Codex. A maintainer needs to do this.
- [x] User scope writes only under home, project scope only under cwd:
unit test for both scopes, plus e2e.
- [x] Named tool is created if missing; with none named, set-up tools
are written and the rest skipped; a bad `--tool` is `USAGE` exit 2 and
writes nothing: unit tests. The completion condition says "skills
directory", but the technical spec says the presence directory
(`.claude`/`.codex`). I built the technical spec. **Spec needs:** one
wording.
- [x] Skill ends byte for byte with `simlock instructions` output: unit
and e2e tests.
- [x] A re-run leaves the same files, and stale entries are removed:
unit tests.
- [x] Nothing outside the `simlock` directories changes: unit tests
compare the whole tree.
- [x] Human view by default, `--json` prints one object: unit tests.
- [x] No daemon is started: e2e checks that no socket appears.
- [x] `docs/CLI.md` and README updated; `pnpm check` green. One e2e
teardown flake ("stray daemon") also reproduces on `task/147`.

## Review

Spec review: 9 findings, 3 fixed. Code review: 8 findings, 4 fixed.

Rejected:

- The "starts no daemon" check might miss a daemon if the socket
followed `HOME`. It can't: the harness pins `SIMLOCK_HOME`, and the
socket path comes from that.
- The hand check and `pnpm check` are not shown in the diff. They are
covered in the checklist above.
- The exit-code note now says `USAGE` is outside `ERROR_TABLE`. That is
true: the table has no `USAGE` row. The sentence had to change once
`SETUP_REFUSED` was added.
- Removing a `SKILL.md` that is not a file, and its real-filesystem
test, were not asked for. They fix a code-review finding: a run could
write one tool and fail on the other. Only the real filesystem shows the
bug, because the in-memory double allows a rename onto a directory.
- Some tests go beyond the spec's list. They cover the spec's human view
and the code-review fixes.
- Two runs at once can delete each other's temp file. The losing run
exits 1, and the winner still leaves a complete skill.
- The home/cwd wiring is caught only by e2e. The e2e fast lane runs in
`pnpm check`.
- Imports go to `setup.js` and `filesystem.js` instead of index files.
The spec names `setup.ts` as its own file, and direct file imports
across modules are common in `src`.
- User scope ignores `CODEX_HOME`/`CLAUDE_CONFIG_DIR`. The spec fixes
the four paths. **Spec needs:** a decision on these overrides.

*Written by an agent.*

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01BBVXoPLAzqyEJW47zjMVcQ

---
_Generated by [Claude
Code](https://claude.ai/code/session_01BBVXoPLAzqyEJW47zjMVcQ)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add simlock instructions: the rules an agent must follow, printable and served over MCP

2 participants