@archme/cli 0.5.0 → 0.5.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.
Files changed (2) hide show
  1. package/dist/cli.js +39 -11
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -12138,21 +12138,32 @@ var init_affected = __esm({
12138
12138
  }
12139
12139
  });
12140
12140
 
12141
+ // ../shared/storyNaming.ts
12142
+ var STORY_NAMING_GUIDANCE;
12143
+ var init_storyNaming = __esm({
12144
+ "../shared/storyNaming.ts"() {
12145
+ STORY_NAMING_GUIDANCE = `Story titles:
12146
+ - **Leaves are actions.** A leaf story is a flow, so title it verb + object, imperative: \`sign up with email\`, \`refund a charge\`, \`retry a failed job\`. Not the noun phrase for the same flow (\`email signup\`, \`charge refunds\`, \`failed job retry\`).
12147
+ - **Groups are areas.** A parent story is a feature area, so title it as a noun phrase naming what its leaves have in common: \`auth\`, \`billing\`, \`job queue\`. Not an action (\`authenticate users\`).
12148
+ - Keep both as short as the hierarchy allows \u2014 the group supplies the context, so a leaf never restates it.
12149
+ - Good: "web app" > "auth" > "sign up with email"
12150
+ - Bad: "new user signs up with email on the web app"
12151
+ - **An existing convention wins.** If a story's siblings already agree on a different form, match them \u2014 cohesion across the tree is the goal, and the rules above are only the default when there is nothing to match. Restyle only titles you are already editing for another reason; a rename lands in someone's diff, so never sweep the tree for form alone.`;
12152
+ }
12153
+ });
12154
+
12141
12155
  // ../shared/scanPrompts.ts
12142
12156
  function buildFormatRefStories(opts) {
12143
12157
  const draftBlock = opts.persistentDrafts ? FORMAT_REF_DRAFT_STORIES_BLOCK : "";
12144
12158
  const uncoveredSubFlowRule = opts.persistentDrafts ? CROSS_REF_UNCOVERED_DRAFT_STUB : CROSS_REF_UNCOVERED_REAL_STORY;
12145
- const hierarchyExample = opts.persistentDrafts ? `- Example: storyUpdates: [{add: [{id: "auth", title: "Authentication", description: "User auth flows", draft: true, userStories: [{id: "login", title: "Login Flow", draft: true, acceptanceCriteria: ["< 1s response"]}]}]}]` : `- Example: storyUpdates: [{add: [{id: "auth", title: "Authentication", description: "User auth flows", userStories: [{id: "login", title: "Login Flow", acceptanceCriteria: ["< 1s response"], sequence: "sequenceDiagram\\n ..."}]}]}]`;
12159
+ const hierarchyExample = opts.persistentDrafts ? `- Example: storyUpdates: [{add: [{id: "auth", title: "Authentication", description: "User auth flows", draft: true, userStories: [{id: "login", title: "log in with email", draft: true, acceptanceCriteria: ["< 1s response"]}]}]}]` : `- Example: storyUpdates: [{add: [{id: "auth", title: "Authentication", description: "User auth flows", userStories: [{id: "login", title: "log in with email", acceptanceCriteria: ["< 1s response"], sequence: "sequenceDiagram\\n ..."}]}]}]`;
12146
12160
  return `Recursive story hierarchy:
12147
12161
  - Stories can contain child stories via userStories: [...] \u2014 parent stories act as feature groups
12148
12162
  - Use top-level stories with description, links, and nested children to organize by feature area
12149
12163
  ${hierarchyExample}
12150
12164
  - Removing a parent story cascades to all descendants
12151
12165
 
12152
- Story titles:
12153
- - Keep titles as short as possible \u2014 rely on the parent group for context.
12154
- - Good: "web app" > "auth" > "sign up with email"
12155
- - Bad: "new user signs up with email on the web app"
12166
+ ${STORY_NAMING_GUIDANCE}
12156
12167
 
12157
12168
  Story description format (markdown, 1-4 sentences \u2014 render target is a narrow side panel):
12158
12169
  - Write for someone who knows the product but isn't reading the code. Say what the system does and what the user/operator experiences at the highest useful altitude, not how it's implemented. A tl;dr, not a rehash.
@@ -12205,14 +12216,15 @@ storyUpdates targeting:
12205
12216
  - add: stories to add or update (merged by ID if story already exists)
12206
12217
  - remove: story IDs to remove
12207
12218
  - Examples:
12208
- - Add at root: storyUpdates: [{add: [{id: "us1", title: "Login", ...}]}]
12209
- - Add under story group: storyUpdates: [{under: "auth", add: [{id: "login", title: "Login Flow", ...}]}]
12219
+ - Add at root: storyUpdates: [{add: [{id: "us1", title: "log in", ...}]}]
12220
+ - Add under story group: storyUpdates: [{under: "auth", add: [{id: "login", title: "log in with email", ...}]}]
12210
12221
  - Remove: storyUpdates: [{remove: ["old_story"]}]
12211
12222
  - Combined: storyUpdates: [{under: "auth", add: [{id: "new_flow", ...}], remove: ["old_flow"]}]`;
12212
12223
  }
12213
12224
  var ANCHOR_RULES, ANCHOR_DISCOVERY, ANCHOR_VERIFICATION, FORMAT_REF_COMPONENTS, FORMAT_REF_CONNECTIONS, FORMAT_REF_DRAFT_STORIES_BLOCK, CROSS_REF_UNCOVERED_DRAFT_STUB, CROSS_REF_UNCOVERED_REAL_STORY, FORMAT_REF_STORIES;
12214
12225
  var init_scanPrompts = __esm({
12215
12226
  "../shared/scanPrompts.ts"() {
12227
+ init_storyNaming();
12216
12228
  ANCHOR_RULES = `Every component must have either \`anchors\` (non-empty array) or \`unanchored: true\`. No bare components.
12217
12229
 
12218
12230
  Pick the anchor kind based on how the component lives in code:
@@ -12637,12 +12649,15 @@ async function getLanguage(lang, cacheRoot = defaultCacheRoot()) {
12637
12649
  return language;
12638
12650
  }
12639
12651
  async function getParser(lang, cacheRoot) {
12652
+ const cached = parserCache.get(lang);
12653
+ if (cached) return cached;
12640
12654
  const language = await getLanguage(lang, cacheRoot);
12641
12655
  const parser = new Parser();
12642
12656
  parser.setLanguage(language);
12657
+ parserCache.set(lang, parser);
12643
12658
  return parser;
12644
12659
  }
12645
- var initialized, languageCache;
12660
+ var initialized, languageCache, parserCache;
12646
12661
  var init_parser = __esm({
12647
12662
  "src/analyze/tree-sitter/parser.ts"() {
12648
12663
  "use strict";
@@ -12650,6 +12665,7 @@ var init_parser = __esm({
12650
12665
  init_grammars();
12651
12666
  initialized = false;
12652
12667
  languageCache = /* @__PURE__ */ new Map();
12668
+ parserCache = /* @__PURE__ */ new Map();
12653
12669
  }
12654
12670
  });
12655
12671
 
@@ -12977,22 +12993,34 @@ var init_extract = __esm({
12977
12993
 
12978
12994
  // src/analyze/tree-sitter/symbols.ts
12979
12995
  import { Query } from "web-tree-sitter";
12996
+ async function getQuery(lang) {
12997
+ const cached = queryCache.get(lang);
12998
+ if (cached) return cached;
12999
+ const query = new Query(await getLanguage(lang), SYMBOL_QUERIES[lang]);
13000
+ queryCache.set(lang, query);
13001
+ return query;
13002
+ }
12980
13003
  async function extractSymbols(lang, source) {
12981
13004
  const parser = await getParser(lang);
12982
13005
  const tree = parser.parse(source);
12983
13006
  if (!tree) {
12984
13007
  return [];
12985
13008
  }
12986
- const language = await getLanguage(lang);
12987
- const query = new Query(language, SYMBOL_QUERIES[lang]);
12988
- return symbolsFromMatches(query.matches(tree.rootNode));
13009
+ try {
13010
+ const query = await getQuery(lang);
13011
+ return symbolsFromMatches(query.matches(tree.rootNode));
13012
+ } finally {
13013
+ tree.delete();
13014
+ }
12989
13015
  }
13016
+ var queryCache;
12990
13017
  var init_symbols = __esm({
12991
13018
  "src/analyze/tree-sitter/symbols.ts"() {
12992
13019
  "use strict";
12993
13020
  init_parser();
12994
13021
  init_queries();
12995
13022
  init_extract();
13023
+ queryCache = /* @__PURE__ */ new Map();
12996
13024
  }
12997
13025
  });
12998
13026
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archme/cli",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Map your codebase into a living architecture diagram: run `archme init` in a repo to scan it, `archme daemon start` to keep it current on every commit.",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",