reffy-cli 0.6.5 → 0.6.7
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 +10 -10
- package/dist/cli.js +26 -16
- package/dist/doctor.js +6 -6
- package/dist/storage.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,11 +23,11 @@ reffy bootstrap
|
|
|
23
23
|
|
|
24
24
|
Command summary:
|
|
25
25
|
|
|
26
|
-
- `reffy init`: idempotently creates/updates root `AGENTS.md` managed block and `.
|
|
27
|
-
- `reffy bootstrap`: idempotently runs `init`, ensures `.
|
|
26
|
+
- `reffy init`: idempotently creates/updates root `AGENTS.md` managed block and `.reffy/AGENTS.md`.
|
|
27
|
+
- `reffy bootstrap`: idempotently runs `init`, ensures `.reffy/` structure exists, then reindexes artifacts.
|
|
28
28
|
- `reffy doctor`: diagnoses required Reffy setup and optional tool availability.
|
|
29
|
-
- `reffy reindex`: reconciles `.
|
|
30
|
-
- `reffy validate`: validates `.
|
|
29
|
+
- `reffy reindex`: reconciles `.reffy/manifest.json` with `.reffy/artifacts` by adding missing files and removing stale entries.
|
|
30
|
+
- `reffy validate`: validates `.reffy/manifest.json` against manifest v1 contract.
|
|
31
31
|
- `reffy summarize`: generates a read-only handoff summary from indexed artifacts.
|
|
32
32
|
- `reffy diagram render`: renders Mermaid diagrams as SVG or ASCII, including spec-aware generation from OpenSpec `spec.md`.
|
|
33
33
|
|
|
@@ -48,31 +48,31 @@ reffy summarize --output text
|
|
|
48
48
|
reffy summarize --output json
|
|
49
49
|
reffy diagram render --stdin --format svg < diagram.mmd
|
|
50
50
|
reffy diagram render --input openspec/specs/auth/spec.md --format ascii
|
|
51
|
-
reffy diagram render --input openspec/specs/auth/spec.md --format svg --output .
|
|
51
|
+
reffy diagram render --input openspec/specs/auth/spec.md --format svg --output .reffy/artifacts/auth-spec.svg
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
## Using Reffy With SDD Frameworks (OpenSpec Example)
|
|
55
55
|
|
|
56
56
|
`reffy` is designed to complement spec-driven development workflows rather than replace them. A common pattern is:
|
|
57
57
|
|
|
58
|
-
1. Use Reffy for ideation and context capture in `.
|
|
58
|
+
1. Use Reffy for ideation and context capture in `.reffy/`.
|
|
59
59
|
2. Use an SDD framework (for example [OpenSpec](https://github.com/Fission-AI/OpenSpec)) for formal proposals/specs/tasks.
|
|
60
60
|
3. Keep a clear handoff from exploratory artifacts to formal specs.
|
|
61
61
|
|
|
62
62
|
Reference implementation in this repo:
|
|
63
63
|
|
|
64
64
|
- `AGENTS.md`: contains both managed instruction blocks and encodes sequencing.
|
|
65
|
-
- `AGENTS.md`: Reffy block routes ideation/exploration requests to `@/.
|
|
65
|
+
- `AGENTS.md`: Reffy block routes ideation/exploration requests to `@/.reffy/AGENTS.md`.
|
|
66
66
|
- `AGENTS.md`: OpenSpec block routes planning/proposal/spec requests to `@/openspec/AGENTS.md`.
|
|
67
|
-
- `.
|
|
67
|
+
- `.reffy/AGENTS.md`: defines Reffy as the ideation/context layer and documents handoff expectations to OpenSpec.
|
|
68
68
|
- `openspec/AGENTS.md`: defines OpenSpec as the formal planning/specification workflow after ideation is stable.
|
|
69
|
-
- `src/cli.ts`: `reffy init`/`reffy bootstrap` enforce this integration by idempotently writing the managed Reffy guidance into `AGENTS.md` and `.
|
|
69
|
+
- `src/cli.ts`: `reffy init`/`reffy bootstrap` enforce this integration by idempotently writing the managed Reffy guidance into `AGENTS.md` and `.reffy/AGENTS.md`.
|
|
70
70
|
|
|
71
71
|
Practical connection pattern for any repo:
|
|
72
72
|
|
|
73
73
|
1. Run `reffy init` to install/refresh the Reffy instruction layer.
|
|
74
74
|
2. Keep your SDD framework instructions (for example OpenSpec) in the same root `AGENTS.md`.
|
|
75
|
-
3. During planning, cite only relevant Reffy artifacts from `.
|
|
75
|
+
3. During planning, cite only relevant Reffy artifacts from `.reffy/artifacts/` in your proposal/spec docs.
|
|
76
76
|
4. Continue implementation in your SDD framework's normal review/approval process.
|
|
77
77
|
|
|
78
78
|
## Develop
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
import { existsSync, promises as fs, statSync } from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { renderDiagram } from "./diagram.js";
|
|
5
6
|
import { runDoctor } from "./doctor.js";
|
|
6
7
|
import { ReferencesStore } from "./storage.js";
|
|
7
8
|
import { summarizeArtifacts } from "./summarize.js";
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
const { version: packageVersion } = require("../package.json");
|
|
8
11
|
const REFFY_ASCII = [
|
|
9
12
|
" __ __ ",
|
|
10
13
|
" _ __ ___ / _|/ _|_ _",
|
|
@@ -18,20 +21,20 @@ const REFFY_BLOCK = `<!-- REFFY:START -->
|
|
|
18
21
|
|
|
19
22
|
These instructions are for AI assistants working in this project.
|
|
20
23
|
|
|
21
|
-
Always open \`@/.
|
|
24
|
+
Always open \`@/.reffy/AGENTS.md\` when the request:
|
|
22
25
|
- Mentions early-stage ideation, exploration, brainstorming, or raw notes
|
|
23
26
|
- Needs context before drafting specs or proposals
|
|
24
27
|
- Refers to "reffy", "references", "explore", or "context layer"
|
|
25
28
|
|
|
26
|
-
Use \`@/.
|
|
29
|
+
Use \`@/.reffy/AGENTS.md\` to learn:
|
|
27
30
|
- Reffy workflow and artifact conventions
|
|
28
31
|
- How Reffy and OpenSpec should be sequenced
|
|
29
|
-
- How to store and consume ideation context in \`.
|
|
32
|
+
- How to store and consume ideation context in \`.reffy/\`
|
|
30
33
|
|
|
31
34
|
Keep this managed block so \`reffy init\` can refresh the instructions.
|
|
32
35
|
|
|
33
36
|
<!-- REFFY:END -->`;
|
|
34
|
-
const REFFY_AGENTS_RELATIVE = path.join(".
|
|
37
|
+
const REFFY_AGENTS_RELATIVE = path.join(".reffy", "AGENTS.md");
|
|
35
38
|
const REFFY_AGENTS_CONTENT = `# Reffy Instructions
|
|
36
39
|
|
|
37
40
|
These instructions are for AI assistants working in this project.
|
|
@@ -39,7 +42,7 @@ These instructions are for AI assistants working in this project.
|
|
|
39
42
|
## TL;DR Checklist
|
|
40
43
|
|
|
41
44
|
- Decide whether Reffy ideation is needed for this request.
|
|
42
|
-
- If needed, read existing context in \`.
|
|
45
|
+
- If needed, read existing context in \`.reffy/artifacts/\`.
|
|
43
46
|
- Add/update exploratory artifacts and keep them concise.
|
|
44
47
|
- Run \`reffy reindex\` and \`reffy validate\` after artifact changes.
|
|
45
48
|
- After ideation approval, run \`reffy summarize --output json\` and pick only directly relevant artifacts for proposal citations.
|
|
@@ -60,9 +63,9 @@ You can skip Reffy when the request is:
|
|
|
60
63
|
|
|
61
64
|
## Reffy Workflow
|
|
62
65
|
|
|
63
|
-
1. Read existing artifacts in \`.
|
|
66
|
+
1. Read existing artifacts in \`.reffy/artifacts/\`.
|
|
64
67
|
2. Add or update artifacts to capture exploratory context.
|
|
65
|
-
3. Run \`reffy reindex\` to index newly added files into \`.
|
|
68
|
+
3. Run \`reffy reindex\` to index newly added files into \`.reffy/manifest.json\`.
|
|
66
69
|
4. Run \`reffy validate\` to verify manifest contract compliance.
|
|
67
70
|
|
|
68
71
|
## Relationship To OpenSpec
|
|
@@ -102,7 +105,7 @@ No Reffy references used.
|
|
|
102
105
|
|
|
103
106
|
## Artifact Conventions
|
|
104
107
|
|
|
105
|
-
- Treat \`.
|
|
108
|
+
- Treat \`.reffy/\` as a repository-local guidance and ideation context layer.
|
|
106
109
|
- Keep artifact names clear and stable.
|
|
107
110
|
- Prefer markdown notes for exploratory content.
|
|
108
111
|
- Keep manifests machine-readable and schema-compliant (version 1).
|
|
@@ -153,10 +156,10 @@ function isDirectory(targetPath) {
|
|
|
153
156
|
function discoverRepoRoot(startDir) {
|
|
154
157
|
let current = path.resolve(startDir);
|
|
155
158
|
while (true) {
|
|
156
|
-
if (path.basename(current) === ".
|
|
159
|
+
if (path.basename(current) === ".reffy" && isDirectory(path.join(current, "artifacts"))) {
|
|
157
160
|
return path.dirname(current);
|
|
158
161
|
}
|
|
159
|
-
if (isDirectory(path.join(current, ".
|
|
162
|
+
if (isDirectory(path.join(current, ".reffy"))) {
|
|
160
163
|
return current;
|
|
161
164
|
}
|
|
162
165
|
if (pathExists(path.join(current, "AGENTS.md")) || pathExists(path.join(current, ".git"))) {
|
|
@@ -224,12 +227,15 @@ function usage() {
|
|
|
224
227
|
return [
|
|
225
228
|
"Usage: reffy <command> [--repo PATH] [--output text|json]",
|
|
226
229
|
"",
|
|
230
|
+
"Flags:",
|
|
231
|
+
" --version Print the installed reffy package version.",
|
|
232
|
+
"",
|
|
227
233
|
"Commands:",
|
|
228
|
-
" init Ensure root AGENTS.md block and .
|
|
229
|
-
" bootstrap Run init, ensure .
|
|
234
|
+
" init Ensure root AGENTS.md block and .reffy/AGENTS.md are up to date.",
|
|
235
|
+
" bootstrap Run init, ensure .reffy structure exists, then reindex artifacts.",
|
|
230
236
|
" doctor Diagnose required Reffy setup and optional tool availability.",
|
|
231
|
-
" reindex Scan .
|
|
232
|
-
" validate Validate .
|
|
237
|
+
" reindex Scan .reffy/artifacts and add missing files to manifest.",
|
|
238
|
+
" validate Validate .reffy/manifest.json against manifest v1 contract.",
|
|
233
239
|
" summarize Generate a read-only summary of indexed Reffy artifacts.",
|
|
234
240
|
" diagram Render Mermaid diagrams (supports SVG and ASCII).",
|
|
235
241
|
].join("\n");
|
|
@@ -365,9 +371,13 @@ function printSection(title, values) {
|
|
|
365
371
|
}
|
|
366
372
|
async function main() {
|
|
367
373
|
const [, , command, ...rest] = process.argv;
|
|
368
|
-
if (!command) {
|
|
374
|
+
if (!command || command === "--help" || command === "-h") {
|
|
369
375
|
console.error(usage());
|
|
370
|
-
return 1;
|
|
376
|
+
return command ? 0 : 1;
|
|
377
|
+
}
|
|
378
|
+
if (command === "--version") {
|
|
379
|
+
console.log(packageVersion);
|
|
380
|
+
return 0;
|
|
371
381
|
}
|
|
372
382
|
if (command === "diagram") {
|
|
373
383
|
const [subcommand, ...diagramArgs] = rest;
|
package/dist/doctor.js
CHANGED
|
@@ -27,7 +27,7 @@ function summarizeChecks(checks) {
|
|
|
27
27
|
}
|
|
28
28
|
export async function runDoctor(repoRoot, options) {
|
|
29
29
|
const checks = [];
|
|
30
|
-
const refsDir = path.join(repoRoot, ".
|
|
30
|
+
const refsDir = path.join(repoRoot, ".reffy");
|
|
31
31
|
const artifactsDir = path.join(refsDir, "artifacts");
|
|
32
32
|
const manifestPath = path.join(refsDir, "manifest.json");
|
|
33
33
|
const rootAgentsPath = path.join(repoRoot, "AGENTS.md");
|
|
@@ -37,14 +37,14 @@ export async function runDoctor(repoRoot, options) {
|
|
|
37
37
|
id: "refs_dir_exists",
|
|
38
38
|
level: "required",
|
|
39
39
|
ok: refsDirExists,
|
|
40
|
-
message: refsDirExists ? ".
|
|
40
|
+
message: refsDirExists ? ".reffy directory found" : ".reffy directory is missing",
|
|
41
41
|
});
|
|
42
42
|
const artifactsDirExists = await pathExists(artifactsDir);
|
|
43
43
|
checks.push({
|
|
44
44
|
id: "artifacts_dir_exists",
|
|
45
45
|
level: "required",
|
|
46
46
|
ok: artifactsDirExists,
|
|
47
|
-
message: artifactsDirExists ? ".
|
|
47
|
+
message: artifactsDirExists ? ".reffy/artifacts directory found" : ".reffy/artifacts directory is missing",
|
|
48
48
|
});
|
|
49
49
|
const rootAgentsExists = await pathExists(rootAgentsPath);
|
|
50
50
|
checks.push({
|
|
@@ -58,7 +58,7 @@ export async function runDoctor(repoRoot, options) {
|
|
|
58
58
|
id: "refs_agents_exists",
|
|
59
59
|
level: "required",
|
|
60
60
|
ok: refsAgentsExists,
|
|
61
|
-
message: refsAgentsExists ? ".
|
|
61
|
+
message: refsAgentsExists ? ".reffy/AGENTS.md found" : ".reffy/AGENTS.md is missing",
|
|
62
62
|
});
|
|
63
63
|
const manifestExists = await pathExists(manifestPath);
|
|
64
64
|
if (!manifestExists) {
|
|
@@ -66,7 +66,7 @@ export async function runDoctor(repoRoot, options) {
|
|
|
66
66
|
id: "manifest_valid",
|
|
67
67
|
level: "required",
|
|
68
68
|
ok: false,
|
|
69
|
-
message: ".
|
|
69
|
+
message: ".reffy/manifest.json is missing",
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
else {
|
|
@@ -76,7 +76,7 @@ export async function runDoctor(repoRoot, options) {
|
|
|
76
76
|
level: "required",
|
|
77
77
|
ok: manifestResult.ok,
|
|
78
78
|
message: manifestResult.ok
|
|
79
|
-
? `.
|
|
79
|
+
? `.reffy/manifest.json is valid (artifacts=${String(manifestResult.artifact_count)})`
|
|
80
80
|
: `manifest invalid: ${manifestResult.errors.join("; ")}`,
|
|
81
81
|
});
|
|
82
82
|
}
|
package/dist/storage.js
CHANGED
|
@@ -16,7 +16,7 @@ export class ReferencesStore {
|
|
|
16
16
|
manifestPath;
|
|
17
17
|
constructor(repoRoot) {
|
|
18
18
|
this.repoRoot = repoRoot;
|
|
19
|
-
this.refsDir = path.join(repoRoot, ".
|
|
19
|
+
this.refsDir = path.join(repoRoot, ".reffy");
|
|
20
20
|
this.artifactsDir = path.join(this.refsDir, "artifacts");
|
|
21
21
|
this.manifestPath = path.join(this.refsDir, "manifest.json");
|
|
22
22
|
this.ensureStructure();
|