Skip to content

HEARTBEAT — frappe-stack

Stamped at every phase transition. Newest entry on top.


2026-05-05 — D-10: plugin-only refactor (drop apps/stack_core)

State: the plugin now uses Frappe's stock REST API. No custom Frappe app. Nothing to install on the Frappe site beyond what stock Frappe v15+ already ships.

Why

The original ask was "a Claude plugin that calls Frappe with an API key." stack_core was over-engineering for v0.1 — server-side enforcement of patterns the plugin already validates client-side, plus a parallel audit log when Frappe's built-in Activity Log already captures the same events.

What was removed

  • apps/stack_core/ — entire Frappe app (~30 files): 4 DocTypes, 6 API endpoints, 5 guardrail validators, 5 git-bridge modules, 5 test modules, hooks.py.
  • docs/operators/installing-stack-core.md.

What was reframed

  • All agents (engineer, deployer, reviewer, tester) now call POST /api/resource/<DocType> instead of stack_core.api.*.
  • All slash commands (init, build, pull, push, diff, promote, experiment) updated.
  • All skills with code examples updated.
  • All catalog pages (docs/skills.md, docs/commands.md, docs/hooks.md, docs/architecture.md).
  • Two hook scripts (coach_user_prompt, block_ignore_permissions) updated.
  • Builder Protocol files (PRD, SECURITY, CLAUDE, CONTRIBUTING) updated.
  • Operator runbook trimmed to just rotating-keys.md.

What stays the same

  • Skills, agents, slash commands, hooks (their roles).
  • A/B experiments, but built from stock primitives — Custom Field + Server Script + a regular Experiment Assignment DocType, created on demand via POST /api/resource.
  • Validators (schema, reserved-name, fieldtype whitelist, workflow shape) — same logic, runs client-side now.
  • Local audit log at .frappe-stack/audit.jsonl.
  • B+ hybrid sync model (D-01) and the /promote PR flow.

Architecture is now

  1. Claude Code on PM's machine (the plugin)
  2. Stock Frappe v15+ site (token auth, REST API)
  3. GitHub config repo (per-blueprint JSONs, PR-protected main)

Three commits delivered the refactor: 618c89d (delete + structural docs), d57bc6c (agents + commands), 4b6ed60 (skills + catalogs + hooks). This commit closes out the Builder Protocol files.


2026-05-05 — GitHub Pages site (MkDocs Material)

State: docs site config + GitHub Action landed. Pages will deploy automatically on push to main once Pages is enabled in the repo settings.

Done

  • mkdocs.yml — site config: name, description, repo URL, edit-on-GitHub, light/dark palette toggle, navigation tabs, Material icons, search with highlighting, code-block copy buttons, mermaid support.
  • requirements-docs.txt — pinned MkDocs Material 9.5.49 + plugins.
  • .github/workflows/docs.yml — checkout → install → stage root-level Builder Protocol files into docs/mkdocs buildactions/deploy-pages@v4. Triggered on push to main for docs/** / mkdocs.yml / Builder Protocol files / the workflow itself.
  • docs/README.mddocs/index.md rename (MkDocs landing-page convention).
  • CHANGELOG updated.

Manual step required (you, in GitHub UI)

  1. Go to https://github.com/dhwani-ris/frappe-stack/settings/pages
  2. Under Source, select GitHub Actions.
  3. Save.
  4. Push any commit to main (or run the workflow manually via Actions tab → "Deploy docs site" → Run workflow).
  5. Site lands at https://dhwani-ris.github.io/frappe-stack/.

Why this matters

External readers (potential contributors, operators evaluating the plugin, future-you on a phone during an incident) get a searchable, dark-mode-capable docs site instead of clicking through GitHub's plain markdown rendering. Reduces the activation cost of the project.

Crosses D-09 line slightly

D-09 deferred infra/ (Docker / CI / pre-commit). This adds a GitHub Action workflow, which is technically CI infrastructure. Treating Pages as docs publishing (separate from code CI) — the rule of thumb: anything that builds the source code or runs tests stays deferred; anything that publishes static content from existing markdown is fine.


2026-05-05 — Public-readiness pass + docs hub

State: repo prepared for going public. Documentation hub added; private-repo references removed; contributor surface added.

Done

  • docs/README.md — index with how-the-pieces-fit diagram + 5/30-min reading paths.
  • docs/skills.md — 17-skill catalog grouped by purpose (building / shipping / organizing / platform / meta).
  • docs/agents.md — 8-agent catalog with model rationale + pairing chart.
  • docs/commands.md — 9-command catalog with argument hints and typical-flow diagram.
  • docs/hooks.md — 8-hook catalog with lifecycle layout and layered-enforcement matrix.
  • docs/architecture.md — three-actor diagram, B+ sync model, end-to-end build + promote flows, DocType layout, layered enforcement, failure modes.
  • README.md — refreshed: install instructions, quick-links table, what's-in-the-box inventory. Replaced the Phase-0 placeholder framing.
  • CONTRIBUTING.md — how to set up dev environment, run tests, propose skills/agents/commands, conventional commits, security disclosure.
  • .github/ISSUE_TEMPLATE/ — bug, feature, skill proposal templates.
  • .github/PULL_REQUEST_TEMPLATE.md — PR template that surfaces reviewer/tester output and security checklist.
  • Removed prody-dris/mgrant-stack references from README.md + PRD.md (private repo; outsiders saw 404s). Replaced with a generic "internal reference" note where appropriate.
  • CHANGELOG updated.

Why this matters

Up to now, the only way to discover what the plugin shipped was to ls -R skills/ agents/ commands/. Reviewers, contributors, and anyone picking up the repo cold had no map. The docs hub makes the surface area inspectable in five minutes. The contributor templates signal "we accept PRs."


2026-05-03 — Prompt-coaching layer added

State: added a UserPromptSubmit hook that coaches PMs at typing time, before Claude sees the prompt.

Done

  • .claude-plugin/hook_scripts/coach_user_prompt.py — the hook script. Approves by default; blocks on PII / hard-delete / bypass-review intent; coaches on vague build intents, prod-write intents, permission bypass, elevated fieldtypes, schema renames, A/B without question, multi-blueprint without spec, integrations.
  • hooks/hooks.json — UserPromptSubmit matcher added.
  • skills/process/prompt-coaching/SKILL.md — reference doc explaining what the hook reacts to and how to tune.
  • CHANGELOG.md updated.

Why this matters

Skills only fire when the engineer agent loads them. The user's typed prompt happens before any agent. Without this hook, a vague PM ask reaches the model uncoached. The hook closes that gap — every free-text prompt is silently routed (or blocked, or nudged) before Claude commits to an approach.


2026-05-03 — Phases 1–9 artifacts complete (local only, not pushed)

Phase: 9 — Polish + docs State: all artifact work landed locally; awaiting smoke-tests in a real bench / clean Claude Code session

Done in one session (commits 3af316f → HEAD)

  • Phase 1.claude-plugin/plugin.json + marketplace.json + LICENSE + scaffolding.
  • Phase 2 + 7apps/stack_core/ Frappe support app: 4 DocTypes, 6 API endpoints, 5 guardrail validators, 5 git_bridge modules, 5 test modules. Hooks wired in hooks.py. ~40 files.
  • Phase 3 — 16 skills under skills/ (platform / building / process / builder-protocol).
  • Phase 4 — 8 agents under agents/ (engineer, reviewer, tester, deployer, analyst, migrator, documenter, orchestrator).
  • Phase 5 — 9 slash commands under commands/ (init, build, pull, push, diff, promote, experiment, review, ship).
  • Phase 6 — 7 safety hooks: hooks/hooks.json declaration + 6 Python scripts under .claude-plugin/hook_scripts/.
  • Phase 8 — A/B in workflows is integrated through Phases ⅔/5 (split-state validator, Experiment Assignment DocType, designing-experiments skill, /frappe-stack:experiment command).
  • Phase 9 — 4 PM walkthroughs + 2 operator runbooks under docs/. CHANGELOG.md.

Pending (cannot be done from inside this session)

  • Plugin install smoke-test — run in a clean Claude Code session:
    /plugin marketplace add https://github.com/dhwani-ris/frappe-stack.git
    /plugin install frappe-stack@frappe-stack
    
    Confirm both succeed; spot-check that /frappe-stack:init, :build, :pull appear.
  • Bench test executionbench --site test_site run-tests --app stack_core --coverage. Tests written but not executed; need a Frappe v15+ environment.
  • Pre-commit / CI / Docker — D-09 keeps infra/ deferred to post-v0.1. Port from dhwani-ris/frappe_dhwani_base when reopened.
  • Push to origin — user instruction "complete it locally first" — local commits only, awaiting explicit push.

File count summary

Layer Files
Builder Protocol docs 6 (README, PRD, PLAN, SECURITY, CLAUDE, HEARTBEAT) + CHANGELOG
Plugin scaffolding 4 (.claude-plugin: plugin.json, marketplace.json, README.md; LICENSE)
stack_core app ~30 (controllers, JSONs, validators, git bridge, tests)
Skills 16
Agents 8
Commands 9
Hooks (declaration + scripts) 7
docs/ 7 (4 walkthroughs + 2 operator runbooks + CHANGELOG cross-ref)
Total ~87

Next checkpoint

  • User confirms whether to push.
  • User runs the install smoke-test (or grants bench access for me to run it).
  • Once green: tag v0.1.0 via /frappe-stack:ship.

2026-05-03 — Phase 1 artifacts complete

Phase: 1 — Plugin manifest + Builder Protocol scaffolding State: artifacts written; smoke-test pending

Done

  • D-02..D-08 confirmed (all defaults locked).
  • D-02 amended: namespace auto-derives from manifest name field. Original /fs- proposal isn't supported by Claude Code's plugin schema; commands now invoke as /frappe-stack:<verb>.
  • .claude-plugin/plugin.json written (minimal valid manifest, version: 0.1.0).
  • .claude-plugin/marketplace.json written (single-plugin self-marketplace pattern, source: "./").
  • .claude-plugin/README.md written (install + namespace docs).
  • LICENSE (MIT) added.
  • Stub directories committed: skills/, agents/, commands/, hooks/, apps/stack_core/ (each with .gitkeep).

Pending checkpoint

  • Smoke-test: in a clean Claude Code session, run /plugin marketplace add https://github.com/dhwani-ris/frappe-stack.git then /plugin install frappe-stack@frappe-stack — confirm install succeeds with no errors. (Cannot run from inside Claude Code; needs manual operator step.)

Next

Phase 2 — stack_core Frappe support app. DocTypes, API endpoints, guardrail validators, tests. Per PLAN.md §3, blocked only on a bench environment to scaffold against; can write the DocType JSON specs and validator code without bench, but cannot run tests until a Frappe v15+ site is available.


2026-05-01 — D-01 confirmed

Decision: D-01 (sync direction) = B+ hybrid. Staging is interactive (PM API writes allowed); production is git-only (PR-merge → bench migrate). Phase 7 (git roundtrip) and Phase 5 (/fs-promote) build against this.

Open: D-02..D-08 still proposed.


2026-05-01 — Phase 0 opened

Phase: 0 — Planning & alignment State: in progress Owner: TBD (awaiting product sign-off)

Done

  • Initial commit: README.md, PRD.md, PLAN.md, SECURITY.md, CLAUDE.md, HEARTBEAT.md, .gitignore.
  • Research complete:
  • mgrant-stack pattern documented (Claude Code plugin, not a Frappe app).
  • Frappe ecosystem prior art surveyed (awesome-frappe, frappe_dhwani_base, sunandan89/mgrant-frappe-patterns).
  • Frappe issue #34915 + #36398 (fixture sync gaps) noted in PLAN.md §12 Risks.
  • No existing GitOps tool for Frappe found — confirms this is novel.
  • No existing A/B in Frappe Workflow found — confirms this is novel.

Blocked / pending

  • D-01 to D-08 in PLAN.md §0 — all proposed, none confirmed by product yet.
  • mgrant-stack collaborator access — work continues from public README only until granted.
  • stack_core API key strategy — placeholder; needs IT/secrets-manager decision before Phase 2.

Next checkpoint

Close Phase 0 by getting D-01..D-08 confirmed (or amended) by product owner. Then begin Phase 1 (plugin manifest + Builder Protocol scaffolding).

Notes for next session

  • The infra/ directory is deferred per stakeholder direction (D-09 confirmed). Pre-commit hooks, Docker, CI workflows all wait until post-v0.1.
  • frappe_dhwani_base already has the pre-commit / CI setup we want — port from there when infra/ reopens, don't write from scratch.
  • The cloned upstream dhwani-ris/frappe-stack was empty — this commit initializes it.