mirror of
https://github.com/jparkerweb/plan2code.git
synced 2026-07-21 18:33:22 -07:00
Compare commits
6 Commits
v1.15.4
...
aedfe944b2
| Author | SHA1 | Date | |
|---|---|---|---|
| aedfe944b2 | |||
| 9b3c06b498 | |||
| 8fe1bfa805 | |||
| 68542fd778 | |||
| 4656a6ebb7 | |||
| 7e9de755f1 |
@@ -27,6 +27,8 @@ plan2code/
|
||||
│ └── local-commands/ # For per-project installation (.claude/, etc.)
|
||||
├── .husky/ # Git hooks (husky)
|
||||
│ └── pre-commit # Runs character count validation
|
||||
├── .claude/ # Repo-local Claude Code config (NOT installed by install.js)
|
||||
│ └── skills/ # Maintainer-only dev skills, e.g. plan2code-publish/
|
||||
├── docs/ # Documentation and assets
|
||||
├── specs/ # Feature specs (if any in-progress)
|
||||
├── install.js # Interactive installer (Node.js)
|
||||
@@ -59,6 +61,7 @@ plan2code/
|
||||
| `plan2code-3-implement.md` | 3 | Execute implementation (phase by phase) |
|
||||
| `plan2code-review.md` | review | Post-implementation comprehensive review |
|
||||
| `plan2code-4-finalize.md` | 4 | Validate, summarize, feedback, archive (7 steps) |
|
||||
| `plan2code-handoff.md` | handoff | Compact the conversation into a self-contained handoff document |
|
||||
|
||||
## Naming Convention
|
||||
|
||||
@@ -84,6 +87,14 @@ Some workflows use companion reference files for depth that exceeds the 11k char
|
||||
|
||||
Reference files are NOT subject to the 11,000 character limit. Currently only the review workflow uses this pattern — it serves as the POC for potential adoption by other workflows.
|
||||
|
||||
## Repo-Local Skills (`.claude/skills/`)
|
||||
|
||||
Maintainer-only Claude Code skills committed to the repo but **deliberately excluded** from `install.js` — they are dev tooling, not shipped product, so they never install to `~/.claude/skills/` and carry no version bump of their own (a product-version bump would wrongly imply a user-facing release); changelog mentions fold into the current version's entry.
|
||||
|
||||
- `plan2code-publish/` — cuts a GitHub Release from the top `CHANGELOG.md` entry once `CHANGELOG.md` / `version.json` / `package.json` agree and the version is ahead of the latest published release. Delegates tag creation to `gh release create --target main`.
|
||||
|
||||
**Warning:** anything named `plan2code-*` placed under `~/.claude/skills/` is deleted by the installer's uninstall (`uninstallFiles()` in `install.js`) and by every re-install's pre-copy cleanup in `install()` (both match `/^plan2code-/` for the Claude Code skills target). Keep these skills repo-local only.
|
||||
|
||||
## Status Line
|
||||
|
||||
Optional Claude Code status bar living in `src/statusline-claude/`. Three-line bar (icon + content per line) showing model, project, branch, uncommitted diff stats, session duration + cost, context window usage, and plan/quota usage.
|
||||
|
||||
@@ -74,3 +74,29 @@ When modifying workflow prompts in `src/`:
|
||||
2. Run `node install.js` to regenerate distribution files
|
||||
3. Test the workflow in your AI tool of choice
|
||||
4. The `dist/` folder is regenerated automatically — don't edit files there directly
|
||||
|
||||
## Adding a New Workflow Prompt / Skill
|
||||
|
||||
Adding a new prompt to `src/` is more than dropping in a file — the installer is
|
||||
driven by an explicit registry and several docs enumerate the command set. When
|
||||
you add a `src/plan2code-<name>.md`, do **all** of the following so nothing drifts:
|
||||
|
||||
1. **Create the source file** `src/plan2code-<name>.md` — body content **only**,
|
||||
no YAML frontmatter (the installer generates frontmatter per platform). Keep
|
||||
it **under 11,000 characters** (`npm test` enforces this).
|
||||
2. **Register it in the installer.** Add an entry to the `SOURCE_PROMPTS` array in
|
||||
`install.js` (`source`, `stepNumber`, `name`, `displayName`, `description`, and
|
||||
`isUtility: true` for non-numbered utilities). If `stepNumber` is a non-numeric
|
||||
label (e.g. `'handoff'`), add a matching case to `generateStepLabel()` so the
|
||||
generated description reads correctly.
|
||||
3. **Update every doc that lists the command set** — keep these in sync, they are
|
||||
the canonical inventories:
|
||||
- `README.md` — command table ("When to Use")
|
||||
- `QUICK-REFERENCE.md` — Commands table
|
||||
- `.agents-docs/AGENTS-architecture.md` — "Workflow Prompts (in `src/`)" table
|
||||
- `CHANGELOG.md` — add an entry under the current version
|
||||
- `docs/index.html` — **only** if the new prompt belongs to the core pipeline
|
||||
shown there; utilities (like `init`, `quick-task`, `handoff`) are deliberately
|
||||
omitted from that curated marketing list.
|
||||
4. **Regenerate and validate:** run `node install.js` (regenerates `dist/`) and
|
||||
`npm test` (character-count validator now covers the new file).
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
---
|
||||
name: plan2code-publish
|
||||
description: "Publish a GitHub Release for jparkerweb/plan2code whenever CHANGELOG.md's top version is ahead of the latest published release on GitHub — after verifying CHANGELOG.md, version.json, and package.json all agree on the version. Use this skill when the user says 'publish a release', 'create a GitHub release', 'cut a release', 'tag a release', 'tag and release', 'is the changelog published', or otherwise mentions publishing/releasing/tagging this repo."
|
||||
---
|
||||
|
||||
# Plan2Code Release Publisher
|
||||
|
||||
Publish a GitHub Release for `jparkerweb/plan2code` whenever `CHANGELOG.md`'s top version is ahead of the latest published release on GitHub. This turns the merged CHANGELOG entry on `main` into an actual GitHub Release (which also creates the `vX.Y.Z` git tag).
|
||||
|
||||
**Repo-local by design.** This skill lives in the repo's `.claude/skills/` and is intentionally NOT wired into `install.js` — it is a maintainer dev tool, not part of the shipped product, so it is never installed to `~/.claude/skills/`. Do **not** copy it there: the uninstaller (`uninstallFiles()` in `install.js`) and every re-install's pre-copy cleanup in `install()` both delete every entry matching `/^plan2code-/` under `~/.claude/skills/`, so a copy placed there would be silently removed.
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1 — Preflight: clean working tree
|
||||
|
||||
Run `git status --porcelain`. If the output is non-empty, stop immediately — do not switch branches or take any other action. Tell the user:
|
||||
|
||||
> Working tree has uncommitted changes. Commit or stash them, then re-run this skill.
|
||||
|
||||
### Step 2 — Switch to main and pull
|
||||
|
||||
If the working tree is clean, switch to `main` and pull latest. Run these as two separate, non-chained commands (never `&&`/`;`-chain `git`/`gh` commands — Windows PowerShell 5.1 rejects `&&`):
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
git pull origin main
|
||||
```
|
||||
|
||||
### Step 3 — Read the three version sources
|
||||
|
||||
Read all three files at the repo root and extract each version:
|
||||
|
||||
- `CHANGELOG.md` — parse the first `## vX.Y.Z` heading. Strip the leading `v` → `$CHANGELOG_VERSION`. Note: plan2code CHANGELOG headings are `## vX.Y.Z` (v-prefixed, **no** date and **no** brackets) — different from a `## [x.y.z] - YYYY-MM-DD` format.
|
||||
- `version.json` — the `version` field → `$VERSION_JSON`. Also read its `releaseDate` field → `$RELEASE_DATE` (informational only — shown at the confirm step, never part of the sync gate; use `(none)` if absent).
|
||||
- `package.json` (root) → the `version` field → `$PACKAGE_JSON`.
|
||||
|
||||
Also capture from `CHANGELOG.md` the **section body** for the top version: everything from the `## vX.Y.Z` heading line itself (heading **included**) up to — but not including — the next `## v` heading, or end-of-file if there is none. Call this `$SECTION`. Keep the `## vX.Y.Z` heading in `$SECTION`; plan2code release bodies include it.
|
||||
|
||||
### Step 4 — Version-sync preflight (STOP on mismatch)
|
||||
|
||||
All three versions must be identical. This enforces the repo's documented invariant (`.agents-docs/AGENTS-code-style.md` → "Version sync"): `CHANGELOG.md`, `version.json`, and `package.json` must always show the same version number.
|
||||
|
||||
If `$CHANGELOG_VERSION`, `$VERSION_JSON`, and `$PACKAGE_JSON` are **not** all equal, **stop** — do not read the release, do not publish. Report exactly which files disagree:
|
||||
|
||||
> ⚠️ Version files are out of sync — refusing to publish. The repo requires `CHANGELOG.md`, `version.json`, and `package.json` to match.
|
||||
>
|
||||
> - **CHANGELOG.md:** $CHANGELOG_VERSION
|
||||
> - **version.json:** $VERSION_JSON
|
||||
> - **package.json:** $PACKAGE_JSON
|
||||
>
|
||||
> Fix the mismatch first, then re-run this skill. To realign: pick the intended version (normally the highest / newest CHANGELOG entry) and update the other two files to match — see the "Version sync" gotcha in `.agents-docs/AGENTS-code-style.md`.
|
||||
|
||||
This skill never modifies these files — it only reads and compares them.
|
||||
|
||||
### Step 5 — Determine the highest published release
|
||||
|
||||
List every published (non-draft) release and take the numerically-highest semver tag. Do **not** rely on `gh release view` / GitHub's "Latest" flag: that flag returns whatever release is *marked* latest — normally the newest semver, but a maintainer can manually pin it to an older release, which would make the Step 6 ahead-comparison misfire.
|
||||
|
||||
```bash
|
||||
gh release list --repo jparkerweb/plan2code --limit 100 --json tagName,isDraft -q '.[] | select(.isDraft==false) | .tagName'
|
||||
```
|
||||
|
||||
Strip any leading `v` from each returned tag, compare them as numeric `(major, minor, patch)` tuples (the same rule as Step 6), and take the maximum → `$RELEASE_VERSION`. If the command returns no tags or exits non-zero for **any** reason (no releases yet, transient error, etc.), set `$RELEASE_VERSION = "0.0.0"` — no error-text matching is needed.
|
||||
|
||||
### Step 6 — Compare versions
|
||||
|
||||
Compare `$CHANGELOG_VERSION` vs `$RELEASE_VERSION` as a numeric `(major, minor, patch)` tuple. Never do a plain string/lexicographic compare — e.g. `"1.9.0" > "1.10.0"` is true as strings but wrong numerically.
|
||||
|
||||
### Step 7 — Not ahead: no-op
|
||||
|
||||
If `$CHANGELOG_VERSION` ≤ `$RELEASE_VERSION`, print a simple status message showing both versions and stop:
|
||||
|
||||
> CHANGELOG top version ($CHANGELOG_VERSION) is not ahead of the latest published release ($RELEASE_VERSION). Nothing to publish.
|
||||
|
||||
No error is raised and no release is created.
|
||||
|
||||
### Step 8 — Ahead: compute and confirm
|
||||
|
||||
If `$CHANGELOG_VERSION` > `$RELEASE_VERSION`, compute:
|
||||
|
||||
- `tag = "v$CHANGELOG_VERSION"`
|
||||
- `title = "v$CHANGELOG_VERSION"` (plan2code keeps the `v` prefix in release titles)
|
||||
- `notes` = the header line `# What's New 🎉`, then one blank line, then `$SECTION` verbatim (`$SECTION` already starts with the `## vX.Y.Z` heading). Build this as a real multi-line string with **actual newlines** — the `\n\n` shorthand shown elsewhere means "a blank line," never the literal two-character sequence `\` + `n`. Getting this wrong would run the header and the first CHANGELOG heading together with a stray `\n\n` in the published body.
|
||||
|
||||
Present all three to the user and wait for an explicit answer before any write. Offer the optional decorative title suffix — a plain `vX.Y.Z` title is the default, but a release may append one (e.g. `v1.14.0 - 🔍 Review workflow`):
|
||||
|
||||
> 🚀 [Publish Plan2Code Release]
|
||||
>
|
||||
> CHANGELOG is ahead of the latest published release:
|
||||
> - **Current release:** $RELEASE_VERSION
|
||||
> - **CHANGELOG top version:** $CHANGELOG_VERSION
|
||||
> - **version.json releaseDate:** $RELEASE_DATE (informational — read from `version.json`)
|
||||
>
|
||||
> Proposed release:
|
||||
> - **Tag:** $tag
|
||||
> - **Title:** $title
|
||||
> - **Notes:**
|
||||
> ```
|
||||
> $notes
|
||||
> ```
|
||||
>
|
||||
> Publish this release? Reply **yes** to publish as-is, **no** to cancel, or provide a decorative suffix to append to the title (e.g. `⇢ 🎆 Feature Name` or `- 🔍 Feature Name`).
|
||||
|
||||
If the user supplies a suffix, set `title = "v$CHANGELOG_VERSION " + <suffix>` (single space join) and proceed to publish. The tag and notes are unaffected by the suffix.
|
||||
|
||||
### Step 9 — Publish (on approval)
|
||||
|
||||
On approval, write `$notes` to a temp file — never pass multiline text inline via `--notes`, that regresses into a quoting bug — then create the release targeting `main`. Two requirements for the temp file: `$notes` must already hold **real newlines** (per Step 8) because `printf '%s'` / `WriteAllText` write it byte-for-byte — a literal `\n` in the string lands literally in the release body; and it MUST be **UTF-8** because the notes contain emoji (`🎉`, `🐛`, `✨`, `🔧`).
|
||||
|
||||
**bash (preferred in this environment):**
|
||||
|
||||
```bash
|
||||
NOTES_FILE=$(mktemp)
|
||||
printf '%s' "$notes" > "$NOTES_FILE"
|
||||
gh release create "$tag" --repo jparkerweb/plan2code --title "$title" --notes-file "$NOTES_FILE" --target main
|
||||
rm -f "$NOTES_FILE"
|
||||
```
|
||||
|
||||
**PowerShell:** do NOT use `Set-Content` — under Windows PowerShell 5.1 it writes ANSI/UTF-16 by default and mangles the emoji into `??`. Write UTF-8 **without BOM** (a BOM would leak into the release body):
|
||||
|
||||
```powershell
|
||||
$NotesFile = [System.IO.Path]::GetTempFileName()
|
||||
[System.IO.File]::WriteAllText($NotesFile, $notes, [System.Text.UTF8Encoding]::new($false))
|
||||
gh release create "$tag" --repo jparkerweb/plan2code --title "$title" --notes-file "$NotesFile" --target main
|
||||
Remove-Item -Path $NotesFile
|
||||
```
|
||||
|
||||
Always delete the temp file afterward, regardless of whether `gh release create` succeeded or failed.
|
||||
|
||||
**Failure handling — already-exists classification:** if `gh release create` exits non-zero, inspect the error text.
|
||||
|
||||
- If and only if it contains the substring `already exists` (real output: `HTTP 422: Validation Failed` / `Release.tag_name already exists`), report this to the user as already published, not as a raw CLI error:
|
||||
|
||||
> This version ($CHANGELOG_VERSION) was already published as a release — nothing more to do.
|
||||
|
||||
- Every other failure (auth, network, permissions, etc.) must be surfaced to the user verbatim. Never silently reclassify a genuine failure as "already published."
|
||||
|
||||
### Step 10 — Verify
|
||||
|
||||
Confirm the release now exists and report its URL:
|
||||
|
||||
```bash
|
||||
gh release view "$tag" --repo jparkerweb/plan2code
|
||||
```
|
||||
|
||||
Report the release URL to the user.
|
||||
|
||||
## Rules
|
||||
|
||||
- **Repo-local only** — this skill is not part of the installed product; never add it to `install.js`, and never copy it to `~/.claude/skills/` (the uninstaller deletes `plan2code-*` entries there).
|
||||
- **Read-only on version files** — never modify `CHANGELOG.md`, `version.json`, or `package.json`; this skill only reads and compares them.
|
||||
- **Version-sync gate is hard** (Step 4) — if the three version sources disagree, stop and report; do not publish a release from an inconsistent repo.
|
||||
- **Never run a local `git tag` or `git push`** — tag creation is delegated entirely to `gh release create --target main`.
|
||||
- **Always use `--notes-file`**, never inline multiline `--notes`, and always write the notes file as UTF-8 (no BOM) so emoji survive.
|
||||
- **Always clean up the temp notes file**, even on a mid-run error.
|
||||
- **Always get explicit approval before any write** (Step 8) — no release is created without a yes (or a yes-with-suffix).
|
||||
- **Derive the current version from the highest published semver tag** (Step 5), never from GitHub's manually-pinnable "Latest" flag. On an empty or failed release list, treat it as "no prior release" (baseline `0.0.0`) — no error-text matching needed.
|
||||
- **On a `gh release create` failure** (Step 9), only reclassify as already-published when the error contains `already exists` — every other failure must be shown verbatim, never swallowed.
|
||||
- **Idempotent and safe to re-run** at any time — re-running after a successful publish hits the Step 7 no-op; re-running after a race-lost publish hits the Step 9 already-exists handling.
|
||||
File diff suppressed because one or more lines are too long
@@ -11,6 +11,7 @@ plan2code-metrics/package-lock.json
|
||||
.plan2code-metrics
|
||||
nul
|
||||
.cognition/
|
||||
handoffs/
|
||||
node_modules/
|
||||
package-lock.json
|
||||
SYNC.md
|
||||
@@ -2,6 +2,20 @@
|
||||
|
||||
All notable changes to Plan2Code will be documented in this file.
|
||||
|
||||
## v1.16.0
|
||||
|
||||
### ✨ Added
|
||||
|
||||
- **`/plan2code-handoff` skill** — compacts the current conversation into a self-contained handoff document (written to gitignored `./handoffs/<timestamp>-handoff.md`) so a fresh session or another agent can resume the work
|
||||
- Always captures a confirmed **Next task**: infers a candidate from context and requires the user to confirm or fill it in before the file is written
|
||||
- References plan specs, logs, and files by path rather than copying them; strips secrets; suggests follow-on skills and verification steps
|
||||
- Repo-safe: checks `git check-ignore` and warns (without silently editing `.gitignore`) when `handoffs/` isn't ignored in an arbitrary repo
|
||||
- **Repo-local release publisher skill** — new `/plan2code-publish` maintainer skill in `.claude/skills/` cuts a GitHub Release from the top `CHANGELOG.md` entry once `CHANGELOG.md`, `version.json`, and `package.json` agree and the version is ahead of the latest published release. Dev tooling only — deliberately excluded from `install.js`, never installed to `~/.claude/skills/`.
|
||||
|
||||
### 🐛 Fixed
|
||||
|
||||
- **Review workflow next-step suggestion made context-aware** — `/plan2code-review` Session End now reconciles three signals: session context (what preceded the review in the conversation), the user's review intent, and on-disk spec state gathered shell-agnostically — a file-search tool's empty result is never treated as proof that no specs exist. Suggestions render only at actual session end, cite their evidence and its source, and conflicting signals ask one targeted question instead of guessing.
|
||||
|
||||
## v1.15.4
|
||||
|
||||
### ✨ Added
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
| 2 | /plan2code-2-document | PLAN-DRAFT.md | overview.md + Phase files |
|
||||
| 3 | /plan2code-3-implement | overview.md | Implemented code |
|
||||
| 4 | /plan2code-4-finalize | overview.md | Archived specs |
|
||||
| handoff | /plan2code-handoff | Conversation | Self-contained handoff doc in handoffs/ |
|
||||
|
||||
## File Structure
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ A structured 4-step workflow for developing features and projects with AI assist
|
||||
| `/plan2code-2-document` | After planning, create implementation specs |
|
||||
| `/plan2code-3-implement` | Execute implementation (one phase per conversation) |
|
||||
| `/plan2code-4-finalize` | All phases complete, ready to archive |
|
||||
| `/plan2code-handoff` | Compact the conversation into a handoff doc for a fresh session |
|
||||
|
||||
**Key Rules:**
|
||||
- Start NEW conversation for each step (and each implementation phase)
|
||||
|
||||
+10
@@ -180,6 +180,14 @@ const SOURCE_PROMPTS = [
|
||||
name: 'finalize',
|
||||
displayName: 'Finalization Mode',
|
||||
description: 'Validate, summarize, and archive completed work'
|
||||
},
|
||||
{
|
||||
source: 'plan2code-handoff.md',
|
||||
stepNumber: 'handoff',
|
||||
name: 'handoff',
|
||||
displayName: 'Handoff Mode',
|
||||
description: 'Compact the conversation into a self-contained handoff document for a fresh session',
|
||||
isUtility: true
|
||||
}
|
||||
];
|
||||
|
||||
@@ -199,7 +207,9 @@ function generateSkillName(prompt) {
|
||||
// Helper function to generate step label for descriptions
|
||||
function generateStepLabel(prompt) {
|
||||
if (prompt.stepNumber === 'init') return 'Init';
|
||||
if (prompt.stepNumber === 'update') return 'Update';
|
||||
if (prompt.stepNumber === 'review') return 'Review';
|
||||
if (prompt.stepNumber === 'handoff') return 'Handoff';
|
||||
return `Step ${prompt.stepNumber}`;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "plan2code",
|
||||
"version": "1.15.4",
|
||||
"version": "1.16.0",
|
||||
"private": true,
|
||||
"bin": {
|
||||
"plan2code": "./install.js"
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
# plan2code-handoff
|
||||
|
||||
Turn everything useful in the current conversation into a single, self-contained
|
||||
handoff document that lets a *different* agent — a new session, a teammate's
|
||||
session, or a subagent — resume the work without re-reading this transcript.
|
||||
|
||||
The reader of this document starts with **zero context**. They can see the repo
|
||||
and can open files, but they cannot see this conversation. Write for them.
|
||||
|
||||
## The one hard rule: capture the next task, and confirm it with the user
|
||||
|
||||
Every handoff MUST end with a **Next task** that the incoming agent should start
|
||||
on. This is the single most important part of the document — a handoff with a
|
||||
vague or missing next step forces the reader to re-derive intent, which is
|
||||
exactly what this skill exists to prevent.
|
||||
|
||||
Determine it like this:
|
||||
|
||||
1. **Try to infer it** from the conversation — the open TODO, the failing test,
|
||||
the plan step you were mid-way through, the thing the user just asked for
|
||||
next. Look at what's actually unfinished, not just the last message.
|
||||
2. **Present it to the user for confirmation before writing the file.** If you
|
||||
inferred a candidate, show it and ask them to confirm or correct it. If you
|
||||
genuinely can't infer one, ask them to tell you what the next agent should do.
|
||||
Use `AskUserQuestion` (offer your inferred task as the recommended option) or
|
||||
a plain question — either is fine.
|
||||
3. **Do not write the document until the user has confirmed or supplied the next
|
||||
task.** This gate is mandatory even when your inference feels obviously
|
||||
correct. The user's answer is the source of truth; your inference is only a
|
||||
draft of it.
|
||||
|
||||
If the user passed a focus area as an argument, treat it as a strong signal for
|
||||
the next task (and shape the whole document around it), but still confirm.
|
||||
|
||||
## Where to write it
|
||||
|
||||
Save to `./handoffs/` at the repo root with a timestamped filename so it's
|
||||
discoverable but doesn't collide with earlier handoffs:
|
||||
|
||||
```
|
||||
./handoffs/<YYYY-MM-DD-HHmm>-handoff.md
|
||||
```
|
||||
|
||||
Get the timestamp from the shell rather than guessing — e.g. PowerShell
|
||||
`Get-Date -Format 'yyyy-MM-dd-HHmm'`. Create the `handoffs/` directory if it
|
||||
doesn't exist.
|
||||
|
||||
### Make sure you aren't leaking the file into version control
|
||||
|
||||
The handoff is working state for the next session, not a project artifact, so it
|
||||
should stay out of commits and PRs. Don't assume it will — this skill may run in
|
||||
any repo. Before (or right after) writing, check whether the path is ignored:
|
||||
|
||||
- Is this even a git repo? `git rev-parse --is-inside-work-tree` — if it errors,
|
||||
there's nothing to ignore; skip this and just tell the user where the file is.
|
||||
- Is the file ignored? `git check-ignore handoffs/` (exit 0 = ignored). This is
|
||||
the reliable check — a repo may ignore `handoffs/` via a global or nested
|
||||
`.gitignore`, so don't rely on grepping the root `.gitignore` alone.
|
||||
|
||||
If it is **not** ignored, do not silently modify the user's `.gitignore`. Tell
|
||||
them the file would be tracked by git and offer to add a `handoffs/` line to
|
||||
`.gitignore` — let them decide. Some users may want handoffs committed so
|
||||
teammates get them; that's a legitimate choice, so present it, don't force it.
|
||||
|
||||
## What to include
|
||||
|
||||
Keep it tight and high-signal. Prefer pointers over prose: this repo already
|
||||
records a lot (plan specs, the loop's NDJSON logs, git history, diffs), so
|
||||
**reference those by path or URL instead of copying them in**. The reader can
|
||||
open a file; they can't open your memory.
|
||||
|
||||
Use this structure:
|
||||
|
||||
```markdown
|
||||
# Handoff — <short title of the work>
|
||||
<!-- written <timestamp> -->
|
||||
|
||||
## Next task
|
||||
<the confirmed next task — concrete and actionable, e.g.
|
||||
"Implement Step 3 of specs/<name>.md: wire the aggregator into cli.ts, then
|
||||
run `npm run build` in plan2code-metrics/ and fix the two failing tests.">
|
||||
|
||||
## Goal / why
|
||||
<1–3 sentences: what the user is ultimately trying to achieve, so the reader
|
||||
can make good judgment calls the instructions don't cover.>
|
||||
|
||||
## Current state
|
||||
<Where things stand right now. What's done, what's in progress, what's broken.
|
||||
Name the branch. Point at the plan/spec file(s) by path rather than restating
|
||||
them. Note anything half-applied or left uncommitted.>
|
||||
|
||||
## Key files & pointers
|
||||
<Bulleted paths the reader will need, each with a one-line "why". Include plan
|
||||
specs, the files you were editing, relevant logs (e.g. .plan2code-loop NDJSON),
|
||||
and any PR/issue URLs.>
|
||||
|
||||
## Gotchas & decisions
|
||||
<Non-obvious things learned this session: a constraint (e.g. the 11k-char limit
|
||||
on src/plan2code-*.md), a decision made and why, a dead end already ruled out,
|
||||
a command that must be run a specific way. Save the reader from re-discovering
|
||||
these the hard way.>
|
||||
|
||||
## Suggested skills
|
||||
<Which skills the next agent should use, and when — e.g. sync-repo for syncing,
|
||||
a plan2code workflow phase, /code-review before finishing. Skip if none apply.>
|
||||
|
||||
## Verification
|
||||
<How the reader confirms their work: exact test/build commands, what "done"
|
||||
looks like.>
|
||||
```
|
||||
|
||||
Adapt the sections to the work — drop any that would be empty rather than
|
||||
padding them. **Next task** is the only section that is never optional.
|
||||
|
||||
## Strip sensitive data
|
||||
|
||||
Before writing, remove credentials, API tokens, passwords, and personal
|
||||
identifiers. If a secret is load-bearing for the next step, reference *where* it
|
||||
lives (env var name, secret manager entry) rather than its value.
|
||||
|
||||
## After writing
|
||||
|
||||
Tell the user the path you wrote to and give a one-line summary of the confirmed
|
||||
next task, so they know what the incoming agent will start on. Mention that a
|
||||
fresh session can be pointed at the file to resume the work.
|
||||
|
||||
If your ignore check above found the file is **not** gitignored (or the repo has
|
||||
no `.gitignore`, or it isn't a git repo at all), say so plainly here — e.g. "note:
|
||||
`handoffs/` isn't gitignored in this repo, so this file will show up in `git
|
||||
status` and could be committed" — and offer to add the ignore line. Never leave
|
||||
the user unaware that the handoff might ride along into a commit.
|
||||
+16
-8
@@ -141,7 +141,7 @@ Run every finding through the false-positive detection shortcuts before presenti
|
||||
|
||||
> **Totals:** X Critical · Y Warning · Z Suggestion
|
||||
|
||||
**Fix options:** Reply `H` (high-priority), `A` (all), or `S 1,3,5` (specific findings).
|
||||
**Fix options:** Reply `H` to fix Critical + Warning findings, `A` to fix all findings, or `S 1,3,5` to fix specific findings.
|
||||
|
||||
**Zero findings:** Skip table and fix options. Dimension Coverage justifies each clean dimension.
|
||||
|
||||
@@ -155,16 +155,24 @@ Run every finding through the false-positive detection shortcuts before presenti
|
||||
|
||||
## Session End
|
||||
|
||||
Render this section only when the session is over: fix options resolved (fixes applied and verified, or user declined) or the review had zero findings. Step 5 ends at fix options — stop there and wait.
|
||||
|
||||
Work summary — tell user: scope reviewed, findings count by severity (Critical/Warning/Suggestion), fixes applied, unresolved findings.
|
||||
|
||||
After approval, select template based on project state:
|
||||
**Next step** — suggest what genuinely helps next. Principles to reason from, not a lookup table — adapt; when a case doesn't fit cleanly, say what you verified and ask.
|
||||
|
||||
**Pre-condition check:** Before suggesting implement or finalize, verify that `overview.md` AND at least one `phase-*.md` file exist in the specs directory. If they do NOT exist, the document step has not been run yet.
|
||||
|
||||
- **Specs dir exists but NO overview.md / phase-*.md files:** "Next: generate implementation docs. NEW conversation: `/plan2code-2-document`"
|
||||
- **Specs + overview.md + phase files + more phases:** "Next: Phase X. NEW conversation: `/plan2code-3-implement`"
|
||||
- **Specs + overview.md + phase files + all complete:** "All complete! NEW conversation: `/plan2code-4-finalize`"
|
||||
- **Standalone:** "Review complete -- [summary]."
|
||||
- **Plan2Code Workflow Pipeline:** `/plan2code-1-plan` → `PLAN-*` files · `/plan2code-2-document` → `overview.md` + `phase-*.md` (the "spec docs") in `specs/<feature>/` · `/plan2code-3-implement` → checks off phase tasks, one phase per run · `/plan2code-4-finalize` → archives to `specs--completed/`.
|
||||
- **Find specs (any OS/shell):** `specs/` is gitignored, and search tools (Glob/Grep/project search) skip gitignored paths on many platforms — an empty search result is not evidence either way. Check with a terminal listing: `ls specs/<feature>/` (bash/zsh) · `Get-ChildItem specs/<feature>` (PowerShell) · `dir specs\<feature>` (cmd). Feature dir unknown? List `specs/` first. Command errors? Try another shell's form, then read the expected files directly — file reads see gitignored paths. Conclude "no specs" only after a terminal listing or a failed direct read.
|
||||
- **Reconcile three signals:** session context (what this conversation was doing — a fresh session may have none), user intent (what they asked reviewed), the disk check above. Disk wins on state; context wins on intent and on disk silence; no context → intent + disk decide.
|
||||
- **plan2code artifact reviewed (a plan, the spec docs, phases) — route on the reviewed feature's own `specs/<feature>/` state (another feature's specs prove nothing here), to the earliest unmet stage, suggesting only a step whose input exists:**
|
||||
- `PLAN-*` without `overview.md` → `/plan2code-2-document`
|
||||
- `overview.md` without `phase-*.md` → `/plan2code-2-document`
|
||||
- Unchecked `- [ ]` tasks in `phase-*.md` → `/plan2code-3-implement` (checkboxes are ground truth; flag overview conflicts)
|
||||
- All phase tasks checked → `/plan2code-4-finalize`
|
||||
- Archived spec → pipeline complete; summary only
|
||||
- **Anything else** (code/PRs, logs, docs, tickets, emails, a codebase): no pipeline step — close with the summary; add a next action only if the review makes one obvious and actionable.
|
||||
- **Gates:** unresolved Criticals → fixing them (H/A/S) is the next step. Signals the rules above can't reconcile, or multiple candidate specs → ask one targeted question.
|
||||
- **Output:** "Next (NEW conversation): `/plan2code-<step>` — [why + how you know]"; otherwise "Review complete -- [summary]."
|
||||
- **Commit** (code changes): `git add [files] && git commit -m "fix: [desc]" -m "<JIRA>" -m "AI Assisted"` -- derive JIRA from branch.
|
||||
|
||||
```
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Plan2Code",
|
||||
"version": "1.15.3",
|
||||
"version": "1.16.0",
|
||||
"description": "A structured 4-step workflow methodology for AI-assisted software development",
|
||||
"keywords": [
|
||||
"ai",
|
||||
@@ -17,7 +17,7 @@
|
||||
"url": "https://github.com/jparkerweb/plan2code"
|
||||
},
|
||||
"homepage": "https://plan2code.jparkerweb.com",
|
||||
"releaseDate": "2026-06-28",
|
||||
"releaseDate": "2026-07-20",
|
||||
"mode": "utility"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user