Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/rules/agents-tier-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Genuinely cross-cutting. Apply to every turn regardless of file:
- `pr-comment-fact-check` — fires the fact-check skill on PR-comment intent triggers
- `preserve-comments` — never silently delete TODOs / commented-out code
- `tracer-bullets` — small end-to-end slices, not horizontal layers
- `consumer-surfaces` — consumer-facing text describes user-visible behavior only
- `verify-after-each-step` — run the project's checks per milestone, not at commit time

### Tier 2 — Auto-attached technical rules (this rule's tier)
Expand Down
5 changes: 5 additions & 0 deletions .agents/rules/concise-comments.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ For every comment you wrote, ask: **"Could a teammate (human or AI) re-derive th
- Section headers in short files (`// === Helpers ===`).
- Author / date stamps (git tracks this).
- Multi-line prose where one clause does the job.
- **Prose inside JSDoc** when `@param` / `@returns` / `@typedef` already carry the meaning — types stay; narrating them does not.

## Exception: JSDoc as types (`.mjs`, `@ts-check`)

Untyped JS has no `.ts` surface — **`@typedef`, `@param`, `@returns`, and inline `@type` are the type system; keep them.** Apply the decision test only to **prose** in those blocks (keep non-obvious _why_ like `bunx` vs `bun x`; cut restatements of param names or return shapes).

## Reconcile with `preserve-comments`

Expand Down
40 changes: 40 additions & 0 deletions .agents/rules/consumer-surfaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
description: Consumer-facing surfaces must describe user-visible behavior only — no maintainer internals, CI wiring, or implementation file names.
alwaysApply: true
---

# Consumer surfaces

Consumers install **`@stainless-code/codemap`** and interact through CLI, MCP, HTTP, and bundled agent templates. They must only see **what to run** and **what it does** — never how this repo implements it.

## Consumer surfaces (write for users)

| Surface | Audience |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `templates/agent-content/**` | Served live via `codemap skill` / `codemap rule`, `codemap://skill` / `codemap://rule`, MCP `instructions`, HTTP resources |
| `templates/agents/**` | Copied into consumer projects by `codemap agents init` |
| **`.changeset/*.md` body** | Release notes → `CHANGELOG.md` on npm |
| **Root `README.md` (install / usage)** | npm landing page |
| **CLI help text and user-facing errors** | Terminal output |

`docs/agents.md` is maintainer reference linked from bundled README — keep **MCP wiring / init** sections consumer-accurate; implementation tables belong in maintainer sections, not in served agent-content.

## Maintainer-only (never leak into consumer surfaces)

- Internal refactors, CI / GitHub Action wiring, dual-file sync (`*.ts` ↔ `*.mjs`)
- `scripts/`, `docs/plans/`, `docs/research/`, module paths under `src/`
- Dogfood paths (`bun src/index.ts`) — maintainer workflow only; consumers use PM-aware spawn from `agents init --mcp`
- “We moved X to Y” unless the **user-visible** command or output changed

## When editing consumer surfaces

1. **Behavior, not implementation** — e.g. “PM-aware MCP spawn via `agents init --mcp`”, not “`resolveCodemapCliInvocation` in `codemap-invocation.ts`”.
2. **Changesets** — user-visible outcome only; no Action refactors, detect-pm delegation, or sync comments between source files.
3. **Served skill / rule** — no hardcoded `{command: "codemap"}` unless documenting legacy manual wiring; prefer `codemap agents init --mcp` and PM-specific examples (`npx`, `pnpm exec`, `yarn exec`, `bunx`, dlx).
4. **Cross-ref maintainer detail** — plans, architecture internals, and contributor tables stay in `docs/` or `.agents/` skills; link from consumer text only when the user must follow a public doc (e.g. [agents.md § MCP wiring](https://github.com/stainless-code/codemap/blob/main/docs/agents.md#mcp-wiring-via-agents-init)).

## Decision test

Before shipping text on a consumer surface: **“Would a user who only `npm i @stainless-code/codemap` care?”** If no → cut it or move it to a maintainer doc.

Related: [`write-a-skill`](../skills/write-a-skill/SKILL.md) (maintainer vs shipped templates), [`docs-governance`](./docs-governance.md) Rule 10 (agent-content layers).
2 changes: 1 addition & 1 deletion .agents/rules/docs-governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ alwaysApply: false

Before authoring or editing any doc in this repo, **read the [`docs-governance` skill](../skills/docs-governance/SKILL.md)** for the full reference. This rule is the priming layer.

The canonical Rules (1–10) live in [`docs/README.md`](../../docs/README.md) — cite them by number; never restate them.
The canonical Rules (1–10) live in [`docs/README.md`](../../docs/README.md) — cite them by number; never restate them. Consumer-surface policy: [`.agents/rules/consumer-surfaces.md`](./consumer-surfaces.md) (Rule 10 sub-bullet).

## Surface tiers (which subset of governance applies)

Expand Down
5 changes: 5 additions & 0 deletions .changeset/mcp-invocation-resolve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stainless-code/codemap": patch
---

`codemap agents init --mcp` writes PM-aware MCP spawn commands (e.g. `npx codemap`, `pnpm exec codemap`, `yarn exec codemap`, `bunx codemap`, or dlx `@stainless-code/codemap@latest`) instead of assuming global `codemap` on PATH.
1 change: 1 addition & 0 deletions .cursor/rules/consumer-surfaces.mdc
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ jobs:
- name: Run unit tests with coverage
run: bun run test:coverage

- name: Run scripts tests (Action helpers + TS↔mjs sync)
run: bun run test:scripts

- name: Golden query regression (fixtures/minimal)
run: bun run test:golden

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ codemap context --compact --for "refactor auth" # JSON envelope + i
codemap ingest-coverage coverage/coverage-final.json --json # Istanbul / LCOV (auto-detected) → coverage table; joins with symbols
NODE_V8_COVERAGE=.cov bun test && codemap ingest-coverage .cov --runtime --json # V8 protocol (per-process dumps); local-only
codemap agents init # scaffold .agents/ rules + skills
codemap agents init --mcp # project MCP config (see docs/agents.md)
codemap agents init --mcp # PM-aware project MCP config (see docs/agents.md)
codemap apply rename-preview --params old=foo,new=bar --dry-run # preview recipe-driven edits (substrate executor)
```

Expand Down Expand Up @@ -246,7 +246,7 @@ codemap --files src/a.ts src/b.tsx
# Scaffold .agents/ from bundled templates — full matrix: docs/agents.md
codemap agents init
codemap agents init --force
codemap agents init --mcp # project MCP config for supported IDEs
codemap agents init --mcp # PM-aware project MCP config (see docs/agents.md)
codemap agents init --interactive # -i; IDE wiring + symlink vs copy
```

Expand Down
16 changes: 10 additions & 6 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ inputs:

outputs:
agent:
description: "Resolved package manager (npm / pnpm / yarn / bun)."
description: "Resolved package manager (npm / pnpm / yarn / yarn@berry / bun)."
value: ${{ steps.detect-pm.outputs.agent }}
exec:
description: "Shell-ready command used to invoke codemap."
Expand Down Expand Up @@ -140,14 +140,18 @@ runs:
env:
PACKAGE_MANAGER: ${{ inputs.package-manager }}
VERSION: ${{ inputs.version }}
WORKING_DIRECTORY: ${{ inputs.working-directory }}
run: |
ACTION_STAGE="$RUNNER_TEMP/codemap-action"
WORK_DIR="${{ inputs.working-directory }}"
RESOLVED_WORKDIR="$(bash "${{ github.action_path }}/scripts/action-resolve-working-directory.sh" "$GITHUB_WORKSPACE" "$WORK_DIR")"
# Action runs without its own node_modules; install the detector lazily.
# Pinned to a known version so consumers get reproducible builds.
npm install --no-save --prefix "$RUNNER_TEMP/codemap-action" package-manager-detector@1.6.0 >/dev/null
cp "${{ github.action_path }}/scripts/detect-pm.mjs" "$RUNNER_TEMP/codemap-action/detect-pm.mjs"
cd "$RUNNER_TEMP/codemap-action"
node detect-pm.mjs
npm install --no-save --prefix "$ACTION_STAGE" package-manager-detector@1.6.0
cp "${{ github.action_path }}/scripts/detect-pm.mjs" \
"${{ github.action_path }}/scripts/codemap-invocation.mjs" \
"$ACTION_STAGE/"
cd "$ACTION_STAGE"
WORKING_DIRECTORY="$RESOLVED_WORKDIR" node detect-pm.mjs

- name: Validate inputs (mode + flag interactions)
if: steps.gate.outputs.skip != 'true'
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ These rules are normative — cite them by number in PR review. Ordered by how o
- **Auto-flows (no template edit needed)** — recipe additions (`templates/recipes/*.{sql,md}`), schema additions (`src/db.ts` `createTables()`). Both surfaces via `*.gen.md` renderers in `src/application/agent-content.ts`; `codemap skill` re-assembles every call, while MCP/HTTP memoize the assembled skill/rule/schema/mcp-instructions body per server process.
- **Narrative changes** — new CLI flag / output mode / MCP tool / HTTP route / output-shape change → edit the relevant hand-written section in **`templates/agent-content/skill/*.md`** (single source of truth; `codemap skill` (CLI), `codemap://skill` (MCP), and `GET /resources/{encoded-uri}` against `codemap serve` (HTTP) all serve the same assembled body).
- **Pointer-shape changes** (frontmatter schema, fetch instructions, marker comments) → edit `templates/agents/{rules/codemap,skills/codemap/SKILL}.md` AND bump `EXPECTED_POINTER_VERSION` in `agent-content.ts` so consumers see the staleness nag and re-run `codemap agents init --force`.
- **Consumer-only surfaces** — [`templates/agent-content/`](../templates/agent-content/), [`templates/agents/`](../templates/agents/), [`.changeset/`](../.changeset/) bodies, and user-facing CLI text describe **user-visible behavior** only. No maintainer internals (Action wiring, `src/` module names, dual-file sync, dogfood spawn paths). Full policy: [`.agents/rules/consumer-surfaces.md`](../.agents/rules/consumer-surfaces.md).

This repo's `.agents/{rules/codemap,skills/codemap/SKILL}.md` are thin pointers too (regenerate via `bun src/index.ts agents init --force` if pointer shape drifts) — they used to be the dev-side "second copy" to keep in sync; that obligation is gone.

Expand Down
7 changes: 4 additions & 3 deletions docs/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Example: `CODEMAP_MCP_TOOLS=query,context,show codemap mcp --no-watch`

| Target | Files written |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Cursor | `.cursor/mcp.json` — `codemap mcp --watch --root ${workspaceFolder}` |
| Cursor | `.cursor/mcp.json` — PM-resolved spawn + `mcp --watch --root ${workspaceFolder}` (e.g. `npx codemap`, `pnpm exec codemap`, `yarn exec codemap`, `bunx codemap`) |
| Claude Code | `.mcp.json` + `.claude/settings.json` — `permissions.allow` includes `mcp__codemap__*` |
| VS Code / Copilot | `.vscode/mcp.json` — `servers.codemap` with `type: stdio` |
| Continue | `.continue/mcpServers/codemap-mcp.json` (JSON `mcpServers`; also accepted from Cursor/Cline exports) |
Expand All @@ -138,9 +138,9 @@ Example: `CODEMAP_MCP_TOOLS=query,context,show codemap mcp --no-watch`

With **`--mcp`** and no `--target` filter, all **project-local** rows above are written except **Windsurf**, which has no documented workspace MCP path.

Merge is idempotent: foreign MCP servers and existing settings keys are preserved; only the `codemap` server entry and permission pattern are upserted. Requires `codemap` on `PATH` (global install or dev dependency binary).
Merge is idempotent: foreign MCP servers and existing settings keys are preserved; only the `codemap` server entry and permission pattern are upserted. **`command` / spawn args are resolved from the project** (when `@stainless-code/codemap` is listed in `package.json`, the local PM runner is used — e.g. `pnpm exec codemap`, `yarn exec codemap`, `bunx codemap`; otherwise PM dlx of `@stainless-code/codemap@latest` — e.g. `npx @stainless-code/codemap@latest`, `pnpm dlx @stainless-code/codemap@latest`, `yarn dlx @stainless-code/codemap@latest`; yarn classic may fall back to `npx` per `package-manager-detector`; Bun uses **`bunx`**, not `bun x`). Init logs the chosen invocation (`MCP CLI: …`).

**Side-effect-only re-runs:** When `.agents/` already exists, `codemap agents init --mcp` or `--git-hooks` still applies MCP/hook changes without `--force`. `codemap agents init --no-git-hooks --mcp` uninstalls hook blocks and writes MCP even when `.agents/` is absent. Template refresh still requires `--force`. Unparseable MCP JSON is rejected unless `--force` (which replaces the whole file and drops foreign entries — a warning is printed).
**Side-effect-only re-runs:** When `.agents/` already exists, `codemap agents init --mcp` or `--git-hooks` still applies MCP/hook changes without `--force`. `codemap agents init --no-git-hooks --mcp` uninstalls hook blocks and writes MCP even when `.agents/` is absent. Template refresh still requires `--force`. Unparseable MCP JSON is rejected unless `--force` (full file replace; foreign MCP entries dropped — warning printed). Invalid `mcpServers` / `servers` **shape** with `--force` replaces only that map and preserves other top-level keys.

## Section assembler and `*.gen.md`

Expand Down Expand Up @@ -188,6 +188,7 @@ Warning goes to stderr only so `codemap skill > file.md` stays clean.
| **`src/agents-init-targets.ts`** | **`AgentsInitTarget`** + symlink-style integration ids — shared by init and MCP registry without import cycles. |
| **`src/agents-init.ts`** | **`runAgentsInit`**, **`upsertCodemapPointerFile`**, **`listRegularFilesRecursive`**, **`applyAgentsInitTargets`** (per-file **`copyFileSync`** / **`symlinkFilesGranular`**), **`ensureGitignoreCodemapPattern`** (writes `<state-dir>/.gitignore`), **`targetsNeedLinkMode`**. |
| **`src/agents-init-mcp-registry.ts`** | **`AGENTS_INIT_MCP_REGISTRY`** — paths, formats, defaults, docs URLs (source of truth for the MCP table below). |
| **`src/codemap-invocation.ts`** | PM-aware codemap CLI spawn resolution (`resolveCodemapCliInvocation`, `buildCodemapMcpSpawn`); shared with `scripts/codemap-invocation.mjs`. |
| **`src/agents-init-mcp.ts`** | **`applyAgentsInitMcp`**, JSON merge + post-write verify; **`--mcp`** side effect. |
| **`src/agents-init-interactive.ts`** | **`@clack/prompts`** flow; calls **`runAgentsInit`**. |
| **`src/cli/cmd-agents.ts`** | Lazy-loaded from **`src/cli/main.ts`**. |
Expand Down
Loading
Loading