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
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@

## Docmap - Seek Documentation

**Before any investigation or code exploration**, run `npm run docmap` to list the documentation index. This is mandatory for every task — do not skip it. Browse subdirectories or read files by passing them as arguments (`npm run docmap -- topic-a docs/topic-b/doc.md`), or list everything (`npm run docmap -- --recursive`).
**Before any investigation or code exploration**, run `npm run docmap`, then read the relevant documentation. Mandatory for every task.

## AlignFirst - Ticket ID, Commit Message, Branch Name

_Ticket ID_: Format is numeric. Use the ticket ID if explicitly provided. Otherwise, deduce it from the current branch name (no confirmation needed). If the branch name is unavailable, get it via `git branch --show-current`. Only ask the user as a last resort.

Commit message convention: we use conventional commit, e.g., `feat: [#123] add new feature`. Always prefix the ticket ID with a `#` sign. Do not add a "Co-Authored-By:" line.

Branch naming convention: `<type>/<ticket-id>` (with type from conventional commit, e.g., `feat/123`, `fix/123`, `refactor/123`, `chore/123`).
Branch naming convention: `<ticket-id>/<1-3-words>`.

Add `paleo-typescript-style` skill to every plan.

Expand Down
51 changes: 15 additions & 36 deletions alignfirst-skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,20 @@ npx skills add https://github.com/paleo/alignfirst --global --skill alignfirst -

### Configure your project (optional)

This adds `.plans` to `.gitignore` and an AlignFirst section to your `AGENTS.md` (or `CLAUDE.md`). Give your agent this prompt:
This adds `.plans` to `.gitignore` and an AlignFirst section to your `AGENTS.md` (or `CLAUDE.md`). Install the setup-guide skill temporarily:

```markdown
I just installed the alignfirst skill. Help me configure it:

1. Create `.plans/` directory if it doesn't exist, and add `.plans` to `.gitignore` if needed.
2. Check if `AGENTS.md` or `CLAUDE.md` exists. If one exists, use it. If neither exists, create `AGENTS.md`. This file is our INSTRUCTION_FILE.
3. Look at our git branches (`git branch -a`) to detect our ticket ID format (e.g., `ABC-###`, `PROJ-###`, or numeric).
- If no pattern is found, ask me for our ticket ID format:

> "I couldn't detect a ticket ID format from the branch names. Please provide the ticket ID format (e.g., "numeric", `ABC-###`, etc.) or type 'skip' to omit."

4. From our recent commit messages (`git log --oneline -20`), deduce the commit message convention (e.g., `<type>: [<ticket-id>] description`, `<type>(<scope>): description`, `[<ticket-id>] description`, etc.).
- If no pattern is found, ask me for our commit message convention:

> "I couldn't detect a commit message convention. Please describe it (e.g., `feat: [AB-123] short description`, `type(scope): description`, etc.) or type 'skip' to omit."

5. Detect the default branch with `git remote show origin | grep "HEAD branch"` (e.g., `main`, `master`, `develop`).
```bash
npx skills add https://github.com/paleo/alignfirst --skill alignfirst-setup-guide
```

6. Insert the following into the INSTRUCTION_FILE (skip any part already present):
- Add this line where it feels appropriate: "Always ignore the `.plans` directory when searching the codebase."
- If a ticket ID format was found, add this section (include each convention line only if one was detected or provided):
Then ask your agent:

> ## AlignFirst - Ticket ID, Commit Message, Default Branch
>
> _Ticket ID:_ Format is `{DETECTED_FORMAT}`. Use the ticket ID if explicitly provided. Otherwise, deduce it from the current branch name (no confirmation needed). If the branch name is unavailable, get it via `git branch --show-current`. Only ask the user as a last resort.
>
> _Commit message convention:_ `{DETECTED_CONVENTION}`
>
> _Default branch:_ `{DETECTED_DEFAULT_BRANCH}`
```text
Use your alignfirst-setup-guide skill. Configure the AlignFirst skills in this project.
```

Once done, you can uninstall the setup-guide skill — it won't be used by your project anymore.

> **Note (2026-03-09):** On Cursor, to make the skills available as commands (using `/`), I had to create a symlink: `cd ~/.cursor/ && ln -s ../.agents/skills .`

## Usage
Expand Down Expand Up @@ -152,28 +134,25 @@ Specs, plans, and summaries should be written in well-organized (git-ignored) lo

## Upgrade from v1 or v2

1. Install the docmap skill:
1. Install the setup-guide skill:

```bash
npx skills add https://github.com/paleo/alignfirst --skill docmap
npx skills add https://github.com/paleo/alignfirst --skill alignfirst-setup-guide
```

Then, ask your agent to install the docmap CLI:
2. Ask your agent to run the upgrade:

```text
Use your docmap skill. Install docmap CLI in this project.
Use your alignfirst-setup-guide skill. Upgrade AlignFirst in this project.
```

At the end, the agent will suggest available instructions: ignore them, we will handle that in the prompt of step 2.

2. Give your agent **[this upgrade prompt](https://raw.githubusercontent.com/paleo/alignfirst/refs/heads/main/migrations/upgrade.md)**.
3. Install the new alignfirst skill:
3. Install the new alignfirst skills:

```bash
npx skills add https://github.com/paleo/alignfirst --global --skill alignfirst --skill al --skill alplan --skill alspec --skill aldescription --skill alreview --skill alread --skill almerge
```

> **Note:** We recommend installing the alignfirst skills globally so they're easier to update. For the docmap skill, prefer a local/project installation.
> **Note:** We recommend installing the alignfirst skills globally so they're easier to update.

## License

Expand Down
25 changes: 15 additions & 10 deletions docs/docmap-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,26 @@ Three TypeScript modules in `packages/docmap/src/`, compiled to `packages/docmap
| --- | --- |
| `src/parser.ts` | YAML frontmatter extraction (`extractMetadata`) and stripping (`stripFrontmatter`). |
| `src/formatter.ts` | Directory reading, listing/formatting, name validation, `--check`, and file resolution (`readDocFile`, direct path then fuzzy basename search; returns `undefined` when nothing resolves). |
| `src/cli.ts` | Argument parsing, flow orchestration, package-manager detection for tips. |
| `src/cli.ts` | Argument parsing, flow orchestration, package-manager detection, and help/guide rendering (the `--guide` body is read from `templates/guide.md`). |

Entry point: `packages/docmap/bin/docmap.mjs` → imports `packages/docmap/dist/cli.js` → calls `main()` → returns an exit code.

The `--guide` text lives as Markdown in `packages/docmap/templates/guide.md` with three placeholders: `{{PM}}` for a bare invocation, `{{PM_ARGS}}` for one that forwards arguments, and `{{COMMANDS}}` for the rendered "Browsing with CLI" command block. `{{PM}}` and `{{PM_ARGS}}` differ only for npm, whose `run` script needs a `--` separator before args (`npm run docmap` vs `npm run docmap --`); every other manager forwards args verbatim, so both resolve to the same command. `renderGuide()` reads the file via `new URL("../templates/guide.md", import.meta.url)` — the path resolves from both `src/cli.ts` (dev/test) and `dist/cli.js` (published), each one level under the package root — and substitutes all three tokens. `templates/` is listed in `package.json` `files` so it ships with the package.

Help and guide command lists are built from shared `CommandRow[]` builders (`browseCommands`, `moreCommands`, `guideCommands`) and rendered through one `renderCommands()` helper that pads each command to the group's longest, so the `#` comments stay vertically aligned for any package-manager prefix. Short help, full help (`Commands:` + `More:`), and the guide's `{{COMMANDS}}` block all flow through it; each group aligns independently.

## CLI Flow

`main()` in `src/cli.ts` drives everything:

1. **Parse args** — `parseArgs()` extracts `--recursive`, `--root`, `--check`, collects positional **paths**, and collects unknown `--flags`. Tokens starting with `--` are never paths; an unknown one is recorded and later warned about on stderr (so a stale `docmap --dir topic-a` still works — `--dir` is skipped, `topic-a` is a positional). `parseArgs` is pure (no writes).
1. **Parse args** — `parseArgs()` extracts the mode flags `--help`, `--guide`, `--search <terms>`, `--recursive`, `--root <path>`, `--check`, collects positional **paths**, and collects unknown `--flags`. `--search` consumes the next token as its value (same shape as `--root`); without a following token it is recorded as unknown. Tokens starting with `--` are never paths; an unknown one is recorded and later warned about on stderr (so a stale `docmap --dir topic-a` still works — `--dir` is skipped, `topic-a` is a positional). `parseArgs` is pure (no writes).
2. **Resolve base directory** — `--root` or default `docs/` relative to `cwd`. The **display prefix** is `relative(cwd, baseDir)` — `docs` by default, or the root's path for a custom `--root` (e.g. `config/docs`, or `../shared` outside cwd). All displayed paths carry this prefix, so they stay real and openable; the empty prefix (root === cwd) yields bare paths.
3. **`--check`** → `checkAll()` validates every file and directory name (shell-safe regex) and every `.md` frontmatter. Returns exit code 1 if any issues. (Only `--check` returns non-zero.)
4. **Classify positionals** — each path is normalized (trailing slashes stripped, leading display prefix removed; the bare prefix → root), resolved under the base dir, then `statSync`-tested. Existing directory → listing bucket; everything else (existing file, or missing) → read bucket. `statSync` throwing on a missing path is caught and treated as "not a directory". The filesystem is the source of truth — no extension heuristic.
5. **Listings** — produced for each directory-classified path via `listDirectory()`/`formatDirectory()` or `formatRecursive()`. With no positionals at all, or with `--recursive` and no directory positionals, the root is listed. Files-only with `--recursive` off produces no listing.
6. **Reads** — each read-bucket path goes through `readDocFile()` (direct path, then fuzzy basename search). A resolved result is wrapped in `<document_file>` tags; an unresolved one becomes a single generic `⚠ Not found: <path>` line (same wording for a mistyped file or directory — classification can't read intent, and a not-found read keeps exit code 0). Reads follow listings, separated by a blank line.
7. **Tip** — After a listing, one contextual tip (`formatTip`) is appended explaining that several paths can be passed at once; the example shows directory args only when subdirs exist and file args (carrying the display prefix) only when files exist. The package manager is auto-detected from lockfiles.
3. **Mode dispatch** — modes are tried in precedence and each returns early after printing only its own output: `--help` (full help) → `--guide` (authoring guide) → `--search` (path + frontmatter match) → `--check` (validation) → listing/read. `--help`/`--guide`/`--search` always return `0`; only `--check` can return `1`. Help and guide text is rendered from the auto-detected package manager so every shown command is copy-pasteable.
4. **`--search`** → `searchDocs()` walks the tree (`collectAllFiles`), reads each file, and keeps the ones whose joined `relative-path + title + summary + read_when` text contains every whitespace-split term (case-insensitive; body text is not searched). Including the relative path means a basename or directory segment matches even when absent from frontmatter. Matches render as file bullets, or a single `No documents match: <terms>` line.
5. **Classify positionals** — each path is normalized (trailing slashes stripped, leading display prefix removed; the bare prefix → root), resolved under the base dir, then `statSync`-tested. Existing directory → listing bucket; everything else (existing file, or missing) → read bucket. `statSync` throwing on a missing path is caught and treated as "not a directory". The filesystem is the source of truth — no extension heuristic.
6. **Listings** — produced for each directory-classified path via `listDirectory()`/`formatDirectory()` or `formatRecursive()`. With no positionals at all, or with `--recursive` and no directory positionals, the root is listed. A **bare** invocation (no positionals, none of `--recursive`/`--check`/`--help`/`--guide`/`--search`) lists recursively when the tree holds fewer than 20 `.md` files (`collectAllFiles` count), and is the only case prefixed with short help; at ≥20 it keeps the top-level listing. An explicit `--recursive` is unaffected. Files-only with `--recursive` off produces no listing.
7. **Reads** — each read-bucket path goes through `readDocFile()` (direct path, then fuzzy basename search). A resolved result is wrapped in `<document_file>` tags; an unresolved one becomes a single generic `⚠ Not found: <path>` line (same wording for a mistyped file or directory — classification can't read intent, and a not-found read keeps exit code 0). Reads follow listings, separated by a blank line.
8. **Tip** — After a listing, one contextual tip (`formatTip`) is appended explaining that several paths can be passed at once; the example shows directory args only when subdirs exist and file args (carrying the display prefix) only when files exist. The package manager is auto-detected from lockfiles, falling back to bare `docmap` when no lockfile is found.

## Frontmatter Contract

Expand Down Expand Up @@ -74,8 +79,8 @@ Warnings (⚠) appear inline for name issues or frontmatter errors.
| `npm -w @paleo/docmap test` | Run tests with Vitest |
| `npm run lint` | Biome linter (root) |

Tests live in `packages/docmap/test/docmap.test.ts` and use fixture directories under `packages/docmap/test/fixtures/` (basic, errors, empty, nested, bad-names, subdirs-only). Each fixture is a self-contained `docs/`-like tree passed via `--root`.
Tests live in `packages/docmap/test/docmap.test.ts` and use fixture directories under `packages/docmap/test/fixtures/` (basic, errors, empty, nested, bad-names, subdirs-only, classify, no-frontmatter, large). Each fixture is a self-contained `docs/`-like tree passed via `--root`. The `large` fixture (≥20 `.md` files) exercises the top-level listing kept above the recursive-default threshold.

## Agent Skill
## Authoring Guide and Setup

The `skills/docmap/` directory ships a reusable agent skill that teaches AI agents how to use docmap, write documents, install it in a project, bootstrap a `docs/` directory, and migrate documentation from skills. It is distributed separately from the npm package.
The authoring conventions (frontmatter contract, naming, workflow) ship with the CLI as `templates/guide.md`: `docmap --guide` prints that file, rendered with the project's package-manager prefix. Project setup — bootstrapping a `docs/` tree, wiring docmap into a repo, and migrating existing docs or skills — lives in the separate `alignfirst-setup-guide` skill, distributed outside the npm package.
File renamed without changes.
4 changes: 2 additions & 2 deletions docs/workspace-architecture.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Workspace Package Architecture
summary: Internals of the `@paleo/workspace` kernel — foreground self-exit, stop/teardown signal mechanics, cross-worktree callback dispatch, the `workspace remove` re-exec, the concurrency-cap race, and registry liveness. Complements the `workspace-guide` skill (the consumer-facing blueprint).
summary: Internals of the `@paleo/workspace` kernel — foreground self-exit, stop/teardown signal mechanics, cross-worktree callback dispatch, the `workspace remove` re-exec, the concurrency-cap race, and registry liveness. Complements the workspace setup blueprint (`skills/alignfirst-setup-guide/references/workspace-setup.md`), the consumer-facing guide.
read_when:
- onboarding to the @paleo/workspace codebase
- changing dev-server start/stop, foreground, or eviction behavior
Expand All @@ -10,7 +10,7 @@ read_when:

# Workspace Package Architecture

For the consumer-facing blueprint — concepts, config fields, the CLI surface, and how to adapt the system to a repository — see the [`workspace-guide` skill](../skills/workspace-guide/SKILL.md). This document covers package internals and edge-case behavior that don't belong in that guide.
For the consumer-facing blueprint — concepts, config fields, the CLI surface, and how to adapt the system to a repository — see the [workspace setup blueprint](../skills/alignfirst-setup-guide/references/workspace-setup.md). This document covers package internals and edge-case behavior that don't belong in that guide.

## Foreground self-exit

Expand Down
6 changes: 6 additions & 0 deletions packages/docmap/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @paleo/docmap

## 0.6.0

### Minor Changes

- 4396c78: Self-documenting CLI: add `--help`, `--guide`, and `--search`. Bare run lists recursively for small doc sets. No-lockfile fallback now suggests the package-runner form.

## 0.5.1

### Patch Changes
Expand Down
Loading