Skip to content
Back to skills

Plan Environment

BSecurity

Stage `plan-environment`, wave 1, tier sonnet. Read `../common.md` first. This is prose in `skills/loom-plan-writer/` (from `loom/`, the paths start `../skills/`). No Rust. You own `skills/loom-plan-writer/SKILL.md` and its references `sandbox.md`, `v2-contracts.md`, `authoring-detail.md` and `grounding-protocols.md`.

  • 56 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 1, 2026
ai-agentspythonrustgonodegitdatabase

Security analysis

B84/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 4 files and shows the line behind each finding

Scanned October 1, 2026

npx -y skills add cosmix/loom --skill plan-environment --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Plan Environment?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Plan Environment
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/cosmix-plan-environment/badge)](https://www.skillsdirectory.com/skills/cosmix-plan-environment)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# P3: the plan-writer skill: environment inventory, `provision`, and stage exits

Stage `plan-environment`, wave 1, tier sonnet. Read `../common.md` first. This is prose in
`skills/loom-plan-writer/` (from `loom/`, the paths start `../skills/`). No Rust.

You own `skills/loom-plan-writer/SKILL.md` and its references `sandbox.md`, `v2-contracts.md`,
`authoring-detail.md` and `grounding-protocols.md`.

## Why

The owner's intent: a stage agent disputes when a check is wrong and blocks only for needs
that truly require a person, and plan creation checks network and other human-dependent
requirements up front, so a person is rarely needed. The skill today tells authors to "run
`loom repair`, merge with suggestions" (wrong: `loom repair` prints no domain suggestions;
`loom init` does, `commands/init/plan_setup.rs:136-175`), never mentions `loom stage block`,
frames a dispute as a cost, and tells a stage agent to "stop and report".

## Settled facts to write from (do not invent others)

- New plan field, `version: 2` only: `loom.provision: [{ working_dir: "<dir>", command:
  "<cmd>" }]`. Each time a stage session spawns in a worktree (first spawn, retry, handoff
  successor, requeue after a verdict; standard, integration-verify and knowledge-distill
  stages), the daemon first runs the stage's `before_stage` checks on the pristine worktree,
  then each provision command on the host, in `<worktree>/<working_dir>`, in order, 600 s
  each, with the stage-command environment (`HOME` and `PATH` kept, credentials dropped). The
  contract phase's own spawns on that worktree (the contract-to-implementation handoff and a
  replacement contract session) reuse the install. A provision command may write only files
  git ignores (`node_modules/`, `.venv/`): the daemon compares `git status` before and after
  and blocks the stage on any new entry, which would otherwise read as a non-contract edit at
  the contract freeze and as prior stage work on a retry. `before_stage` checks run first and
  therefore must not need provisioned dependencies. A failure blocks the stage, and
  `loom status` shows provision \`<cmd>\` in \`<dir>\` failed: <stderr tail>. Commands must be
  idempotent (every retry, handoff successor and verdict requeue runs them again); `bun install --frozen-lockfile`, `npm ci`,
  `uv sync --frozen` and `pnpm install --frozen-lockfile` are. `loom init` copies the entries
  into the work directory's `config.toml` (`[plan_provision]`), and the daemon runs only that
  copy, never the plan file, because a stage can edit the plan file and provision runs on the
  host. To change the entries during a run, the operator edits `[plan_provision]` and runs
  `loom stage retry <id>`. Provision runs outside the sandbox: its registry needs no
  `allowed_domains` entry.
- The JS-provision and pre-commit-hook lints judge the repository, not the stages. In a
  repository with a JS package (this one has `web/`), every v2 plan needs a `provision` entry
  for it; in one whose pre-commit hook runs `bunx`, every sandboxed stage needs
  `registry.npmjs.org`, because every stage commits.
- `loom stage block` and `loom stage dispute-*` are the stage MAIN agent's commands. A
  subagent reports the need to its orchestrator instead: a block retires the stage session.
- New `loom plan verify` errors (v2): a command in a stage's acceptance, setup, wiring tests,
  after-stage checks or dead-code check that fetches from a registry its sandbox does not
  allow (`bunx`/`npx`/`npm|bun|pnpm|yarn install` → `registry.npmjs.org`; `cargo
  install|fetch` → `crates.io`, `index.crates.io`, `static.crates.io`; `uv sync|add`, `uv pip
  install`, `uvx`, `pip install` → `pypi.org`, `files.pythonhosted.org`; `go get`, `go mod
  download` → `proxy.golang.org`); the repository's pre-commit hook (from `core.hooksPath`,
  else `.git/hooks`) fetching from a registry a stage does not allow; a JS package with a test
  runner that no `provision` entry covers. `loom init` prints domain suggestions.
- `loom stage dispute-criteria <stage-id> [--field acceptance|wiring|wiring-tests]
  --criterion-index <n> --reason "..."`; `loom stage complete` labels failures `[criterion
  n]`, `[wiring n]`, `[wiring_tests n]`.
- `loom stage block <stage-id> "<what is needed and why>"`: from a stage agent, the daemon
  retires the session, the exit is not a crash, `loom status` shows the reason, and the operator
  resumes with `loom stage retry <stage-id>` after providing what was needed.
- Filing any dispute ends the stage session by design; the daemon starts a fresh session with
  the verdict. Impact-selected tests have no dispute: a failure there is a regression.
- BLOCK-F, which stage `stage-exits` puts in every stage signal. Its exact bytes are the one
  line in the plan YAML (stage `stage-exits`, "BLOCK-F, verbatim"); if you quote it, copy that
  line, not the wrapped reading copy below, which is here only so you know what it says:

  > **When the stage cannot finish.** Fix what the stage can fix. A criterion, wiring check,
  > contract, review finding or test-integrity event that is wrong gets a dispute: `loom stage
  > dispute-criteria` (with `--field` for wiring and wiring-tests entries), `dispute-contract`,
  > `dispute-findings` or `dispute-integrity`. Filing ends this session by design: the daemon
  > starts a fresh session with the verdict, so waiting gains nothing. Never revert, weaken or
  > postpone correct work to avoid a dispute. A need only a person can meet (a credential, a
  > host install, a network domain or path the plan does not grant) gets `loom stage block
  > <stage-id> "<what is needed and why>"`: the daemon retires the session and shows the reason
  > to the operator. Commit your work before filing either. Never end a turn asking the
  > operator to act while the stage is executing.

## Edits

1. **SKILL.md Section 8** (`## 8. Sandbox & Execution Environment`, about line 411):
   - Replace "Then run `loom repair`, merge with suggestions, and add a `sandbox` block" with:
     `loom init` prints domain suggestions; `loom plan verify` now errors on the registry,
     hook and JS-provision gaps it can see.
   - Add an **environment inventory** checklist, walked per stage across the stage's whole
     life, where each need ends as allowed (a sandbox domain or path), provisioned (a
     `loom.provision` entry), or resolved with the user before `loom run`: implementation
     fetches (`cargo add`, `bun add`, `uv add`, `go get`), acceptance commands,
     impact-selected runners per package (a JS package needs `node_modules`: provision it),
     the repository's git hooks (a pre-commit `bunx` needs the npm registry in every stage
     that commits), audit databases (`cargo audit` fetches from github.com unless run with
     `--no-fetch` against a host copy), credentials and tokens, and host tools that must be
     installed.
   - Document `loom.provision` with a YAML example, the idempotence rule, when it runs (after
     the `before_stage` checks), that it runs outside the sandbox, that the daemon runs the
     `loom init` snapshot and never the plan file, and that a repository with a JS package
     needs an entry in every v2 plan.
2. **SKILL.md Section 9**: keep the dispute text, add `--field` for wiring and wiring-tests
   entries, say a dispute ending the session is expected and the daemon starts a fresh one
   with the verdict, and name `loom stage block <stage-id> "<what is needed and why>"` for a
   need only a person can meet, with what the daemon does. Wording agrees with BLOCK-F.
3. **SKILL.md Pre-STOP checklist** (about line 673): add a line "Environment inventory done:
   every network, install, credential and host need of every stage allowed, provisioned or
   resolved with the user".
4. **references/sandbox.md**: a `provision` section (what, when, host-side, idempotent, how it
   differs from `setup:`, which only prefixes acceptance commands), and the pre-commit hook's
   network need.
5. **references/v2-contracts.md** line about 128 (Disputes bullet) and about 138 (Dispute in
   batches): say filing ends the session by design and a fresh session starts with the verdict;
   keep the batching advice (one `dispute-findings` per round). Name `--field` in the
   zero-test-guard row's `dispute-criteria` mention if you touch it. Do NOT edit the
   Impact-selected tests row or bullet: knowledge-distill rewrites those after this plan
   merges.
6. **references/authoring-detail.md** Section 9 (about line 116): replace "A stage agent
   facing one is correct to stop and report rather than weaken the check — its sanctioned move
   is ..." with the dispute route (BLOCK-F's wording), and name `loom stage block` for a need
   only a person can meet.
7. **references/grounding-protocols.md** "JS/TS projects: provision worktree dependencies
   first": the plan's `loom.provision` entry is how a worktree gets `node_modules` before a
   session starts; an in-session `bun install` remains the fallback when the daemon cannot
   provision (and needs `registry.npmjs.org` plus a `node_modules` write grant).

## Constraints

- `orchestrator/signals/tests_doctrine.rs` pins BLOCK-B verbatim in SKILL.md Section 4 and
  sweeps SKILL.md for retired phrases; `tests_doctrine_v2.rs` requires SKILL.md to name `loom
  project detect` and `references/v2-contracts.md`. Leave Section 4 and those names alone.
  Never write "report a needed sandbox block as a blocker", "STOP and report it as a blocker",
  or "ends your turn and sends the stage to adjudication; loom retires" (stage `stage-exits`
  retires them).
- Every fenced code block names its language. Tables stay aligned. Writing style: plain
  sentences, no marketing words, no "not X, but Y" constructions.
- Acceptance greps SKILL.md for `loom.provision` and `loom stage block`, and
  `references/sandbox.md` for `provision`. It also fails if the old advice "run `loom repair`,
  merge with suggestions" survives in SKILL.md, or if any file under `skills/loom-plan-writer/`
  holds one of the three retired phrases above (stage `stage-exits` adds them to the doctrine
  sweep, which reads SKILL.md, and runs in parallel with this stage).

## Check

None: P1 edits the crate in parallel. The main agent runs
`cargo test --lib orchestrator::signals::tests_doctrine`, which reads SKILL.md.

Files in this skill

  • p1-provision.md17.4 KB
  • p2-environment-lints.md12.5 KB
  • p3-plan-writer-skill.md10.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…