@archme/cli 0.8.1 → 0.8.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 +79 -45
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10005,9 +10005,23 @@ async function tailLog(opts = {}) {
|
|
|
10005
10005
|
await new Promise((resolve6, reject) => {
|
|
10006
10006
|
let fileWatcher = null;
|
|
10007
10007
|
let dirWatcher = null;
|
|
10008
|
+
let poller = null;
|
|
10009
|
+
let settled = false;
|
|
10008
10010
|
const dir = dirname7(path7);
|
|
10009
10011
|
const name = basename(path7);
|
|
10010
|
-
const
|
|
10012
|
+
const stop = () => {
|
|
10013
|
+
settled = true;
|
|
10014
|
+
fileWatcher?.close();
|
|
10015
|
+
dirWatcher?.close();
|
|
10016
|
+
if (poller) clearInterval(poller);
|
|
10017
|
+
process.removeListener("SIGINT", handleSigint);
|
|
10018
|
+
};
|
|
10019
|
+
const fail = (err2) => {
|
|
10020
|
+
if (settled) return;
|
|
10021
|
+
stop();
|
|
10022
|
+
reject(err2);
|
|
10023
|
+
};
|
|
10024
|
+
const readNew = async () => {
|
|
10011
10025
|
try {
|
|
10012
10026
|
const st = await stat(path7);
|
|
10013
10027
|
if (st.size < offset) offset = 0;
|
|
@@ -10020,61 +10034,50 @@ async function tailLog(opts = {}) {
|
|
|
10020
10034
|
});
|
|
10021
10035
|
offset = st.size;
|
|
10022
10036
|
}
|
|
10037
|
+
if (!fileWatcher && !settled) attachFileWatcher();
|
|
10023
10038
|
} catch (err2) {
|
|
10024
10039
|
if (err2.code === "ENOENT") return;
|
|
10025
|
-
|
|
10040
|
+
fail(err2);
|
|
10026
10041
|
}
|
|
10027
10042
|
};
|
|
10028
|
-
|
|
10029
|
-
|
|
10030
|
-
|
|
10031
|
-
|
|
10032
|
-
});
|
|
10033
|
-
} catch (err2) {
|
|
10034
|
-
if (err2.code !== "ENOENT") {
|
|
10035
|
-
reject(err2);
|
|
10036
|
-
return;
|
|
10037
|
-
}
|
|
10038
|
-
attachDirWatcher();
|
|
10039
|
-
}
|
|
10043
|
+
let chain = Promise.resolve();
|
|
10044
|
+
const drain = () => {
|
|
10045
|
+
if (settled) return;
|
|
10046
|
+
chain = chain.then(readNew);
|
|
10040
10047
|
};
|
|
10041
|
-
const
|
|
10048
|
+
const attachFileWatcher = () => {
|
|
10042
10049
|
try {
|
|
10043
|
-
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
10047
|
-
|
|
10048
|
-
attachFileWatcher();
|
|
10049
|
-
});
|
|
10050
|
-
}
|
|
10051
|
-
});
|
|
10052
|
-
} catch (err2) {
|
|
10053
|
-
reject(err2);
|
|
10050
|
+
fileWatcher = watch(path7, () => drain());
|
|
10051
|
+
dirWatcher?.close();
|
|
10052
|
+
dirWatcher = null;
|
|
10053
|
+
} catch {
|
|
10054
|
+
fileWatcher = null;
|
|
10054
10055
|
}
|
|
10055
10056
|
};
|
|
10056
|
-
|
|
10057
|
-
() =>
|
|
10058
|
-
|
|
10059
|
-
|
|
10060
|
-
|
|
10061
|
-
|
|
10062
|
-
|
|
10063
|
-
|
|
10064
|
-
}
|
|
10065
|
-
);
|
|
10057
|
+
try {
|
|
10058
|
+
dirWatcher = watch(dir, (_event, filename) => {
|
|
10059
|
+
if (filename === name) drain();
|
|
10060
|
+
});
|
|
10061
|
+
} catch (err2) {
|
|
10062
|
+
fail(err2);
|
|
10063
|
+
return;
|
|
10064
|
+
}
|
|
10066
10065
|
const handleSigint = () => {
|
|
10067
|
-
|
|
10068
|
-
|
|
10066
|
+
if (settled) return;
|
|
10067
|
+
stop();
|
|
10069
10068
|
resolve6();
|
|
10070
10069
|
};
|
|
10071
10070
|
process.once("SIGINT", handleSigint);
|
|
10071
|
+
poller = setInterval(drain, FOLLOW_POLL_MS);
|
|
10072
|
+
drain();
|
|
10072
10073
|
});
|
|
10073
10074
|
}
|
|
10075
|
+
var FOLLOW_POLL_MS;
|
|
10074
10076
|
var init_logs = __esm({
|
|
10075
10077
|
"src/daemon/service/logs.ts"() {
|
|
10076
10078
|
"use strict";
|
|
10077
10079
|
init_paths();
|
|
10080
|
+
FOLLOW_POLL_MS = 500;
|
|
10078
10081
|
}
|
|
10079
10082
|
});
|
|
10080
10083
|
|
|
@@ -13294,6 +13297,13 @@ var init_sequenceChapters = __esm({
|
|
|
13294
13297
|
}
|
|
13295
13298
|
});
|
|
13296
13299
|
|
|
13300
|
+
// ../shared/architectureDiff.ts
|
|
13301
|
+
var init_architectureDiff = __esm({
|
|
13302
|
+
"../shared/architectureDiff.ts"() {
|
|
13303
|
+
init_storyChanges();
|
|
13304
|
+
}
|
|
13305
|
+
});
|
|
13306
|
+
|
|
13297
13307
|
// ../shared/walkthrough.ts
|
|
13298
13308
|
var MAX_WALKTHROUGH_STEPS, MAX_STEP_TITLE_CHARS;
|
|
13299
13309
|
var init_walkthrough = __esm({
|
|
@@ -13301,6 +13311,7 @@ var init_walkthrough = __esm({
|
|
|
13301
13311
|
init_storyChanges();
|
|
13302
13312
|
init_sequenceChapters();
|
|
13303
13313
|
init_validationCodes();
|
|
13314
|
+
init_architectureDiff();
|
|
13304
13315
|
MAX_WALKTHROUGH_STEPS = 20;
|
|
13305
13316
|
MAX_STEP_TITLE_CHARS = 60;
|
|
13306
13317
|
}
|
|
@@ -13317,13 +13328,15 @@ var init_walkthroughGuidance = __esm({
|
|
|
13317
13328
|
- **Steps are in reading order, not build order.** This is not an implementation plan and not a restatement of your sequencing section \u2014 start where a reviewer should start, and put each step where it makes the next one make sense.
|
|
13318
13329
|
- **Group by idea.** One step is one coherent change, usually 3\u20138 elements. A one-element step is fine and often valuable: an independent fix that would otherwise be lost among the rest. Aim for a handful of steps; the cap is ${MAX_WALKTHROUGH_STEPS}.
|
|
13319
13330
|
- **Titles are terse** \u2014 a handle, not a summary. Under ${MAX_STEP_TITLE_CHARS} characters. \`Markers move per-repo\`, not \`This step explains how the source marker moves onto a per-repo table\`.
|
|
13320
|
-
- **
|
|
13321
|
-
-
|
|
13331
|
+
- **Every step gets a short description** \u2014 the narration a reader follows while the diagrams move beside it, one step at a time. Two or three plain sentences: what this part of the change is, why it exists, and how it fits the rest, at a high level. Example: \`This is the daemon picking up GitHub's answer after it posts a comment, review or approval on your behalf, and recording whether it worked.\`
|
|
13332
|
+
- Not prescriptive: describe the change, do not tell the reviewer what to check or what to think of it.
|
|
13333
|
+
- Not dense: no condensed paragraph of identifiers, flags and edge cases crammed into one sentence. Never restate the components, stories or connections the step already references \u2014 the reader is looking at them.
|
|
13334
|
+
- **Write it for someone meeting this change for the first time.** They know the system; they have NOT read your proposal body and were not in the design discussion. Say plainly what the step does and why it is there.
|
|
13322
13335
|
- Don't argue with objections the reader hasn't raised \u2014 no \`not just a nicety\`, no \`as discussed\`, no \`this is why it is its own step\`. They don't know how the walkthrough was assembled and haven't disagreed with you. A trade-off worth stating is information (\`X was considered; it breaks Y\`), not a rebuttal.
|
|
13323
13336
|
- Don't use the change's OWN new vocabulary undefined. If the step introduces a term, say what it means in the same breath or use plain words.
|
|
13324
13337
|
- Bad: \`A correctness item, not a phase-3 nicety: anchors are repo-relative paths, so two repos with the same conventional layout collide silently and seed stories from the wrong one.\`
|
|
13325
13338
|
- Good: \`With two repos in one project a path like src/index.ts exists in both, so looking up which component owns a changed file can return the wrong repo's. Each repo now records the container its code lives under, and lookups search only that subtree.\`
|
|
13326
|
-
- **Cover every story the change touches
|
|
13339
|
+
- **Cover every change** \u2014 every story, component and connection the change touches \u2014 or \`set_walkthrough\` rejects the walkthrough and lists what is missing. Guided mode walks the steps and nothing after them, so anything no step reaches is a change the reviewer never sees. A connection is covered when a step names it, names both of its components, or names a story page that draws it as an arrow. Name a connection inside a component as \`<component path>::<id>\` (\`daemon::session_auth->key_account\`); a root connection by its plain id.
|
|
13327
13340
|
- **Skip it for a small change.** A handful of elements needs no walkthrough; omit it rather than writing a step per element.
|
|
13328
13341
|
- **Prefer CHAPTERS to narrow a diagram.** If a story's sequence carries \`%% chapter: <id> | <Label>\` markers, name the ones your step covers as \`chapters: [{ story, chapter }]\`, using the **id**, never the label \u2014 ids are stable across a rename, labels are not. A chapter is a page break the story's author already wrote, so it is sharper than naming components, where one hub the step mentions decides the whole view.`;
|
|
13329
13342
|
}
|
|
@@ -16129,7 +16142,9 @@ function observeGithubPull(p) {
|
|
|
16129
16142
|
createdAt: p.created_at ?? null,
|
|
16130
16143
|
updatedAt: p.updated_at ?? null,
|
|
16131
16144
|
mergedAt: p.merged_at ?? null,
|
|
16132
|
-
closedAt: p.closed_at ?? null
|
|
16145
|
+
closedAt: p.closed_at ?? null,
|
|
16146
|
+
// Before the merge it is GitHub's throwaway test merge.
|
|
16147
|
+
mergeCommitSha: p.merged_at ? p.merge_commit_sha ?? null : null
|
|
16133
16148
|
};
|
|
16134
16149
|
}
|
|
16135
16150
|
function metaKey(o2) {
|
|
@@ -16164,6 +16179,7 @@ function toItem(o2, action, sent) {
|
|
|
16164
16179
|
created_at: o2.createdAt,
|
|
16165
16180
|
merged_at: o2.mergedAt,
|
|
16166
16181
|
closed_at: o2.closedAt,
|
|
16182
|
+
merge_commit_sha: o2.mergeCommitSha,
|
|
16167
16183
|
body: o2.body,
|
|
16168
16184
|
...action === "synchronize" && sent.seq !== void 0 ? { seq: sent.seq } : {}
|
|
16169
16185
|
};
|
|
@@ -16573,6 +16589,22 @@ var init_defaultBranch = __esm({
|
|
|
16573
16589
|
}
|
|
16574
16590
|
});
|
|
16575
16591
|
|
|
16592
|
+
// ../shared/prRefs.ts
|
|
16593
|
+
function pushCommitSubject(message) {
|
|
16594
|
+
if (message == null) return null;
|
|
16595
|
+
const [subject = "", ...body] = message.split("\n");
|
|
16596
|
+
const pr = MERGE_PR_SUBJECT.exec(subject.trim());
|
|
16597
|
+
const title = body.find((line) => line.trim())?.trim();
|
|
16598
|
+
return pr && title && !TRAILER_LINE.test(title) ? `${title} (#${pr[1]})` : subject;
|
|
16599
|
+
}
|
|
16600
|
+
var MERGE_PR_SUBJECT, TRAILER_LINE;
|
|
16601
|
+
var init_prRefs = __esm({
|
|
16602
|
+
"../shared/prRefs.ts"() {
|
|
16603
|
+
MERGE_PR_SUBJECT = /^Merge pull request #(\d+) from \S+$/;
|
|
16604
|
+
TRAILER_LINE = /^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+:\s/;
|
|
16605
|
+
}
|
|
16606
|
+
});
|
|
16607
|
+
|
|
16576
16608
|
// src/daemon/localGit.ts
|
|
16577
16609
|
var localGit_exports = {};
|
|
16578
16610
|
__export(localGit_exports, {
|
|
@@ -16641,13 +16673,14 @@ async function firstParentRange(dir, marker, tip) {
|
|
|
16641
16673
|
async function readCommitMeta(dir, sha) {
|
|
16642
16674
|
const { exitCode, stdout } = await git(
|
|
16643
16675
|
dir,
|
|
16644
|
-
|
|
16676
|
+
// %b last: it spans lines, and `pushCommitSubject` reads a merge commit's title from it.
|
|
16677
|
+
["show", "-s", "--format=%an%n%cI%n%s%n%b", sha],
|
|
16645
16678
|
{ allowFail: true }
|
|
16646
16679
|
);
|
|
16647
16680
|
if (exitCode !== 0) return { message: "", authorName: null, committedAt: null };
|
|
16648
|
-
const [
|
|
16681
|
+
const [authorName = "", committedAt = "", ...message] = stdout.split("\n");
|
|
16649
16682
|
return {
|
|
16650
|
-
message: message.trim(),
|
|
16683
|
+
message: (pushCommitSubject(message.join("\n")) ?? "").trim(),
|
|
16651
16684
|
authorName: authorName.trim() || null,
|
|
16652
16685
|
committedAt: committedAt.trim() || null
|
|
16653
16686
|
};
|
|
@@ -16676,6 +16709,7 @@ var init_localGit = __esm({
|
|
|
16676
16709
|
init_execa();
|
|
16677
16710
|
init_preflight();
|
|
16678
16711
|
init_defaultBranch();
|
|
16712
|
+
init_prRefs();
|
|
16679
16713
|
GIT_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
16680
16714
|
}
|
|
16681
16715
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@archme/cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.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",
|