@rijalpermana/spec-forge 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/cli.js +32 -5
- package/package.json +1 -1
- package/templates/rules.md +71 -0
package/README.md
CHANGED
|
@@ -63,6 +63,7 @@ forge --version
|
|
|
63
63
|
cd your-project
|
|
64
64
|
forge init # scaffolds specs/ + AI bridge (defaults to Claude Code)
|
|
65
65
|
forge scan # (optional) inventory existing code -> specs/CODEBASE.md
|
|
66
|
+
forge rules # (optional) scaffold specs/RULES.md — project conventions
|
|
66
67
|
forge smelt btn-fraud-check # interactive Q&A -> brief.md + prd.md stub
|
|
67
68
|
|
|
68
69
|
# draft prd.md by hand, or with your AI tool, using brief.md as grounding
|
|
@@ -127,6 +128,7 @@ the writing.
|
|
|
127
128
|
| `forge init [--target <t>]` | — | `specs/`, `specs/INDEX.md`, AI bridge files | Yes — bridge files regenerate freely |
|
|
128
129
|
| `forge bridge <target>` | — | AI bridge files for `<target>` | Yes — always regenerates |
|
|
129
130
|
| `forge scan [--depth <n>]` | — | `specs/CODEBASE.md` (stack, file stats, existing schema/API files, directory tree) | Yes — refreshes on every run |
|
|
131
|
+
| `forge rules` | — | `specs/RULES.md` (project conventions the AI grounds all drafting in) | Yes — refuses if `RULES.md` exists |
|
|
130
132
|
| `forge smelt <feature>` | — | `brief.md`, `prd.md` (stub), `INDEX.md` entry (`draft`) | Yes — refuses if `brief.md` exists |
|
|
131
133
|
| `forge schema <feature>` | `prd.md` | `schema.dbml` (stub) | Yes |
|
|
132
134
|
| `forge contract <feature>` | `prd.md` | `api-contract.md` (stub) | Yes |
|
|
@@ -141,6 +143,7 @@ your-project/
|
|
|
141
143
|
├── specs/
|
|
142
144
|
│ ├── INDEX.md # creation order, status, dependencies across all features
|
|
143
145
|
│ ├── CODEBASE.md # (optional) forge scan output: existing project inventory
|
|
146
|
+
│ ├── RULES.md # (optional) forge rules output: project conventions the AI follows
|
|
144
147
|
│ └── <feature-name>/
|
|
145
148
|
│ ├── brief.md # smelt Q&A capture
|
|
146
149
|
│ ├── prd.md # goal, actors, user stories, business rules, out-of-scope
|
package/dist/cli.js
CHANGED
|
@@ -6821,6 +6821,7 @@ function featureDir(feature, cwd = process.cwd()) {
|
|
|
6821
6821
|
}
|
|
6822
6822
|
|
|
6823
6823
|
// src/lib/command-specs.ts
|
|
6824
|
+
var GROUND_IN_RULES = "If specs/RULES.md exists, read it first and follow those project conventions — " + "they override any defaults described below. ";
|
|
6824
6825
|
var COMMAND_SPECS = [
|
|
6825
6826
|
{
|
|
6826
6827
|
name: "scan",
|
|
@@ -6830,13 +6831,21 @@ var COMMAND_SPECS = [
|
|
|
6830
6831
|
readOnly: true,
|
|
6831
6832
|
instructions: "This command scans the existing project deterministically (no code is " + "interpreted) and writes specs/CODEBASE.md — a factual inventory of the detected " + "stack, file statistics, existing schema and API files, and the directory tree. " + "After it runs, read specs/CODEBASE.md and use it as grounding: when drafting " + "schemas, contracts, or tasks later, reuse the conventions, entities, and files " + "that already exist here instead of inventing new ones. Don't echo the whole file " + "back — just confirm the stack and the spec-relevant files you found."
|
|
6832
6833
|
},
|
|
6834
|
+
{
|
|
6835
|
+
name: "rules",
|
|
6836
|
+
argumentHint: "(no arguments — scaffolds specs/RULES.md)",
|
|
6837
|
+
description: "Scaffold specs/RULES.md — project conventions the AI follows when drafting",
|
|
6838
|
+
requiresPrd: false,
|
|
6839
|
+
readOnly: false,
|
|
6840
|
+
instructions: "This command scaffolds specs/RULES.md — a project-level conventions file " + "(tech stack, naming, module structure, API/response format, data, validation, " + "security, testing, docs, tooling). After it runs, help the user fill the [TODO] " + "sections: infer what you can from specs/CODEBASE.md and the existing code, and " + "ask about anything you can't. Keep each rule factual and enforceable. Once " + "filled, every other forge drafting command must obey these rules."
|
|
6841
|
+
},
|
|
6833
6842
|
{
|
|
6834
6843
|
name: "smelt",
|
|
6835
6844
|
argumentHint: "[feature-name]",
|
|
6836
6845
|
description: "Extract raw requirements into a grounding brief, then draft the PRD",
|
|
6837
6846
|
requiresPrd: false,
|
|
6838
6847
|
readOnly: false,
|
|
6839
|
-
instructions: "This command is interactive — it prompts for goal, actors, constraints, and " + "out-of-scope items in the terminal. Once it completes, read {{brief}} and " + "draft {{prd}} following the structure already stubbed there. Do not invent " + "scope, actors, or rules that aren't grounded in the brief — if something's " + "missing, ask what to clarify instead of guessing."
|
|
6848
|
+
instructions: GROUND_IN_RULES + "This command is interactive — it prompts for goal, actors, constraints, and " + "out-of-scope items in the terminal. Once it completes, read {{brief}} and " + "draft {{prd}} following the structure already stubbed there. Do not invent " + "scope, actors, or rules that aren't grounded in the brief — if something's " + "missing, ask what to clarify instead of guessing."
|
|
6840
6849
|
},
|
|
6841
6850
|
{
|
|
6842
6851
|
name: "schema",
|
|
@@ -6844,7 +6853,7 @@ var COMMAND_SPECS = [
|
|
|
6844
6853
|
description: "Scaffold schema.dbml, then draft it from prd.md",
|
|
6845
6854
|
requiresPrd: true,
|
|
6846
6855
|
readOnly: false,
|
|
6847
|
-
instructions: "Read {{prd}} and fill {{schema}} with tables, columns, and relationships that " + "are directly traceable to entities, actors, or business rules in the PRD. " + "Follow existing DBML conventions in this repo (multi-tenant RLS pattern, " + "tenant_id scoping, Drizzle-compatible types) if a reference schema exists " + "elsewhere in the project."
|
|
6856
|
+
instructions: GROUND_IN_RULES + "Read {{prd}} and fill {{schema}} with tables, columns, and relationships that " + "are directly traceable to entities, actors, or business rules in the PRD. " + "Follow existing DBML conventions in this repo (multi-tenant RLS pattern, " + "tenant_id scoping, Drizzle-compatible types) if a reference schema exists " + "elsewhere in the project."
|
|
6848
6857
|
},
|
|
6849
6858
|
{
|
|
6850
6859
|
name: "contract",
|
|
@@ -6852,7 +6861,7 @@ var COMMAND_SPECS = [
|
|
|
6852
6861
|
description: "Scaffold api-contract.md, then draft it from prd.md",
|
|
6853
6862
|
requiresPrd: true,
|
|
6854
6863
|
readOnly: false,
|
|
6855
|
-
instructions: "Read {{prd}} and fill {{contract}}. Use exactly this format per endpoint, " + `one block per endpoint, no deviation:
|
|
6864
|
+
instructions: GROUND_IN_RULES + "Read {{prd}} and fill {{contract}}. Use exactly this format per endpoint, " + `one block per endpoint, no deviation:
|
|
6856
6865
|
|
|
6857
6866
|
` + `Title: [short name]
|
|
6858
6867
|
` + `endpoint: [METHOD] [path]
|
|
@@ -6866,7 +6875,7 @@ var COMMAND_SPECS = [
|
|
|
6866
6875
|
description: "Scaffold tasks.md, then draft it from prd.md",
|
|
6867
6876
|
requiresPrd: true,
|
|
6868
6877
|
readOnly: false,
|
|
6869
|
-
instructions: "Read {{prd}} and {{schema}} (if present), then fill {{tasks}}. Sequence " + "strictly: data/schema tasks before logic tasks before UI tasks. Call out any " + "dependency inversion explicitly rather than silently reordering — if the PRD " + "implies model or logic work before its data source exists, flag it instead of " + "hiding it."
|
|
6878
|
+
instructions: GROUND_IN_RULES + "Read {{prd}} and {{schema}} (if present), then fill {{tasks}}. Sequence " + "strictly: data/schema tasks before logic tasks before UI tasks. Call out any " + "dependency inversion explicitly rather than silently reordering — if the PRD " + "implies model or logic work before its data source exists, flag it instead of " + "hiding it."
|
|
6870
6879
|
},
|
|
6871
6880
|
{
|
|
6872
6881
|
name: "testcase",
|
|
@@ -6874,7 +6883,7 @@ var COMMAND_SPECS = [
|
|
|
6874
6883
|
description: "Scaffold testcases.md, then draft it from prd.md",
|
|
6875
6884
|
requiresPrd: true,
|
|
6876
6885
|
readOnly: false,
|
|
6877
|
-
instructions: "Read {{prd}} and fill {{testcases}}. Use exactly this table format, one row " + `per scenario, do not change columns:
|
|
6886
|
+
instructions: GROUND_IN_RULES + "Read {{prd}} and fill {{testcases}}. Use exactly this table format, one row " + `per scenario, do not change columns:
|
|
6878
6887
|
|
|
6879
6888
|
` + `| No | Test Scenario | Test Case | Test Type | Expected Result | Actual Result | Status | Remark |
|
|
6880
6889
|
` + `| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
|
|
@@ -7525,12 +7534,30 @@ function linesOrNone(items, emptyText) {
|
|
|
7525
7534
|
`) : emptyText;
|
|
7526
7535
|
}
|
|
7527
7536
|
|
|
7537
|
+
// src/commands/rules.ts
|
|
7538
|
+
import { join as join12 } from "node:path";
|
|
7539
|
+
function rules() {
|
|
7540
|
+
const cwd = process.cwd();
|
|
7541
|
+
const outPath = join12(specsDir(cwd), "RULES.md");
|
|
7542
|
+
const raw = readTemplate(join12(templatesDir, "rules.md"));
|
|
7543
|
+
const written = writeIfAbsent(outPath, raw);
|
|
7544
|
+
if (!written) {
|
|
7545
|
+
console.log(`${outPath} already exists — edit it directly, or delete it to regenerate the template.`);
|
|
7546
|
+
return;
|
|
7547
|
+
}
|
|
7548
|
+
console.log(`Wrote ${outPath}`);
|
|
7549
|
+
console.log(` Fill in the [TODO] sections with your project's conventions.`);
|
|
7550
|
+
console.log(`
|
|
7551
|
+
Every forge drafting command (smelt, schema, contract, tasks, testcase) ` + `will ground the AI in these rules.`);
|
|
7552
|
+
}
|
|
7553
|
+
|
|
7528
7554
|
// src/cli.ts
|
|
7529
7555
|
var program2 = new Command;
|
|
7530
7556
|
program2.name("forge").description("Spec-driven development CLI — scaffolds specs, schemas, API contracts, tasks, and test cases.").version("0.1.0");
|
|
7531
7557
|
program2.command("init").description("Scaffold specs/ folder and an AI-tool bridge in the current project").option("-t, --target <target>", "bridge target: claude, cursor, windsurf, or generic", "claude").action((options) => init({ target: options.target }));
|
|
7532
7558
|
program2.command("bridge <target>").description("(Re)generate AI-tool bridge commands: claude, cursor, windsurf, or generic").action((target) => bridge(target));
|
|
7533
7559
|
program2.command("scan").description("Inventory the existing project structure into specs/CODEBASE.md").option("-d, --depth <n>", "directory-tree depth to include in the report", "2").action((options) => scan({ depth: Number(options.depth) }));
|
|
7560
|
+
program2.command("rules").description("Scaffold specs/RULES.md — project conventions the AI follows when drafting").action(() => rules());
|
|
7534
7561
|
program2.command("smelt <feature>").description("Extract raw requirements into a grounding brief and stub the PRD").action(smelt);
|
|
7535
7562
|
program2.command("schema <feature>").description("Scaffold schema.dbml (requires prd.md)").action(makeScaffoldCommand({ file: SPEC_FILES.schema, label: "schema" }));
|
|
7536
7563
|
program2.command("contract <feature>").description("Scaffold api-contract.md (requires prd.md)").action(makeScaffoldCommand({ file: SPEC_FILES.contract, label: "contract" }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rijalpermana/spec-forge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Spec-driven development CLI: scaffolds specs, schemas, API contracts, task lists, and test cases; bridges into Claude Code as slash commands.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Project Rules & Conventions
|
|
2
|
+
|
|
3
|
+
> Read by the AI before drafting any spec (schema, contract, tasks, testcases)
|
|
4
|
+
> through `forge`. Rules here **override** forge's built-in defaults. Fill every
|
|
5
|
+
> `[TODO]`, delete sections that don't apply, and keep entries factual and
|
|
6
|
+
> enforceable — the AI follows this literally.
|
|
7
|
+
|
|
8
|
+
## Tech stack
|
|
9
|
+
|
|
10
|
+
- Language / runtime: [TODO]
|
|
11
|
+
- Framework: [TODO]
|
|
12
|
+
- Database / ORM: [TODO]
|
|
13
|
+
- Other key libraries: [TODO]
|
|
14
|
+
|
|
15
|
+
## Naming conventions
|
|
16
|
+
|
|
17
|
+
- Folders & files: [TODO — e.g. kebab-case]
|
|
18
|
+
- Classes / types: [TODO — e.g. PascalCase]
|
|
19
|
+
- Variables & functions: [TODO — e.g. camelCase]
|
|
20
|
+
- Database columns: [TODO — e.g. snake_case]
|
|
21
|
+
- API endpoints / paths: [TODO — e.g. kebab-case, `/v1/...`]
|
|
22
|
+
- Forbidden: [TODO — e.g. no underscores in file/folder names]
|
|
23
|
+
|
|
24
|
+
## Project & module structure
|
|
25
|
+
|
|
26
|
+
[TODO — describe the folder layout a new feature/module must follow, e.g.
|
|
27
|
+
`dto/`, `entities/`, `*.controller.ts`, `*.service.ts`, `*.repository.ts`,
|
|
28
|
+
`*.module.ts`. The AI should scaffold new work to match this.]
|
|
29
|
+
|
|
30
|
+
## API design
|
|
31
|
+
|
|
32
|
+
- Versioning: [TODO — e.g. URI versioning `/v1/`, `/v2/`]
|
|
33
|
+
- Auth: [TODO — e.g. global guard, how to opt an endpoint out]
|
|
34
|
+
- Response envelope: [TODO — paste the exact success shape the API returns]
|
|
35
|
+
- Error shape & status: [TODO — how errors are formatted and what HTTP status is used]
|
|
36
|
+
- Pagination: [TODO — shape of paginated responses]
|
|
37
|
+
|
|
38
|
+
## Data & schema
|
|
39
|
+
|
|
40
|
+
- Audit/base fields every entity carries: [TODO — e.g. created_by, created_date, ...]
|
|
41
|
+
- Multi-tenancy / scoping: [TODO — or "n/a"]
|
|
42
|
+
- Type conventions: [TODO]
|
|
43
|
+
|
|
44
|
+
## Validation
|
|
45
|
+
|
|
46
|
+
[TODO — e.g. all inputs validated with a schema/validator; every field documented with an example]
|
|
47
|
+
|
|
48
|
+
## Security
|
|
49
|
+
|
|
50
|
+
[TODO — e.g. secrets from env only; encryption standard; required headers; rate limiting]
|
|
51
|
+
|
|
52
|
+
## Testing
|
|
53
|
+
|
|
54
|
+
- Framework: [TODO]
|
|
55
|
+
- Coverage threshold: [TODO — e.g. 80% branches/functions/lines/statements, build fails below]
|
|
56
|
+
- Test file convention: [TODO — e.g. `*.spec.ts` beside the file under test]
|
|
57
|
+
- Minimum per unit: [TODO — e.g. 1 success case + 1 error case]
|
|
58
|
+
|
|
59
|
+
## Documentation
|
|
60
|
+
|
|
61
|
+
[TODO — e.g. OpenAPI/Swagger required; every endpoint and DTO documented with examples]
|
|
62
|
+
|
|
63
|
+
## Tooling
|
|
64
|
+
|
|
65
|
+
- Lint: [TODO]
|
|
66
|
+
- Format: [TODO]
|
|
67
|
+
- Pre-commit checks: [TODO]
|
|
68
|
+
|
|
69
|
+
## Out of bounds
|
|
70
|
+
|
|
71
|
+
[TODO — anything the AI must never do in this codebase]
|