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
3 changes: 2 additions & 1 deletion docs/commands/add.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ pharn add # interactive module picker
1. Reads `pharn.config.json`. If none exists, exits with a hint to run `pharn init` first.
2. Fetches `manifest.json` to list available modules.
3. Resolves the **union** of already-installed modules plus the new one, so any dependencies of the new module are pulled in too.
4. Clones `pharn-dev/pharn-oss`, copies the resolved modules' `installs` into `.claude/`, and updates `pharn.config.json` (`modules`, `skillsVersion`, `commit`).
4. **Checks prerequisites** for the newly-introduced modules: any package a module declares (in the manifest's `prerequisites`) must already be in your `package.json`. This is the same gate as [`init`](init.md) — e.g. `pharn add pharn-stack-nextjs` requires `next` — so a pack can't bypass it by being added after init. Missing prerequisites print their `reason` and exit **1** (see [Troubleshooting](../troubleshooting.md#stack-pack-prerequisite-missing)).
5. Clones `pharn-dev/pharn-oss`, copies the resolved modules' `installs` into `.claude/`, and updates `pharn.config.json` (`modules`, `skillsVersion`, `commit`).

`CONSTITUTION.md` is **not** touched — `add` never changes your constitution.

Expand Down
50 changes: 34 additions & 16 deletions docs/commands/init.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,26 @@ sequenceDiagram
participant Modules as module_select
participant Stack as stackpack_select
participant Const as constitution_select
participant Tenant as multitenant_select
participant Summary
participant Install

User->>CLI: pharn init
CLI->>Prereqs: Next.js + git
CLI->>Prereqs: git (.git present)
Prereqs-->>CLI: ok or exit
CLI->>Fresh: commit / file heuristics
CLI->>Fresh: commit + tracked-file heuristics
Fresh-->>User: optional warnings
CLI->>Catalog: fetch manifest.json
loop Until install or cancel
CLI->>Modules: optional modules multiselect
CLI->>Stack: stack pack (single, or none)
CLI->>Const: privacy posture → constitution
CLI->>Tenant: multi-tenant SaaS? (gates Principle 2)
CLI->>Summary: resolved module set + versions
Summary-->>User: install / back / cancel
end
CLI->>Prereqs: stack-pack package prerequisites
Prereqs-->>CLI: ok or exit
CLI->>Install: clone repo, copy modules, write config
Install-->>User: next steps
```
Expand All @@ -44,12 +48,19 @@ sequenceDiagram

## schemaVersion 2 wizard

When the fetched `manifest.json` is `schemaVersion 2`, `init` first asks how to configure your stack:
When the fetched `manifest.json` is `schemaVersion 2`, `init` first reads your `package.json` and pre-fills the wizard from the manifest's detection metadata:

- **Stack pack** — preselected when every package a pack lists in `prerequisites` is present in `dependencies`/`devDependencies` (e.g. `next` → `pharn-stack-nextjs`); otherwise **None**.
- **Per-technology answers** — each question's answer is preselected when one of an option's `detect` packages is present (e.g. `drizzle-orm` → Drizzle, `@supabase/supabase-js` → Supabase). `(coming soon)` options are never auto-selected.

Detected values are shown in a "Detected from package.json" note; you can override every choice, and with no matches the wizard falls back to defaults / None.

`init` then asks how to configure your stack:

- **Default** — every per-technology answer is taken from `manifest.wizard.defaults`; no per-tech questions are asked.
- **Custom** — each wizard section (database, ORM, auth, …) is rendered as a single-select. Options are hidden, relabeled, or whole questions skipped based on your earlier answers (the manifest's `rules`); `(coming soon)` options are shown but not selectable; soft warnings confirm risky combinations.
- **Default** — every per-technology answer is taken from `manifest.wizard.defaults`, overlaid with any detected answers (detection wins; undetected questions keep their default); the manifest's `hide`/`hideQuestion` rules are then applied so the result matches what Custom mode would produce with every default accepted (a question a rule hides is recorded as `skip`, never installed). No per-tech questions are asked.
- **Custom** — each wizard section (database, ORM, auth, …) is rendered as a single-select with detected answers pre-checked. Options are hidden, relabeled, or whole questions skipped based on your earlier answers (the manifest's `rules`); `(coming soon)` options are shown but not selectable; soft warnings confirm risky combinations.

After the stack questions it continues with the methodology multiselect (which excludes the `pharn-skills-*` category modules), stack pack, and constitution as below, then a **vendor-skills consent** step (records consent for vendor official skills; external fetch is [Coming soon](../roadmap.md)). The summary additionally lists the per-technology skills, and install copies only those skill folders into `.claude/skills/`. Your answers and installed skills are written to `pharn.config.json` (`stackAnswers`, `installedSkills`, `vendorSkills`).
After the stack questions it continues with the methodology multiselect (which excludes the `pharn-skills-*` category modules), stack pack, constitution, and the **multi-tenant SaaS** flag as below, then a **vendor-skills consent** step (records consent for vendor official skills). On install, consented skills with a known source are fetched automatically from the vendor's registry into `.claude/skills/`; those without a source are flagged **(manual install)**, and any single fetch failure is non-fatal. The summary additionally lists the per-technology skills, and install copies only those skill folders into `.claude/skills/`. Your answers and installed skills are written to `pharn.config.json` (`stackAnswers`, `installedSkills`, `vendorSkills`).

## Steps

Expand All @@ -61,18 +72,18 @@ Shows the PHARN logo and CLI version.

Hard requirements. See [Getting started](../getting-started.md#prerequisites).

- Next.js in `package.json`
- `.git` present
- **`.git` present** — checked up front, before the wizard (universal, framework-agnostic).
- **Stack-pack packages** — after you pick a stack pack, every package it declares in the manifest's `prerequisites` must be in `package.json` (`dependencies`/`devDependencies`). Validated just before install, only for the pack you chose: **None** or a non-Next pack needs no framework package, while `pharn-stack-nextjs` requires `next`. The failure message is the manifest's own `reason`.

### 3. Fresh check

Soft warnings based on git history and file layout. Thresholds:
Soft warnings based on git signals only (framework-neutral). Thresholds:

| Condition | Message intent |
| --------- | -------------- |
| `git rev-list --count HEAD` >= 6 | Significant history (only this warning) |
| commit count 2–5 | Existing commits; may conflict with structure |
| 0–1 commits and > 3 custom root/app files | Project already customized |
| 0–1 commits and `git ls-files` > 40 | Populated repo, not a fresh scaffold |

Default for "Continue anyway?" is **no** (false).

Expand All @@ -86,7 +97,7 @@ A multiselect of **optional** modules (required modules and stack-pack bases are

### 6. Stack pack select

A single choice among the available stack packs (currently `pharn-stack-nextjs`), or **None**. Stack packs are mutually exclusive; the chosen pack's dependencies (e.g. the React base) are pulled in automatically.
A single choice among the available stack packs (currently `pharn-stack-nextjs`), or **None**. The initial selection is the pack detected from `package.json` (see the wizard section above), or **None** when nothing matches. Stack packs are mutually exclusive; the chosen pack's dependencies (e.g. the React base) are pulled in automatically.

### 7. Privacy posture / constitution

Expand All @@ -98,26 +109,33 @@ Maps your answer to a constitution variant shipped in `pharn-core/templates/cons
| Standard SaaS with user data | `standard` | 1–4 |
| Internal tools / B2B, no end-user PII | `minimal` | 2–4 |

### 8. Summary
### 8. Multi-tenant SaaS

"Is this a multi-tenant SaaS?" — recorded as `isMultiTenant` in `pharn.config.json` (default **Yes**). It gates **Principle 2 (Multi-Tenant Isolation)** in the installed constitution:

- **Yes** (default) — the chosen constitution variant is installed verbatim, including Principle 2.
- **No** — Principle 2 is stripped from the copied `CONSTITUTION.md`: its `## Principle 2` section is removed and `2` is dropped from the `principles_included` frontmatter, so a non-SaaS project is not blocked by a principle that does not apply. Every other principle and the file's structure are unchanged.

### 9. Summary

Displays the **resolved** module set (your selections plus all transitive dependencies, with versions), the skills version, and the constitution variant. Then:
Displays the **resolved** module set (your selections plus all transitive dependencies, with versions), the skills version, the constitution variant, and whether the project is a multi-tenant SaaS. Then:

| Action | Result |
| ------ | ------ |
| Yes, install | Clone the repo and install |
| Go back and change something | Re-run the selection steps, keeping your previous answers |
| Cancel | Exit 0; nothing written |

### 9. Install
### 10. Install

| Action | Behavior |
| ------ | -------- |
| Clone `pharn-dev/pharn-oss` | Whole repo into a temp dir (via degit) |
| Resolve modules | From the cloned `manifest.json` — dependencies + exclusivity |
| Copy modules | Each module's `installs` map merged into `.claude/` |
| Materialize core | `memory-bank/` and the chosen `CONSTITUTION.md` |
| Materialize core | `memory-bank/` and the chosen `CONSTITUTION.md` (Principle 2 stripped when not a multi-tenant SaaS) |
| Pin commit SHA | Best-effort via the GitHub API (null if unavailable) |
| Write `pharn.config.json` | `skillsVersion`, `commit`, `modules`, `constitution` |
| Write `pharn.config.json` | `skillsVersion`, `commit`, `modules`, `constitution`, `isMultiTenant` |

Overwrite prompt if `pharn.config.json` already exists (default: do not overwrite).

Expand Down
30 changes: 16 additions & 14 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
# Getting started

PHARN does not create a Next.js app from scratch. You scaffold with `create-next-app`, initialize git, then run PHARN in that directory.
PHARN does not scaffold your app. You create your project (e.g. with `create-next-app`), initialize git, then run PHARN in that directory.

## Prerequisites

| Requirement | How PHARN checks |
| ----------- | ---------------- |
| Next.js | `next` in `package.json` `dependencies` or `devDependencies` |
| Git | `.git` directory exists in the project root |
| Requirement | How PHARN checks | When |
| ----------- | ---------------- | ---- |
| Git | A `.git` directory exists in the project root | Always — checked up front, before the wizard |
| Stack-pack packages | Every package a selected stack pack declares (via the manifest's `prerequisites`) is in `package.json` `dependencies` or `devDependencies` | Only when you pick a pack that declares one — e.g. `pharn-stack-nextjs` requires `next` |

If either check fails, the CLI prints fix instructions and exits. See [Troubleshooting](troubleshooting.md).
`.git` is required for every install. Package prerequisites are **conditional on your stack-pack choice**: selecting **None** (or a pack with no prerequisites) installs without any framework package. If a check fails, the CLI prints the stack pack's own fix instructions and exits. See [Troubleshooting](troubleshooting.md).

PHARN works best on **fresh** projects. The wizard may warn when:
PHARN works best on **fresh** projects. The wizard may warn (framework-neutral, git-based) when:

- The repo has **6 or more** commits — checked first; repos with 6+ commits do not also see the 2+ warning
- The repo has **2–5** commits (designed for fresh scaffolds)
- There are **0–1** commits (a fresh scaffold; `create-next-app` makes one initial commit) but more than **3** custom files outside known Next.js paths
- The repo has **2–5** commits
- There are **0–1** commits but more than **40** tracked files (`git ls-files`) — a populated repo rather than a fresh scaffold

You can continue after any warning by confirming.

Expand Down Expand Up @@ -47,17 +47,19 @@ The wizard adapts to the manifest the CLI fetches. Newer manifests (`schemaVersi

### Stack mode (schemaVersion 2)

First you choose a mode:
First the CLI reads your `package.json` and pre-fills the wizard from the manifest's detection metadata — the stack pack (when a pack's `prerequisites` are all present, e.g. `next` → `pharn-stack-nextjs`) and each technology answer (when an option's `detect` package is present, e.g. `drizzle-orm` → Drizzle). What it found is shown in a note; you can override anything, and any question with no match keeps its normal default (the recommended value in Default mode, or the option marked default in Custom mode).

- **Default** — takes the recommended stack straight from the manifest and asks **no** per-technology questions.
- **Custom** — walks each section (database, ORM, auth, email, payments, …). Options that don't apply are hidden based on earlier answers, some options are relabeled for context, and anything marked **(coming soon)** is shown but not selectable.
Then you choose a mode:

- **Default** — takes the recommended stack from the manifest, overlaid with any detected answers (detection wins; undetected questions keep the recommended default), and asks **no** per-technology questions.
- **Custom** — walks each section (database, ORM, auth, email, payments, …) with detected answers pre-selected. Options that don't apply are hidden based on earlier answers, some options are relabeled for context, and anything marked **(coming soon)** is shown but not selectable.

Then, regardless of mode, the wizard asks:

1. **Methodology modules** — a multiselect of optional modules (`pharn-pipeline`, `pharn-review`, `pharn-audits`). `pharn-core` is always included.
2. **Stack pack** — a single choice (`pharn-stack-nextjs`, or none). The stack pack pulls in its React base automatically.
2. **Stack pack** — a single choice (`pharn-stack-nextjs`, or none), pre-selected from what was detected. The stack pack pulls in its React base automatically.
3. **Privacy posture** — picks your constitution variant (`gdpr-strict`, `standard`, or `minimal`).
4. **Vendor skills** — for technologies whose skill is published by the vendor (e.g. Supabase), the wizard records your consent to use it. Automatic fetching of those official skills is **Coming soon** ([roadmap](roadmap.md)); for now your choice is recorded in `pharn.config.json` and you install them by hand.
4. **Vendor skills** — for technologies whose skill is published by the vendor (e.g. Supabase), the wizard records your consent to use it. On install, any consented skill with a known source is fetched automatically from the vendor's registry into `.claude/skills/`; a vendor with no known source yet is shown as **(manual install)** and recorded in `pharn.config.json` for you to install by hand. A vendor fetch failure is non-fatal — the rest of the install still completes.

For each answered technology, the CLI copies only the matching skill folder into `.claude/skills/<skill>/` — never the sibling options you didn't pick.

Expand Down
4 changes: 3 additions & 1 deletion docs/reference/pharn-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ PHARN skills in your project read this file at runtime (e.g. to discover the ins
| `repo` | string | Source repo (`pharn-dev/pharn-oss`) |
| `commit` | string \| null | Pinned commit SHA of the install; `null` if the GitHub API was unavailable |
| `constitution` | string | Chosen variant: `gdpr-strict`, `standard`, or `minimal` |
| `isMultiTenant` | boolean | Whether the project is a multi-tenant SaaS. Written on every fresh install (absent on legacy installs, where it reads as `true`). When `false`, **Principle 2 (Multi-Tenant Isolation)** was stripped from the installed `CONSTITUTION.md` |
| `modules` | array | Installed modules (resolved, incl. dependencies), each `{ name, version }` |
| `installedAt` | string | ISO timestamp of the install / last update |
| `stackAnswers` | object | _schemaVersion 2 only._ Wizard answers, `questionId → value` (including `"skip"`) |
| `installedSkills` | array | _schemaVersion 2 only._ Per-technology skills copied into `.claude/skills/`, each `{ skill, from }` (`from` is the repo-relative source path) |
| `vendorSkills` | array | _schemaVersion 2 only._ Vendor official skills you consented to (external fetch is [Coming soon](../roadmap.md)) |
| `vendorSkills` | array | _schemaVersion 2 only._ Names of the vendor official skills you consented to. At `init`, any with a known source are fetched automatically from the vendor's registry; only the names are stored here |

The three `schemaVersion 2` fields are **additive** — installs against an older (`schemaVersion 1`) manifest omit them entirely, and existing configs stay valid.

Expand All @@ -30,6 +31,7 @@ The three `schemaVersion 2` fields are **additive** — installs against an olde
"repo": "pharn-dev/pharn-oss",
"commit": "daa06788…",
"constitution": "standard",
"isMultiTenant": true,
"modules": [
{ "name": "pharn-core", "version": "0.2.0" },
{ "name": "pharn-stack-react", "version": "0.1.2" },
Expand Down
3 changes: 2 additions & 1 deletion docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ What PHARN CLI does today versus what is planned.
| `pharn update` — refresh installed modules to the latest version | Shipped |
| `pharn list` — show installed + available modules/skills (read-only, `--json`) | Shipped |
| `pharn status` — read-only version + local-drift report (modified/missing PHARN-owned files; `--strict`, `--no-drift`) | Shipped |
| Vendor official-skill fetching — `init` auto-fetches consented vendor skills (e.g. Supabase) from their declared `source` into `.claude/skills/`, degrading to manual install where no source is known | Shipped |

## Planned

| Capability | Description |
| ---------- | ----------- |
| Vendor official-skill fetching | `init` records consent for vendor skills (e.g. Supabase) today; automatic fetching of those official skills from the vendor registry, with SHA pinning, is not built yet |
| Vendor skill SHA pinning | Vendor fetches are by `source` reference today; pinning each fetched vendor skill to a commit SHA is not built yet |
| Stack scaffolding | Install npm packages / generate app code from the stack pack |
| Additional stack packs | Beyond `pharn-stack-nextjs` |
| Migration for existing projects | Onboard repos with significant git history (today the CLI only warns) |
Expand Down
Loading