nano-duoshe 0.1.0-alpha.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.
Files changed (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +282 -0
  3. package/README.zh-CN.md +285 -0
  4. package/dist/adapters/claude-md.d.ts +40 -0
  5. package/dist/adapters/claude-md.d.ts.map +1 -0
  6. package/dist/adapters/claude-md.js +108 -0
  7. package/dist/adapters/claude-md.js.map +1 -0
  8. package/dist/adapters/gitignore.d.ts +17 -0
  9. package/dist/adapters/gitignore.d.ts.map +1 -0
  10. package/dist/adapters/gitignore.js +49 -0
  11. package/dist/adapters/gitignore.js.map +1 -0
  12. package/dist/cli/assistant.d.ts +2 -0
  13. package/dist/cli/assistant.d.ts.map +1 -0
  14. package/dist/cli/assistant.js +36 -0
  15. package/dist/cli/assistant.js.map +1 -0
  16. package/dist/cli/commands/graph.d.ts +3 -0
  17. package/dist/cli/commands/graph.d.ts.map +1 -0
  18. package/dist/cli/commands/graph.js +97 -0
  19. package/dist/cli/commands/graph.js.map +1 -0
  20. package/dist/cli/commands/guide.d.ts +4 -0
  21. package/dist/cli/commands/guide.d.ts.map +1 -0
  22. package/dist/cli/commands/guide.js +118 -0
  23. package/dist/cli/commands/guide.js.map +1 -0
  24. package/dist/cli/commands/init.d.ts +3 -0
  25. package/dist/cli/commands/init.d.ts.map +1 -0
  26. package/dist/cli/commands/init.js +338 -0
  27. package/dist/cli/commands/init.js.map +1 -0
  28. package/dist/cli/commands/mcp.d.ts +3 -0
  29. package/dist/cli/commands/mcp.d.ts.map +1 -0
  30. package/dist/cli/commands/mcp.js +10 -0
  31. package/dist/cli/commands/mcp.js.map +1 -0
  32. package/dist/cli/commands/profile.d.ts +3 -0
  33. package/dist/cli/commands/profile.d.ts.map +1 -0
  34. package/dist/cli/commands/profile.js +91 -0
  35. package/dist/cli/commands/profile.js.map +1 -0
  36. package/dist/cli/commands/remember.d.ts +3 -0
  37. package/dist/cli/commands/remember.d.ts.map +1 -0
  38. package/dist/cli/commands/remember.js +110 -0
  39. package/dist/cli/commands/remember.js.map +1 -0
  40. package/dist/cli/commands/review.d.ts +3 -0
  41. package/dist/cli/commands/review.d.ts.map +1 -0
  42. package/dist/cli/commands/review.js +175 -0
  43. package/dist/cli/commands/review.js.map +1 -0
  44. package/dist/cli/commands/search.d.ts +3 -0
  45. package/dist/cli/commands/search.d.ts.map +1 -0
  46. package/dist/cli/commands/search.js +157 -0
  47. package/dist/cli/commands/search.js.map +1 -0
  48. package/dist/cli/commands/session.d.ts +3 -0
  49. package/dist/cli/commands/session.d.ts.map +1 -0
  50. package/dist/cli/commands/session.js +33 -0
  51. package/dist/cli/commands/session.js.map +1 -0
  52. package/dist/cli/commands/skill.d.ts +3 -0
  53. package/dist/cli/commands/skill.d.ts.map +1 -0
  54. package/dist/cli/commands/skill.js +81 -0
  55. package/dist/cli/commands/skill.js.map +1 -0
  56. package/dist/cli/commands/sync.d.ts +3 -0
  57. package/dist/cli/commands/sync.d.ts.map +1 -0
  58. package/dist/cli/commands/sync.js +43 -0
  59. package/dist/cli/commands/sync.js.map +1 -0
  60. package/dist/cli/commands/upgrade.d.ts +3 -0
  61. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  62. package/dist/cli/commands/upgrade.js +87 -0
  63. package/dist/cli/commands/upgrade.js.map +1 -0
  64. package/dist/cli/index.d.ts +3 -0
  65. package/dist/cli/index.d.ts.map +1 -0
  66. package/dist/cli/index.js +143 -0
  67. package/dist/cli/index.js.map +1 -0
  68. package/dist/cli/log.d.ts +10 -0
  69. package/dist/cli/log.d.ts.map +1 -0
  70. package/dist/cli/log.js +25 -0
  71. package/dist/cli/log.js.map +1 -0
  72. package/dist/cli/nudge-throttle.d.ts +2 -0
  73. package/dist/cli/nudge-throttle.d.ts.map +1 -0
  74. package/dist/cli/nudge-throttle.js +44 -0
  75. package/dist/cli/nudge-throttle.js.map +1 -0
  76. package/dist/cli/stub.d.ts +2 -0
  77. package/dist/cli/stub.d.ts.map +1 -0
  78. package/dist/cli/stub.js +6 -0
  79. package/dist/cli/stub.js.map +1 -0
  80. package/dist/core/candidate/id.d.ts +2 -0
  81. package/dist/core/candidate/id.d.ts.map +1 -0
  82. package/dist/core/candidate/id.js +7 -0
  83. package/dist/core/candidate/id.js.map +1 -0
  84. package/dist/core/candidate/index.d.ts +5 -0
  85. package/dist/core/candidate/index.d.ts.map +1 -0
  86. package/dist/core/candidate/index.js +5 -0
  87. package/dist/core/candidate/index.js.map +1 -0
  88. package/dist/core/candidate/publish.d.ts +12 -0
  89. package/dist/core/candidate/publish.d.ts.map +1 -0
  90. package/dist/core/candidate/publish.js +79 -0
  91. package/dist/core/candidate/publish.js.map +1 -0
  92. package/dist/core/candidate/store.d.ts +14 -0
  93. package/dist/core/candidate/store.d.ts.map +1 -0
  94. package/dist/core/candidate/store.js +117 -0
  95. package/dist/core/candidate/store.js.map +1 -0
  96. package/dist/core/candidate/target.d.ts +5 -0
  97. package/dist/core/candidate/target.d.ts.map +1 -0
  98. package/dist/core/candidate/target.js +28 -0
  99. package/dist/core/candidate/target.js.map +1 -0
  100. package/dist/core/index/db.d.ts +5 -0
  101. package/dist/core/index/db.d.ts.map +1 -0
  102. package/dist/core/index/db.js +21 -0
  103. package/dist/core/index/db.js.map +1 -0
  104. package/dist/core/index/index.d.ts +4 -0
  105. package/dist/core/index/index.d.ts.map +1 -0
  106. package/dist/core/index/index.js +4 -0
  107. package/dist/core/index/index.js.map +1 -0
  108. package/dist/core/index/indexer.d.ts +7 -0
  109. package/dist/core/index/indexer.d.ts.map +1 -0
  110. package/dist/core/index/indexer.js +90 -0
  111. package/dist/core/index/indexer.js.map +1 -0
  112. package/dist/core/index/schema.d.ts +3 -0
  113. package/dist/core/index/schema.d.ts.map +1 -0
  114. package/dist/core/index/schema.js +35 -0
  115. package/dist/core/index/schema.js.map +1 -0
  116. package/dist/core/index/search.d.ts +15 -0
  117. package/dist/core/index/search.d.ts.map +1 -0
  118. package/dist/core/index/search.js +107 -0
  119. package/dist/core/index/search.js.map +1 -0
  120. package/dist/core/index/sections.d.ts +9 -0
  121. package/dist/core/index/sections.d.ts.map +1 -0
  122. package/dist/core/index/sections.js +55 -0
  123. package/dist/core/index/sections.js.map +1 -0
  124. package/dist/core/index/tokenize.d.ts +3 -0
  125. package/dist/core/index/tokenize.d.ts.map +1 -0
  126. package/dist/core/index/tokenize.js +28 -0
  127. package/dist/core/index/tokenize.js.map +1 -0
  128. package/dist/core/profile/detect.d.ts +10 -0
  129. package/dist/core/profile/detect.d.ts.map +1 -0
  130. package/dist/core/profile/detect.js +211 -0
  131. package/dist/core/profile/detect.js.map +1 -0
  132. package/dist/core/scanner/filetree.d.ts +10 -0
  133. package/dist/core/scanner/filetree.d.ts.map +1 -0
  134. package/dist/core/scanner/filetree.js +263 -0
  135. package/dist/core/scanner/filetree.js.map +1 -0
  136. package/dist/core/scanner/git.d.ts +5 -0
  137. package/dist/core/scanner/git.d.ts.map +1 -0
  138. package/dist/core/scanner/git.js +131 -0
  139. package/dist/core/scanner/git.js.map +1 -0
  140. package/dist/core/scanner/index.d.ts +13 -0
  141. package/dist/core/scanner/index.d.ts.map +1 -0
  142. package/dist/core/scanner/index.js +32 -0
  143. package/dist/core/scanner/index.js.map +1 -0
  144. package/dist/core/scanner/stack.d.ts +9 -0
  145. package/dist/core/scanner/stack.d.ts.map +1 -0
  146. package/dist/core/scanner/stack.js +719 -0
  147. package/dist/core/scanner/stack.js.map +1 -0
  148. package/dist/core/skills/manager.d.ts +21 -0
  149. package/dist/core/skills/manager.d.ts.map +1 -0
  150. package/dist/core/skills/manager.js +138 -0
  151. package/dist/core/skills/manager.js.map +1 -0
  152. package/dist/core/types.d.ts +107 -0
  153. package/dist/core/types.d.ts.map +1 -0
  154. package/dist/core/types.js +22 -0
  155. package/dist/core/types.js.map +1 -0
  156. package/dist/core/update/check.d.ts +9 -0
  157. package/dist/core/update/check.d.ts.map +1 -0
  158. package/dist/core/update/check.js +135 -0
  159. package/dist/core/update/check.js.map +1 -0
  160. package/dist/core/vault/config.d.ts +10 -0
  161. package/dist/core/vault/config.d.ts.map +1 -0
  162. package/dist/core/vault/config.js +39 -0
  163. package/dist/core/vault/config.js.map +1 -0
  164. package/dist/core/vault/index.d.ts +17 -0
  165. package/dist/core/vault/index.d.ts.map +1 -0
  166. package/dist/core/vault/index.js +66 -0
  167. package/dist/core/vault/index.js.map +1 -0
  168. package/dist/core/vault/paths.d.ts +24 -0
  169. package/dist/core/vault/paths.d.ts.map +1 -0
  170. package/dist/core/vault/paths.js +28 -0
  171. package/dist/core/vault/paths.js.map +1 -0
  172. package/dist/core/vault/templates.d.ts +21 -0
  173. package/dist/core/vault/templates.d.ts.map +1 -0
  174. package/dist/core/vault/templates.js +357 -0
  175. package/dist/core/vault/templates.js.map +1 -0
  176. package/dist/core/version.d.ts +2 -0
  177. package/dist/core/version.d.ts.map +1 -0
  178. package/dist/core/version.js +26 -0
  179. package/dist/core/version.js.map +1 -0
  180. package/dist/index.d.ts +2 -0
  181. package/dist/index.d.ts.map +1 -0
  182. package/dist/index.js +2 -0
  183. package/dist/index.js.map +1 -0
  184. package/dist/skills/devops/README.md +27 -0
  185. package/dist/skills/devops/skill.json +22 -0
  186. package/dist/skills/embedded/README.md +23 -0
  187. package/dist/skills/embedded/skill.json +40 -0
  188. package/dist/skills/graph/analyzer.d.ts +16 -0
  189. package/dist/skills/graph/analyzer.d.ts.map +1 -0
  190. package/dist/skills/graph/analyzer.js +163 -0
  191. package/dist/skills/graph/analyzer.js.map +1 -0
  192. package/dist/skills/graph/index.d.ts +5 -0
  193. package/dist/skills/graph/index.d.ts.map +1 -0
  194. package/dist/skills/graph/index.js +31 -0
  195. package/dist/skills/graph/index.js.map +1 -0
  196. package/dist/skills/graph/skill.json +8 -0
  197. package/dist/skills/matlab/README.md +26 -0
  198. package/dist/skills/matlab/skill.json +22 -0
  199. package/dist/skills/wordpress/README.md +31 -0
  200. package/dist/skills/wordpress/skill.json +17 -0
  201. package/package.json +69 -0
@@ -0,0 +1,108 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ export const BEGIN_MARK = "<!-- BEGIN DUOSHE -->";
4
+ export const END_MARK = "<!-- END DUOSHE -->";
5
+ export const SHELL_FILES = ["CLAUDE.md", "AGENTS.md"];
6
+ export function buildShellBlock() {
7
+ return [
8
+ BEGIN_MARK,
9
+ "## Project Memory (managed by DuoShe)",
10
+ "",
11
+ "This project uses **DuoShe** for structured, traceable project memory.",
12
+ "Authoritative memory lives in `.duoshe/`:",
13
+ "",
14
+ "- `.duoshe/PROJECT.md` — project overview, tech stack, conventions",
15
+ "- `.duoshe/CODEMAP.md` — code graph, entry points, directory roles",
16
+ "- `.duoshe/DECISIONS.md` — architecture decisions (with rationale)",
17
+ "- `.duoshe/TROUBLESHOOTING.md` — known issues and how to fix them",
18
+ "- `.duoshe/MODULES.md` — module boundaries (what each part owns and does NOT own)",
19
+ "- `.duoshe/TODO.md` — current work and what's next",
20
+ "- `.duoshe/SKILLS/enabled/` — opt-in domain skills (embedded / matlab / devops / wordpress / graph)",
21
+ "",
22
+ "**Before answering questions about this project**, read the relevant `.duoshe/` files",
23
+ "for context — especially `PROJECT.md`, `DECISIONS.md`, and `MODULES.md`. If any",
24
+ "skills are enabled, their README in `.duoshe/SKILLS/enabled/<name>/README.md`",
25
+ "explains the domain-specific conventions and detectors that apply.",
26
+ "",
27
+ "**To capture new long-term memory** (decisions, gotchas, module rules), run:",
28
+ '`duoshe remember "..."` — this stages a candidate for the human to confirm,',
29
+ "rather than editing the Markdown files directly. After the human runs",
30
+ "`duoshe review` and `duoshe save <id>` (or `drop <id>`), the entry is",
31
+ "permanently recorded with a traceable footer.",
32
+ "",
33
+ "**Daily commands the user (and you) can run:**",
34
+ '- `duoshe remember "..."` — stage a candidate memory',
35
+ "- `duoshe review` — list pending candidates",
36
+ "- `duoshe save <id>` / `duoshe drop <id>` — promote or discard",
37
+ '- `duoshe search "..."` — FTS5 search over confirmed memory',
38
+ "",
39
+ "_This block is managed by DuoShe. Edit between the markers if you want — DuoShe will",
40
+ "preserve your edits and only warn on conflict. Run `duoshe uninstall` to remove cleanly._",
41
+ END_MARK,
42
+ ].join("\n");
43
+ }
44
+ function findBlockBounds(text) {
45
+ const start = text.indexOf(BEGIN_MARK);
46
+ if (start === -1)
47
+ return null;
48
+ const end = text.indexOf(END_MARK, start + BEGIN_MARK.length);
49
+ if (end === -1)
50
+ return null;
51
+ return { start, end: end + END_MARK.length };
52
+ }
53
+ function syncOne(filePath, file, opts) {
54
+ const block = buildShellBlock();
55
+ if (!existsSync(filePath)) {
56
+ if (!opts.createIfMissing) {
57
+ return { file, status: "skipped-no-existing", path: filePath };
58
+ }
59
+ const fresh = `# ${file === "CLAUDE.md" ? "Claude Code" : "Codex"} Instructions\n\n${block}\n`;
60
+ writeFileSync(filePath, fresh, "utf8");
61
+ return { file, status: "created", path: filePath };
62
+ }
63
+ const current = readFileSync(filePath, "utf8");
64
+ const bounds = findBlockBounds(current);
65
+ if (!bounds) {
66
+ const sep = current.endsWith("\n") ? "\n" : "\n\n";
67
+ const updated = `${current}${sep}${block}\n`;
68
+ writeFileSync(filePath, updated, "utf8");
69
+ return { file, status: "appended", path: filePath };
70
+ }
71
+ const existing = current.slice(bounds.start, bounds.end);
72
+ if (existing === block) {
73
+ return { file, status: "unchanged", path: filePath };
74
+ }
75
+ const updated = current.slice(0, bounds.start) + block + current.slice(bounds.end);
76
+ writeFileSync(filePath, updated, "utf8");
77
+ return { file, status: "updated", path: filePath };
78
+ }
79
+ export function syncShells(projectRoot, opts) {
80
+ return SHELL_FILES.map((f) => syncOne(join(projectRoot, f), f, opts));
81
+ }
82
+ export function uninstallShells(projectRoot) {
83
+ const results = [];
84
+ for (const file of SHELL_FILES) {
85
+ const path = join(projectRoot, file);
86
+ if (!existsSync(path)) {
87
+ results.push({ file, status: "skipped-no-existing", path });
88
+ continue;
89
+ }
90
+ const current = readFileSync(path, "utf8");
91
+ const bounds = findBlockBounds(current);
92
+ if (!bounds) {
93
+ results.push({ file, status: "unchanged", path });
94
+ continue;
95
+ }
96
+ let before = current.slice(0, bounds.start);
97
+ const after = current.slice(bounds.end);
98
+ before = before.replace(/\n+$/, "");
99
+ const cleaned = `${before}\n${after.replace(/^\n+/, "")}`.replace(/\n{3,}/g, "\n\n");
100
+ writeFileSync(path, cleaned.endsWith("\n") ? cleaned : `${cleaned}\n`, "utf8");
101
+ results.push({ file, status: "removed", path });
102
+ }
103
+ return results;
104
+ }
105
+ export function detectExistingShells(projectRoot) {
106
+ return SHELL_FILES.map((f) => ({ file: f, exists: existsSync(join(projectRoot, f)) }));
107
+ }
108
+ //# sourceMappingURL=claude-md.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-md.js","sourceRoot":"","sources":["../../src/adapters/claude-md.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export type GitignoreAction = {
2
+ status: "created";
3
+ path: string;
4
+ } | {
5
+ status: "appended";
6
+ path: string;
7
+ } | {
8
+ status: "updated";
9
+ path: string;
10
+ } | {
11
+ status: "unchanged";
12
+ path: string;
13
+ } | {
14
+ status: "skipped-no-repo";
15
+ };
16
+ export declare function syncGitignore(projectRoot: string): GitignoreAction;
17
+ //# sourceMappingURL=gitignore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../src/adapters/gitignore.ts"],"names":[],"mappings":"AA0BA,MAAM,MAAM,eAAe,GACvB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,MAAM,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAIlC,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAyBlE"}
@@ -0,0 +1,49 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ const BEGIN_MARK = "# BEGIN DUOSHE";
4
+ const END_MARK = "# END DUOSHE";
5
+ // Rules that should be private per-developer (NOT committed):
6
+ // - config.json holds local paths and per-machine preferences
7
+ // - CANDIDATES are unconfirmed drafts the user hasn't decided on
8
+ // - SESSIONS are private chat archives
9
+ // - index.db is a local FTS5 cache, regenerable
10
+ const RULE_BLOCK = `${BEGIN_MARK}
11
+ # DuoShe — local-only state (these stay on your machine).
12
+ # Public memory (PROJECT.md / DECISIONS.md / MODULES.md / TROUBLESHOOTING.md /
13
+ # TODO.md / SETUP.md / CODEMAP.md / SKILLS/) is meant to be committed —
14
+ # share it with your team and AI agents.
15
+ .duoshe/config.json
16
+ .duoshe/nudges.json
17
+ .duoshe/CANDIDATES/
18
+ .duoshe/SESSIONS/
19
+ .duoshe/index.db
20
+ .duoshe/index.db-journal
21
+ .duoshe/index.db-wal
22
+ .duoshe/index.db-shm
23
+ ${END_MARK}`;
24
+ // Idempotently keep the DuoShe block in the project's .gitignore.
25
+ // Only runs when `.git/` exists at the project root (so we don't pollute non-repo projects).
26
+ export function syncGitignore(projectRoot) {
27
+ if (!existsSync(join(projectRoot, ".git")))
28
+ return { status: "skipped-no-repo" };
29
+ const path = join(projectRoot, ".gitignore");
30
+ if (!existsSync(path)) {
31
+ writeFileSync(path, `${RULE_BLOCK}\n`, "utf8");
32
+ return { status: "created", path };
33
+ }
34
+ const current = readFileSync(path, "utf8");
35
+ const start = current.indexOf(BEGIN_MARK);
36
+ const end = current.indexOf(END_MARK);
37
+ if (start === -1 || end === -1) {
38
+ const sep = current.endsWith("\n") ? "\n" : "\n\n";
39
+ writeFileSync(path, `${current}${sep}${RULE_BLOCK}\n`, "utf8");
40
+ return { status: "appended", path };
41
+ }
42
+ const existingBlock = current.slice(start, end + END_MARK.length);
43
+ if (existingBlock === RULE_BLOCK)
44
+ return { status: "unchanged", path };
45
+ const updated = current.slice(0, start) + RULE_BLOCK + current.slice(end + END_MARK.length);
46
+ writeFileSync(path, updated, "utf8");
47
+ return { status: "updated", path };
48
+ }
49
+ //# sourceMappingURL=gitignore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../../src/adapters/gitignore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,GAAG,gBAAgB,CAAC;AACpC,MAAM,QAAQ,GAAG,cAAc,CAAC;AAEhC,8DAA8D;AAC9D,8DAA8D;AAC9D,iEAAiE;AACjE,uCAAuC;AACvC,gDAAgD;AAChD,MAAM,UAAU,GAAG,GAAG,UAAU;;;;;;;;;;;;;EAa9B,QAAQ,EAAE,CAAC;AASb,kEAAkE;AAClE,6FAA6F;AAC7F,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAEjF,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC7C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,aAAa,CAAC,IAAI,EAAE,GAAG,UAAU,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEtC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;QACnD,aAAa,CAAC,IAAI,EAAE,GAAG,OAAO,GAAG,GAAG,GAAG,UAAU,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClE,IAAI,aAAa,KAAK,UAAU;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAEvE,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC5F,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACrC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function nudgeAfterRemember(root: string, contentLength: number): void;
2
+ //# sourceMappingURL=assistant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../src/cli/assistant.ts"],"names":[],"mappings":"AAkBA,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CA6B5E"}
@@ -0,0 +1,36 @@
1
+ import kleur from "kleur";
2
+ import { CandidateStore } from "../core/candidate/index.js";
3
+ import { vaultExists } from "../core/vault/index.js";
4
+ import { log } from "./log.js";
5
+ import { shouldShowAndMark } from "./nudge-throttle.js";
6
+ function getPendingCount(root) {
7
+ try {
8
+ const store = new CandidateStore(root);
9
+ return store.listByStatus("pending").length;
10
+ }
11
+ catch {
12
+ return 0;
13
+ }
14
+ }
15
+ // Called after `duoshe remember` adds a candidate.
16
+ // Shows a one-time short-content warning and a pending-count reminder at
17
+ // thresholds 3 and 5+ to nudge the user toward `duoshe review`.
18
+ export function nudgeAfterRemember(root, contentLength) {
19
+ if (!vaultExists(root))
20
+ return;
21
+ if (contentLength < 20 && shouldShowAndMark(root, "short-content")) {
22
+ log.blank();
23
+ log.raw(kleur.gray(" 💬 这条记录有点短,AI 可能看不太懂。下次试试写得更完整一点(这条提醒今天就到这)。"));
24
+ return;
25
+ }
26
+ const pending = getPendingCount(root);
27
+ if (pending >= 5) {
28
+ log.blank();
29
+ log.raw(kleur.gray(` 💬 你已经有 ${pending} 条记录等着确认了。运行 ${kleur.cyan("duoshe review")} 确认一下。`));
30
+ }
31
+ else if (pending === 3) {
32
+ log.blank();
33
+ log.raw(kleur.gray(` 💬 现在有 3 条待确认的记录了。要不要现在 ${kleur.cyan("duoshe review")} 看一眼?`));
34
+ }
35
+ }
36
+ //# sourceMappingURL=assistant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assistant.js","sourceRoot":"","sources":["../../src/cli/assistant.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,SAAS,eAAe,CAAC,IAAY;IACnC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC;QACvC,OAAO,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,mDAAmD;AACnD,yEAAyE;AACzE,gEAAgE;AAChE,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,aAAqB;IACpE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAAE,OAAO;IAE/B,IAAI,aAAa,GAAG,EAAE,IAAI,iBAAiB,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC;QACnE,GAAG,CAAC,KAAK,EAAE,CAAC;QACZ,GAAG,CAAC,GAAG,CACL,KAAK,CAAC,IAAI,CACR,gDAAgD,CACjD,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,GAAG,CAAC,KAAK,EAAE,CAAC;QACZ,GAAG,CAAC,GAAG,CACL,KAAK,CAAC,IAAI,CACR,aAAa,OAAO,gBAAgB,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CACxE,CACF,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,KAAK,EAAE,CAAC;QACZ,GAAG,CAAC,GAAG,CACL,KAAK,CAAC,IAAI,CACR,6BAA6B,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAChE,CACF,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerGraphCommand(program: Command): void;
3
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/graph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6GzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAc3D"}
@@ -0,0 +1,97 @@
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
+ import kleur from "kleur";
3
+ import { readConfig } from "../../core/vault/config.js";
4
+ import { vaultExists, vaultPathsFor } from "../../core/vault/index.js";
5
+ import { analyzeGraph, renderMermaid } from "../../skills/graph/index.js";
6
+ import { log } from "../log.js";
7
+ const GRAPH_START = "<!-- BEGIN DUOSHE-GRAPH -->";
8
+ const GRAPH_END = "<!-- END DUOSHE-GRAPH -->";
9
+ function mergeGraphBlock(existing, block) {
10
+ if (existing.includes(GRAPH_START)) {
11
+ const before = existing.slice(0, existing.indexOf(GRAPH_START)).trimEnd();
12
+ const after = existing.slice(existing.indexOf(GRAPH_END) + GRAPH_END.length).trimStart();
13
+ return after ? `${before}\n\n${block}\n\n${after}` : `${before}\n\n${block}\n`;
14
+ }
15
+ return existing.trimEnd() ? `${existing.trimEnd()}\n\n${block}\n` : `${block}\n`;
16
+ }
17
+ async function runGraph(opts) {
18
+ const root = process.cwd();
19
+ if (!vaultExists(root)) {
20
+ log.err("这个目录还没有初始化。请先运行 `duoshe init`。");
21
+ process.exit(1);
22
+ }
23
+ const paths = vaultPathsFor(root);
24
+ const cfg = readConfig(paths.config);
25
+ if (cfg && !cfg.enabledSkills.includes("graph")) {
26
+ log.warn(`"graph" 技能还没启用。`);
27
+ log.raw(` 先启用:${kleur.cyan("duoshe skill enable graph")}`);
28
+ log.raw(` 查看所有技能:${kleur.cyan("duoshe skill list")}`);
29
+ process.exit(1);
30
+ }
31
+ log.step("分析代码依赖关系");
32
+ const start = Date.now();
33
+ const analysis = analyzeGraph(root);
34
+ const elapsed = Date.now() - start;
35
+ if (analysis.files.length === 0) {
36
+ log.warn("没扫描到任何源码文件。");
37
+ log.raw(kleur.gray(" 当前 graph 技能只支持 JavaScript / TypeScript(.ts/.tsx/.js/.jsx/.mjs/.cjs)。"));
38
+ log.raw(kleur.gray(" 其他语言(Go / Python / Rust / C/C++ / VHDL / Verilog / Terraform 等)的依赖分析还在路上。"));
39
+ return;
40
+ }
41
+ log.ok(`扫描了 ${analysis.files.length} 个源码文件,发现 ${analysis.edges.length} 条依赖关系(${elapsed}ms)`);
42
+ if (analysis.cycles.length > 0) {
43
+ log.warn(`发现 ${analysis.cycles.length} 个循环依赖:`);
44
+ for (const cycle of analysis.cycles.slice(0, 5)) {
45
+ log.raw(` ${kleur.yellow(cycle.join(" → "))}`);
46
+ }
47
+ if (analysis.cycles.length > 5) {
48
+ log.raw(` ${kleur.gray(`...还有 ${analysis.cycles.length - 5} 个`)}`);
49
+ }
50
+ }
51
+ else {
52
+ log.ok("没有循环依赖");
53
+ }
54
+ if (opts.hot !== false && analysis.hotNodes.length > 0) {
55
+ log.blank();
56
+ log.raw(kleur.bold("热点模块(被依赖最多):"));
57
+ for (const { file, inDegree } of analysis.hotNodes.slice(0, 5)) {
58
+ log.raw(` ${kleur.cyan(String(inDegree).padStart(3))} ${file}`);
59
+ }
60
+ }
61
+ const mermaid = renderMermaid(analysis);
62
+ if ((opts.output ?? "codemap") === "stdout") {
63
+ log.blank();
64
+ log.raw(mermaid);
65
+ return;
66
+ }
67
+ const block = `${GRAPH_START}\n## 代码依赖图\n\n\`\`\`mermaid\n${mermaid}\n\`\`\`\n\n_由 \`duoshe graph\` 于 ${new Date().toISOString()} 生成_\n${GRAPH_END}`;
68
+ let existing;
69
+ try {
70
+ existing = readFileSync(paths.codeMap, "utf8");
71
+ }
72
+ catch (err) {
73
+ if (err.code !== "ENOENT")
74
+ throw err;
75
+ existing = "";
76
+ }
77
+ writeFileSync(paths.codeMap, mergeGraphBlock(existing, block), "utf8");
78
+ log.blank();
79
+ log.ok(`已写入依赖图到 ${kleur.cyan(".duoshe/CODEMAP.md")}`);
80
+ }
81
+ export function registerGraphCommand(program) {
82
+ program
83
+ .command("graph")
84
+ .description("分析代码 import 依赖,生成依赖图写入 .duoshe/CODEMAP.md(需要先启用 graph 技能)")
85
+ .option("--output <模式>", "输出到哪:codemap(默认)| stdout", "codemap")
86
+ .option("--no-hot", "不显示热点模块")
87
+ .action(async (opts) => {
88
+ try {
89
+ await runGraph(opts);
90
+ }
91
+ catch (err) {
92
+ log.err(err instanceof Error ? err.message : String(err));
93
+ process.exit(1);
94
+ }
95
+ });
96
+ }
97
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../../src/cli/commands/graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Command } from "commander";
2
+ export declare function runGuide(root?: string): Promise<void>;
3
+ export declare function registerGuideCommand(program: Command): void;
4
+ //# sourceMappingURL=guide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guide.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/guide.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6FzC,wBAAsB,QAAQ,CAAC,IAAI,SAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BlE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAY3D"}
@@ -0,0 +1,118 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { createInterface } from "node:readline/promises";
3
+ import kleur from "kleur";
4
+ import { readConfig, writeConfig } from "../../core/vault/config.js";
5
+ import { vaultExists, vaultPathsFor } from "../../core/vault/index.js";
6
+ import { log } from "../log.js";
7
+ const BEGIN_GUIDE = "<!-- BEGIN DUOSHE-GUIDE -->";
8
+ const END_GUIDE = "<!-- END DUOSHE-GUIDE -->";
9
+ function splitList(answer) {
10
+ return answer
11
+ .split(/[;\n;]/)
12
+ .map((s) => s.trim())
13
+ .filter(Boolean);
14
+ }
15
+ function bulletList(items) {
16
+ if (items.length === 0)
17
+ return "- _(暂无)_";
18
+ return items.map((item) => `- ${item}`).join("\n");
19
+ }
20
+ function stripGuideSection(md) {
21
+ const start = md.indexOf(BEGIN_GUIDE);
22
+ const end = md.indexOf(END_GUIDE);
23
+ if (start === -1 || end === -1 || end < start)
24
+ return md.trimEnd();
25
+ return `${md.slice(0, start).trimEnd()}\n${md.slice(end + END_GUIDE.length).trimStart()}`.trimEnd();
26
+ }
27
+ function upsertGuideSection(path, title, body) {
28
+ const current = existsSync(path) ? readFileSync(path, "utf8") : "";
29
+ const base = stripGuideSection(current);
30
+ const section = `${BEGIN_GUIDE}\n\n## ${title}\n\n${body.trim()}\n\n${END_GUIDE}\n`;
31
+ writeFileSync(path, `${base}\n\n${section}`, "utf8");
32
+ }
33
+ function hasUsefulAnswer(a) {
34
+ return Boolean(a.overview || a.conventions.length || a.gotchas.length);
35
+ }
36
+ function renderProjectGuide(a) {
37
+ return [
38
+ "### 项目简介",
39
+ "",
40
+ a.overview || "_未填写。_",
41
+ "",
42
+ "### AI 必须记住的规矩",
43
+ "",
44
+ bulletList(a.conventions),
45
+ "",
46
+ "### 不要乱动的地方",
47
+ "",
48
+ bulletList(a.gotchas),
49
+ ].join("\n");
50
+ }
51
+ function hint(text) {
52
+ log.raw(kleur.gray(` 例:${text}`));
53
+ }
54
+ async function promptAnswers() {
55
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
56
+ try {
57
+ log.blank();
58
+ log.raw(kleur.bold(" 3 个小问题,帮 AI 认识这个项目"));
59
+ log.raw(kleur.gray(" 多个答案用分号隔开,不知道的直接回车跳过。"));
60
+ log.blank();
61
+ log.raw(kleur.bold(" 1. 这个项目是做什么的?给谁用?"));
62
+ hint("给中小电商团队用的库存管理后台,用户是仓库管理员");
63
+ const overview = (await rl.question(" > ")).trim();
64
+ log.blank();
65
+ log.raw(kleur.bold(" 2. 有什么规矩 AI 必须记住?"));
66
+ hint("数据库操作走 service 层,不能在 route 里直接查;错误码统一在 errors/codes.ts");
67
+ const conventions = splitList(await rl.question(" > "));
68
+ log.blank();
69
+ log.raw(kleur.bold(" 3. 有什么地方绝对不能乱动?"));
70
+ hint("发货状态机 shipping.ts;库存扣减的分布式锁逻辑");
71
+ const gotchas = splitList(await rl.question(" > "));
72
+ return { overview, conventions, gotchas };
73
+ }
74
+ finally {
75
+ rl.close();
76
+ }
77
+ }
78
+ export async function runGuide(root = process.cwd()) {
79
+ if (!vaultExists(root)) {
80
+ log.err("这个目录还没有初始化。请先运行 `duoshe init`。");
81
+ process.exit(1);
82
+ }
83
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
84
+ log.warn("问答模式需要在终端中运行。请直接运行 `duoshe guide`。");
85
+ return;
86
+ }
87
+ const answers = await promptAnswers();
88
+ if (!hasUsefulAnswer(answers)) {
89
+ log.blank();
90
+ log.info("没有填写任何内容,跳过保存。");
91
+ return;
92
+ }
93
+ const paths = vaultPathsFor(root);
94
+ upsertGuideSection(paths.project, "项目引导", renderProjectGuide(answers));
95
+ const cfg = readConfig(paths.config);
96
+ if (cfg) {
97
+ cfg.guideCompletedAt = new Date().toISOString();
98
+ writeConfig(paths.config, cfg);
99
+ }
100
+ log.blank();
101
+ log.ok("已写入 .duoshe/PROJECT.md。AI 下次进来就能看到这些内容了。");
102
+ log.raw(kleur.gray(' 之后想到什么,随时用 `duoshe remember "..."` 记一条。'));
103
+ }
104
+ export function registerGuideCommand(program) {
105
+ program
106
+ .command("guide")
107
+ .description("回答 3 个核心问题,让 AI 认识这个项目(1 分钟)")
108
+ .action(async () => {
109
+ try {
110
+ await runGuide();
111
+ }
112
+ catch (err) {
113
+ log.err(err instanceof Error ? err.message : String(err));
114
+ process.exit(1);
115
+ }
116
+ });
117
+ }
118
+ //# sourceMappingURL=guide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guide.js","sourceRoot":"","sources":["../../../src/cli/commands/guide.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerInitCommand(program: Command): void;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8UzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgD1D"}