stego-cli 0.4.0 → 0.4.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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "recommendations": [
3
+ "matt-gold.stego-extension",
4
+ "matt-gold.saurus-extension",
5
+ "streetsidesoftware.code-spell-checker"
6
+ ]
7
+ }
package/README.md CHANGED
@@ -70,6 +70,41 @@ Spine V2 is directory-inferred:
70
70
 
71
71
  Projects also include local npm scripts so you can work from inside a project directory.
72
72
 
73
+ ## Complete CLI command reference
74
+
75
+ The full command surface is available via:
76
+
77
+ ```bash
78
+ stego --help
79
+ stego --version
80
+ ```
81
+
82
+ Current `stego --help` command index:
83
+
84
+ ```text
85
+ init [--force]
86
+ list-projects [--root <path>]
87
+ new-project --project <project-id> [--title <title>] [--prose-font <yes|no|prompt>] [--format <text|json>] [--root <path>]
88
+ new --project <project-id> [--i <prefix>|-i <prefix>] [--filename <name>] [--format <text|json>] [--root <path>]
89
+ validate --project <project-id> [--file <project-relative-manuscript-path>] [--root <path>]
90
+ build --project <project-id> [--root <path>]
91
+ check-stage --project <project-id> --stage <draft|revise|line-edit|proof|final> [--file <project-relative-manuscript-path>] [--root <path>]
92
+ lint --project <project-id> [--manuscript|--spine] [--root <path>]
93
+ export --project <project-id> --format <md|docx|pdf|epub> [--output <path>] [--root <path>]
94
+ spine read --project <project-id> [--format <text|json>] [--root <path>]
95
+ spine new-category --project <project-id> --key <category> [--label <label>] [--require-metadata] [--format <text|json>] [--root <path>]
96
+ spine new --project <project-id> --category <category> [--filename <relative-path>] [--format <text|json>] [--root <path>]
97
+ metadata read <markdown-path> [--format <text|json>]
98
+ metadata apply <markdown-path> --input <path|-> [--format <text|json>]
99
+ comments read <manuscript> [--format <text|json>]
100
+ comments add <manuscript> [--message <text> | --input <path|->] [--author <name>] [--start-line <n> --start-col <n> --end-line <n> --end-col <n>] [--cursor-line <n>] [--format <text|json>]
101
+ comments reply <manuscript> --comment-id <CMT-####> [--message <text> | --input <path|->] [--author <name>] [--format <text|json>]
102
+ comments set-status <manuscript> --comment-id <CMT-####> --status <open|resolved> [--thread] [--format <text|json>]
103
+ comments delete <manuscript> --comment-id <CMT-####> [--format <text|json>]
104
+ comments clear-resolved <manuscript> [--format <text|json>]
105
+ comments sync-anchors <manuscript> --input <path|-> [--format <text|json>]
106
+ ```
107
+
73
108
  ## Advanced integration command
74
109
 
75
110
  `stego comments add` is a machine-facing command for editor/tool integrations.
package/dist/stego-cli.js CHANGED
@@ -25,6 +25,7 @@ const RESERVED_COMMENT_PREFIX = "CMT";
25
25
  const DEFAULT_NEW_MANUSCRIPT_SLUG = "new-document";
26
26
  const ROOT_CONFIG_FILENAME = "stego.config.json";
27
27
  const PROSE_FONT_PROMPT = "Switch workspace to proportional (prose-style) font? (recommended)";
28
+ const COMMENT_AUTHOR_PROMPT = "Default comment author for stego.comments.author?";
28
29
  const SCAFFOLD_GITIGNORE_CONTENT = `node_modules/
29
30
  /dist/
30
31
  .DS_Store
@@ -92,6 +93,103 @@ stego new-project --project my-book --title "My Book"
92
93
  stego new --project fiction-example
93
94
  \`\`\`
94
95
  `;
96
+ const SCAFFOLD_AGENTS_CONTENT = `# AGENTS.md
97
+
98
+ ## Purpose
99
+
100
+ This workspace is designed to be AI-friendly for writing workflows.
101
+
102
+ ## Canonical CLI Interface
103
+
104
+ - Run \`stego --help\` for the full command reference.
105
+ - Run \`stego --version\` to confirm which CLI is active.
106
+ - Run project docs commands in \`projects/stego-docs\` when available.
107
+
108
+ ## CLI Resolution Rules
109
+
110
+ - Prefer local CLI over global CLI:
111
+ - \`npm exec -- stego ...\`
112
+ - \`npx --no-install stego ...\`
113
+ - At the start of mutation tasks, run \`stego --version\` and report the version used.
114
+
115
+ ## Workspace Discovery Checklist
116
+
117
+ 1. Confirm workspace root contains \`stego.config.json\`.
118
+ 2. Run \`stego list-projects\`.
119
+ 3. Use explicit \`--project <id>\` for project-scoped commands.
120
+
121
+ ## CLI-First Policy (Required)
122
+
123
+ When asked to edit Stego project content, use documented Stego CLI commands first.
124
+
125
+ Typical targets:
126
+
127
+ - manuscript files
128
+ - spine categories and entries
129
+ - frontmatter metadata
130
+ - comments
131
+ - stage/build/export workflows
132
+
133
+ Preferred commands include:
134
+
135
+ - \`stego new\`
136
+ - \`stego spine read\`
137
+ - \`stego spine new-category\`
138
+ - \`stego spine new\`
139
+ - \`stego metadata read\`
140
+ - \`stego metadata apply\`
141
+ - \`stego comments ...\`
142
+
143
+ ## Machine-Mode Output
144
+
145
+ - For automation and integrations, prefer \`--format json\` and parse structured output.
146
+ - Use text output only for human-facing summaries.
147
+
148
+ ## Mutation Protocol
149
+
150
+ 1. Read current state first (\`metadata read\`, \`spine read\`, \`comments read\`).
151
+ 2. Mutate via CLI commands.
152
+ 3. Verify after writes (\`stego validate --project <id>\` and relevant read commands).
153
+
154
+ ## Manual Edit Fallback
155
+
156
+ Manual file edits are a last resort.
157
+
158
+ If manual edits are required, the agent must:
159
+
160
+ 1. warn that CLI was bypassed,
161
+ 2. explain why CLI could not be used, and
162
+ 3. list which files were manually edited.
163
+
164
+ ## Failure Contract
165
+
166
+ When CLI fails:
167
+
168
+ 1. show the attempted command,
169
+ 2. summarize the error briefly,
170
+ 3. report the recovery attempt, and
171
+ 4. if fallback is required, apply the Manual Edit Fallback policy.
172
+
173
+ ## Validation Expectations
174
+
175
+ After mutations, run relevant checks when feasible (for example \`stego validate --project <id>\`) and report results.
176
+
177
+ ## Scope Guardrails
178
+
179
+ - Do not manually edit \`dist/\` outputs or compiled export artifacts.
180
+ - Do not modify files outside the requested project scope unless the user explicitly asks.
181
+
182
+ ## Task To Command Quick Map
183
+
184
+ - New manuscript: \`stego new --project <id> [--filename <name>]\`
185
+ - Read spine: \`stego spine read --project <id> --format json\`
186
+ - New spine category: \`stego spine new-category --project <id> --key <category>\`
187
+ - New spine entry: \`stego spine new --project <id> --category <category> [--filename <path>]\`
188
+ - Read metadata: \`stego metadata read <markdown-path> --format json\`
189
+ - Apply metadata: \`stego metadata apply <markdown-path> --input <path|-> --format json\`
190
+ - Read comments: \`stego comments read <manuscript> --format json\`
191
+ - Mutate comments: \`stego comments add|reply|set-status|delete|clear-resolved|sync-anchors ... --format json\`
192
+ `;
95
193
  const PROSE_MARKDOWN_EDITOR_SETTINGS = {
96
194
  "[markdown]": {
97
195
  "editor.fontFamily": "Inter, Helvetica Neue, Helvetica, Arial, sans-serif",
@@ -105,7 +203,8 @@ const PROSE_MARKDOWN_EDITOR_SETTINGS = {
105
203
  };
106
204
  const PROJECT_EXTENSION_RECOMMENDATIONS = [
107
205
  "matt-gold.stego-extension",
108
- "matt-gold.saurus-extension"
206
+ "matt-gold.saurus-extension",
207
+ "streetsidesoftware.code-spell-checker"
109
208
  ];
110
209
  const scriptDir = path.dirname(fileURLToPath(import.meta.url));
111
210
  const packageRoot = path.resolve(scriptDir, "..");
@@ -513,6 +612,7 @@ async function initWorkspace(options) {
513
612
  const copiedPaths = [];
514
613
  writeScaffoldGitignore(targetRoot, copiedPaths);
515
614
  writeScaffoldReadme(targetRoot, copiedPaths);
615
+ writeScaffoldAgents(targetRoot, copiedPaths);
516
616
  copyTemplateAsset(".markdownlint.json", targetRoot, copiedPaths);
517
617
  copyTemplateAsset(".markdownlint.manuscript.json", targetRoot, copiedPaths);
518
618
  copyTemplateAsset(".cspell.json", targetRoot, copiedPaths);
@@ -522,8 +622,13 @@ async function initWorkspace(options) {
522
622
  copyTemplateAsset(path.join(".vscode", "extensions.json"), targetRoot, copiedPaths, { optional: true });
523
623
  rewriteTemplateProjectPackageScripts(targetRoot);
524
624
  const enableProseFont = await promptYesNo(PROSE_FONT_PROMPT, true);
525
- if (enableProseFont) {
526
- writeProjectProseEditorSettings(targetRoot, copiedPaths);
625
+ const suggestedCommentAuthor = resolveSuggestedCommentAuthor(targetRoot);
626
+ const commentAuthor = (await promptText(COMMENT_AUTHOR_PROMPT, suggestedCommentAuthor)).trim();
627
+ if (enableProseFont || commentAuthor) {
628
+ writeProjectProseEditorSettings(targetRoot, copiedPaths, {
629
+ enableProseFont,
630
+ commentAuthor
631
+ });
527
632
  }
528
633
  writeInitRootPackageJson(targetRoot);
529
634
  logLine(`Initialized Stego workspace in ${targetRoot}`);
@@ -566,6 +671,46 @@ async function promptYesNo(question, defaultYes) {
566
671
  rl.close();
567
672
  }
568
673
  }
674
+ async function promptText(question, defaultValue = "") {
675
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
676
+ return defaultValue;
677
+ }
678
+ const rl = createInterface({
679
+ input: process.stdin,
680
+ output: process.stdout
681
+ });
682
+ const suffix = defaultValue ? ` [${defaultValue}] ` : " ";
683
+ try {
684
+ const answer = (await rl.question(`${question}${suffix}`)).trim();
685
+ if (!answer) {
686
+ return defaultValue;
687
+ }
688
+ return answer;
689
+ }
690
+ finally {
691
+ rl.close();
692
+ }
693
+ }
694
+ function resolveSuggestedCommentAuthor(cwd) {
695
+ const gitAuthor = spawnSync("git", ["config", "--get", "user.name"], {
696
+ cwd,
697
+ encoding: "utf8"
698
+ });
699
+ const fromGit = (gitAuthor.stdout || "").trim();
700
+ if (gitAuthor.status === 0 && fromGit) {
701
+ return fromGit;
702
+ }
703
+ try {
704
+ const username = os.userInfo().username.trim();
705
+ if (username) {
706
+ return username;
707
+ }
708
+ }
709
+ catch {
710
+ // ignore lookup failure and fall back to empty
711
+ }
712
+ return "";
713
+ }
569
714
  function copyTemplateAsset(sourceRelativePath, targetRoot, copiedPaths, options) {
570
715
  const sourcePath = path.join(packageRoot, sourceRelativePath);
571
716
  if (!fs.existsSync(sourcePath)) {
@@ -600,6 +745,11 @@ function writeScaffoldReadme(targetRoot, copiedPaths) {
600
745
  fs.writeFileSync(destinationPath, SCAFFOLD_README_CONTENT, "utf8");
601
746
  copiedPaths.push("README.md");
602
747
  }
748
+ function writeScaffoldAgents(targetRoot, copiedPaths) {
749
+ const destinationPath = path.join(targetRoot, "AGENTS.md");
750
+ fs.writeFileSync(destinationPath, SCAFFOLD_AGENTS_CONTENT, "utf8");
751
+ copiedPaths.push("AGENTS.md");
752
+ }
603
753
  function shouldCopyTemplatePath(currentSourcePath) {
604
754
  const relativePath = path.relative(packageRoot, currentSourcePath);
605
755
  if (!relativePath || relativePath.startsWith("..")) {
@@ -675,7 +825,7 @@ function ensureProjectExtensionsRecommendations(projectRoot) {
675
825
  };
676
826
  fs.writeFileSync(extensionsPath, `${JSON.stringify(extensionsConfig, null, 2)}\n`, "utf8");
677
827
  }
678
- function writeProjectProseEditorSettings(targetRoot, copiedPaths) {
828
+ function writeProjectProseEditorSettings(targetRoot, copiedPaths, options) {
679
829
  const projectsRoot = path.join(targetRoot, "projects");
680
830
  if (!fs.existsSync(projectsRoot)) {
681
831
  return;
@@ -685,14 +835,16 @@ function writeProjectProseEditorSettings(targetRoot, copiedPaths) {
685
835
  continue;
686
836
  }
687
837
  const projectRoot = path.join(projectsRoot, entry.name);
688
- const settingsPath = writeProseEditorSettingsForProject(projectRoot);
838
+ const settingsPath = writeProseEditorSettingsForProject(projectRoot, options);
689
839
  copiedPaths.push(path.relative(targetRoot, settingsPath));
690
840
  }
691
841
  }
692
- function writeProseEditorSettingsForProject(projectRoot) {
842
+ function writeProseEditorSettingsForProject(projectRoot, options) {
693
843
  const vscodeDir = path.join(projectRoot, ".vscode");
694
844
  const settingsPath = path.join(vscodeDir, "settings.json");
695
845
  fs.mkdirSync(vscodeDir, { recursive: true });
846
+ const enableProseFont = options?.enableProseFont ?? true;
847
+ const commentAuthor = (options?.commentAuthor ?? "").trim();
696
848
  let existingSettings = {};
697
849
  if (fs.existsSync(settingsPath)) {
698
850
  try {
@@ -708,17 +860,22 @@ function writeProseEditorSettingsForProject(projectRoot) {
708
860
  const proseMarkdownSettings = isPlainObject(PROSE_MARKDOWN_EDITOR_SETTINGS["[markdown]"])
709
861
  ? PROSE_MARKDOWN_EDITOR_SETTINGS["[markdown]"]
710
862
  : {};
711
- const existingMarkdownSettings = isPlainObject(existingSettings["[markdown]"])
712
- ? existingSettings["[markdown]"]
713
- : {};
714
863
  const nextSettings = {
715
- ...existingSettings,
716
- "[markdown]": {
864
+ ...existingSettings
865
+ };
866
+ if (enableProseFont) {
867
+ const existingMarkdownSettings = isPlainObject(existingSettings["[markdown]"])
868
+ ? existingSettings["[markdown]"]
869
+ : {};
870
+ nextSettings["[markdown]"] = {
717
871
  ...existingMarkdownSettings,
718
872
  ...proseMarkdownSettings
719
- },
720
- "markdown.preview.fontFamily": PROSE_MARKDOWN_EDITOR_SETTINGS["markdown.preview.fontFamily"]
721
- };
873
+ };
874
+ nextSettings["markdown.preview.fontFamily"] = PROSE_MARKDOWN_EDITOR_SETTINGS["markdown.preview.fontFamily"];
875
+ }
876
+ if (commentAuthor) {
877
+ nextSettings["stego.comments.author"] = commentAuthor;
878
+ }
722
879
  fs.writeFileSync(settingsPath, `${JSON.stringify(nextSettings, null, 2)}\n`, "utf8");
723
880
  return settingsPath;
724
881
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stego-cli",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "description": "Installable CLI for the Stego writing monorepo workflow.",
6
6
  "license": "Apache-2.0",