@archme/cli 0.5.0 → 0.5.2
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/dist/cli.js +53 -11
- 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: "
|
|
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
|
-
|
|
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: "
|
|
12209
|
-
- Add under story group: storyUpdates: [{under: "auth", add: [{id: "login", title: "
|
|
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
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
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
|
|
|
@@ -13022,6 +13050,18 @@ async function outlineSource(source, file) {
|
|
|
13022
13050
|
data: { file, symbols: [] }
|
|
13023
13051
|
});
|
|
13024
13052
|
}
|
|
13053
|
+
const bytes = Buffer.byteLength(source, "utf8");
|
|
13054
|
+
if (bytes >= MAX_PARSE_BYTES) {
|
|
13055
|
+
return envelope({
|
|
13056
|
+
tool: "file",
|
|
13057
|
+
tier: 0,
|
|
13058
|
+
confidence: 0.2,
|
|
13059
|
+
data: { file, symbols: [] },
|
|
13060
|
+
warnings: [
|
|
13061
|
+
`${file} is too large to parse (${bytes} bytes >= ${MAX_PARSE_BYTES}); file-tier only`
|
|
13062
|
+
]
|
|
13063
|
+
});
|
|
13064
|
+
}
|
|
13025
13065
|
try {
|
|
13026
13066
|
const symbols = await extractSymbols(lang, source);
|
|
13027
13067
|
return envelope({
|
|
@@ -13064,12 +13104,14 @@ async function runOutline(file) {
|
|
|
13064
13104
|
}
|
|
13065
13105
|
return outlineSource(source, file);
|
|
13066
13106
|
}
|
|
13107
|
+
var MAX_PARSE_BYTES;
|
|
13067
13108
|
var init_outline = __esm({
|
|
13068
13109
|
"src/analyze/commands/outline.ts"() {
|
|
13069
13110
|
"use strict";
|
|
13070
13111
|
init_lang_detect();
|
|
13071
13112
|
init_symbols();
|
|
13072
13113
|
init_output2();
|
|
13114
|
+
MAX_PARSE_BYTES = 1e6;
|
|
13073
13115
|
}
|
|
13074
13116
|
});
|
|
13075
13117
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@archme/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
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",
|