@mrpatronz/nexusflow 1.3.3 → 1.6.0

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 (159) hide show
  1. package/README.md +50 -0
  2. package/dist/commands/create.d.ts.map +1 -1
  3. package/dist/commands/create.js +85 -44
  4. package/dist/commands/create.js.map +1 -1
  5. package/dist/commands/diff.d.ts.map +1 -1
  6. package/dist/commands/diff.js +16 -73
  7. package/dist/commands/diff.js.map +1 -1
  8. package/dist/commands/doctor.d.ts +4 -0
  9. package/dist/commands/doctor.d.ts.map +1 -1
  10. package/dist/commands/doctor.js +58 -318
  11. package/dist/commands/doctor.js.map +1 -1
  12. package/dist/commands/finish.d.ts +17 -0
  13. package/dist/commands/finish.d.ts.map +1 -0
  14. package/dist/commands/finish.js +173 -0
  15. package/dist/commands/finish.js.map +1 -0
  16. package/dist/commands/handoff.d.ts.map +1 -1
  17. package/dist/commands/handoff.js +11 -6
  18. package/dist/commands/handoff.js.map +1 -1
  19. package/dist/commands/knowledge.d.ts +36 -0
  20. package/dist/commands/knowledge.d.ts.map +1 -0
  21. package/dist/commands/knowledge.js +184 -0
  22. package/dist/commands/knowledge.js.map +1 -0
  23. package/dist/commands/open.d.ts.map +1 -1
  24. package/dist/commands/open.js +2 -4
  25. package/dist/commands/open.js.map +1 -1
  26. package/dist/commands/refresh.d.ts +2 -1
  27. package/dist/commands/refresh.d.ts.map +1 -1
  28. package/dist/commands/refresh.js +35 -2
  29. package/dist/commands/refresh.js.map +1 -1
  30. package/dist/commands/strategy.d.ts +37 -0
  31. package/dist/commands/strategy.d.ts.map +1 -0
  32. package/dist/commands/strategy.js +198 -0
  33. package/dist/commands/strategy.js.map +1 -0
  34. package/dist/core/commit.d.ts +41 -0
  35. package/dist/core/commit.d.ts.map +1 -0
  36. package/dist/core/commit.js +53 -0
  37. package/dist/core/commit.js.map +1 -0
  38. package/dist/core/config.d.ts +3 -1
  39. package/dist/core/config.d.ts.map +1 -1
  40. package/dist/core/config.js +60 -32
  41. package/dist/core/config.js.map +1 -1
  42. package/dist/core/config.test.js +24 -0
  43. package/dist/core/config.test.js.map +1 -1
  44. package/dist/core/diff.d.ts +27 -0
  45. package/dist/core/diff.d.ts.map +1 -0
  46. package/dist/core/diff.js +50 -0
  47. package/dist/core/diff.js.map +1 -0
  48. package/dist/core/doctor.d.ts +34 -0
  49. package/dist/core/doctor.d.ts.map +1 -0
  50. package/dist/core/doctor.js +276 -0
  51. package/dist/core/doctor.js.map +1 -0
  52. package/dist/core/finish.d.ts +56 -0
  53. package/dist/core/finish.d.ts.map +1 -0
  54. package/dist/core/finish.js +121 -0
  55. package/dist/core/finish.js.map +1 -0
  56. package/dist/core/finish.test.d.ts +2 -0
  57. package/dist/core/finish.test.d.ts.map +1 -0
  58. package/dist/core/finish.test.js +110 -0
  59. package/dist/core/finish.test.js.map +1 -0
  60. package/dist/core/knowledge.d.ts +96 -0
  61. package/dist/core/knowledge.d.ts.map +1 -0
  62. package/dist/core/knowledge.js +299 -0
  63. package/dist/core/knowledge.js.map +1 -0
  64. package/dist/core/knowledge.test.d.ts +2 -0
  65. package/dist/core/knowledge.test.d.ts.map +1 -0
  66. package/dist/core/knowledge.test.js +157 -0
  67. package/dist/core/knowledge.test.js.map +1 -0
  68. package/dist/core/refresh.test.d.ts +2 -0
  69. package/dist/core/refresh.test.d.ts.map +1 -0
  70. package/dist/core/refresh.test.js +67 -0
  71. package/dist/core/refresh.test.js.map +1 -0
  72. package/dist/core/status.d.ts +45 -0
  73. package/dist/core/status.d.ts.map +1 -0
  74. package/dist/core/status.js +45 -0
  75. package/dist/core/status.js.map +1 -0
  76. package/dist/core/sync.test.d.ts +2 -0
  77. package/dist/core/sync.test.d.ts.map +1 -0
  78. package/dist/core/sync.test.js +86 -0
  79. package/dist/core/sync.test.js.map +1 -0
  80. package/dist/core/workspace.create.test.d.ts +2 -0
  81. package/dist/core/workspace.create.test.d.ts.map +1 -0
  82. package/dist/core/workspace.create.test.js +95 -0
  83. package/dist/core/workspace.create.test.js.map +1 -0
  84. package/dist/core/workspace.d.ts +9 -3
  85. package/dist/core/workspace.d.ts.map +1 -1
  86. package/dist/core/workspace.js +91 -13
  87. package/dist/core/workspace.js.map +1 -1
  88. package/dist/core/worktree.d.ts +11 -1
  89. package/dist/core/worktree.d.ts.map +1 -1
  90. package/dist/core/worktree.js +2 -0
  91. package/dist/core/worktree.js.map +1 -1
  92. package/dist/core/worktree.test.d.ts +2 -0
  93. package/dist/core/worktree.test.d.ts.map +1 -0
  94. package/dist/core/worktree.test.js +111 -0
  95. package/dist/core/worktree.test.js.map +1 -0
  96. package/dist/generators/base.js +1 -1
  97. package/dist/generators/index.d.ts +7 -0
  98. package/dist/generators/index.d.ts.map +1 -1
  99. package/dist/generators/index.js +4 -1
  100. package/dist/generators/index.js.map +1 -1
  101. package/dist/index.js +205 -3
  102. package/dist/index.js.map +1 -1
  103. package/dist/mcp/server.d.ts.map +1 -1
  104. package/dist/mcp/server.js +51 -282
  105. package/dist/mcp/server.js.map +1 -1
  106. package/dist/mcp/tools.d.ts +45 -0
  107. package/dist/mcp/tools.d.ts.map +1 -0
  108. package/dist/mcp/tools.js +413 -0
  109. package/dist/mcp/tools.js.map +1 -0
  110. package/dist/server.d.ts.map +1 -1
  111. package/dist/server.js +43 -26
  112. package/dist/server.js.map +1 -1
  113. package/dist/utils/debug.d.ts +17 -0
  114. package/dist/utils/debug.d.ts.map +1 -0
  115. package/dist/utils/debug.js +25 -0
  116. package/dist/utils/debug.js.map +1 -0
  117. package/dist/utils/detect-ai.d.ts +14 -6
  118. package/dist/utils/detect-ai.d.ts.map +1 -1
  119. package/dist/utils/detect-ai.js +22 -9
  120. package/dist/utils/detect-ai.js.map +1 -1
  121. package/dist/utils/detect-ai.test.js +33 -0
  122. package/dist/utils/detect-ai.test.js.map +1 -1
  123. package/dist/utils/git.d.ts +13 -2
  124. package/dist/utils/git.d.ts.map +1 -1
  125. package/dist/utils/git.js +64 -5
  126. package/dist/utils/git.js.map +1 -1
  127. package/dist/utils/git.test.js +46 -8
  128. package/dist/utils/git.test.js.map +1 -1
  129. package/dist/utils/multi-git.d.ts +40 -0
  130. package/dist/utils/multi-git.d.ts.map +1 -1
  131. package/dist/utils/multi-git.js +80 -0
  132. package/dist/utils/multi-git.js.map +1 -1
  133. package/dist/utils/multi-git.test.js +54 -1
  134. package/dist/utils/multi-git.test.js.map +1 -1
  135. package/dist/utils/open-editor.d.ts +20 -0
  136. package/dist/utils/open-editor.d.ts.map +1 -0
  137. package/dist/utils/open-editor.js +44 -0
  138. package/dist/utils/open-editor.js.map +1 -0
  139. package/dist/utils/pr.d.ts +50 -0
  140. package/dist/utils/pr.d.ts.map +1 -0
  141. package/dist/utils/pr.js +144 -0
  142. package/dist/utils/pr.js.map +1 -0
  143. package/dist/utils/pr.test.d.ts +2 -0
  144. package/dist/utils/pr.test.d.ts.map +1 -0
  145. package/dist/utils/pr.test.js +47 -0
  146. package/dist/utils/pr.test.js.map +1 -0
  147. package/dist/utils/prompts.d.ts +22 -1
  148. package/dist/utils/prompts.d.ts.map +1 -1
  149. package/dist/utils/prompts.js +145 -24
  150. package/dist/utils/prompts.js.map +1 -1
  151. package/dist/utils/resolve-workspace.d.ts +30 -0
  152. package/dist/utils/resolve-workspace.d.ts.map +1 -0
  153. package/dist/utils/resolve-workspace.js +77 -0
  154. package/dist/utils/resolve-workspace.js.map +1 -0
  155. package/dist/utils/workflow-advisor.d.ts +2 -0
  156. package/dist/utils/workflow-advisor.d.ts.map +1 -1
  157. package/dist/utils/workflow-advisor.js +27 -4
  158. package/dist/utils/workflow-advisor.js.map +1 -1
  159. package/package.json +11 -11
@@ -0,0 +1,110 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { finishWorkspace } from './finish.js';
3
+ import * as status from './status.js';
4
+ import * as commit from './commit.js';
5
+ import * as multiGit from '../utils/multi-git.js';
6
+ import * as pr from '../utils/pr.js';
7
+ vi.mock('./status.js');
8
+ vi.mock('./commit.js');
9
+ vi.mock('../utils/multi-git.js');
10
+ vi.mock('../utils/pr.js');
11
+ function repo(overrides) {
12
+ return {
13
+ name: 'api',
14
+ path: '/ws/api',
15
+ branch: 'feat',
16
+ expectedBranch: 'feat',
17
+ onExpectedBranch: true,
18
+ dirty: false,
19
+ changedFiles: [],
20
+ ahead: 0,
21
+ behind: 0,
22
+ remoteUrl: 'https://github.com/o/api.git',
23
+ defaultBranch: 'main',
24
+ ...overrides,
25
+ };
26
+ }
27
+ function report(repos) {
28
+ return {
29
+ workspacePath: '/ws',
30
+ branchName: 'feat',
31
+ repos,
32
+ allClean: repos.every((r) => !r.dirty),
33
+ allPushed: repos.every((r) => r.ahead === 0),
34
+ };
35
+ }
36
+ describe('finishWorkspace', () => {
37
+ beforeEach(() => {
38
+ vi.clearAllMocks();
39
+ vi.mocked(pr.parseRemoteUrl).mockReturnValue({ host: 'github.com', owner: 'o', repo: 'api', kind: 'github' });
40
+ vi.mocked(pr.buildCompareUrl).mockReturnValue('https://github.com/o/api/compare/main...feat?expand=1');
41
+ vi.mocked(pr.detectGh).mockResolvedValue({ installed: false, authenticated: false });
42
+ vi.mocked(multiGit.pushRepo).mockResolvedValue({ success: true, message: 'pushed' });
43
+ });
44
+ it('does nothing to a clean, pushed repo and reports safe to cleanup', async () => {
45
+ const clean = report([repo({ dirty: false, ahead: 0 })]);
46
+ vi.mocked(status.getWorkspaceStatusReport).mockResolvedValue(clean);
47
+ const result = await finishWorkspace('/ws', {});
48
+ expect(commit.commitWorkspace).not.toHaveBeenCalled();
49
+ expect(multiGit.pushRepo).not.toHaveBeenCalled();
50
+ expect(result.safeToCleanup).toBe(true);
51
+ expect(result.repos[0].compareUrl).toContain('/compare/main...feat');
52
+ });
53
+ it('commits a dirty repo when given a message, then pushes', async () => {
54
+ const dirty = report([repo({ dirty: true, ahead: 0 })]);
55
+ const after = report([repo({ dirty: false, ahead: 0 })]);
56
+ vi.mocked(status.getWorkspaceStatusReport).mockResolvedValueOnce(dirty).mockResolvedValueOnce(after);
57
+ vi.mocked(commit.commitWorkspace).mockResolvedValue({
58
+ repos: [{ name: 'api', success: true, commitHash: 'abc1234', filesChanged: 2, message: 'ok' }],
59
+ committedCount: 1,
60
+ failedCount: 0,
61
+ });
62
+ const result = await finishWorkspace('/ws', { message: 'wip' });
63
+ expect(commit.commitWorkspace).toHaveBeenCalledWith('/ws', 'wip', { noPush: true, repos: ['api'] });
64
+ expect(multiGit.pushRepo).toHaveBeenCalledWith('/ws/api', 'feat');
65
+ expect(result.repos[0]).toMatchObject({ committed: true, commitHash: 'abc1234', pushed: true });
66
+ expect(result.safeToCleanup).toBe(true);
67
+ });
68
+ it('errors on a dirty repo when no message is provided', async () => {
69
+ const dirty = report([repo({ dirty: true })]);
70
+ vi.mocked(status.getWorkspaceStatusReport).mockResolvedValue(dirty);
71
+ const result = await finishWorkspace('/ws', {});
72
+ expect(commit.commitWorkspace).not.toHaveBeenCalled();
73
+ expect(result.repos[0].error).toMatch(/no commit message/i);
74
+ expect(result.safeToCleanup).toBe(false);
75
+ });
76
+ it('skips a repo checked out on the wrong branch', async () => {
77
+ const wrong = report([repo({ branch: 'main', onExpectedBranch: false, dirty: true })]);
78
+ vi.mocked(status.getWorkspaceStatusReport).mockResolvedValue(wrong);
79
+ const result = await finishWorkspace('/ws', { message: 'wip' });
80
+ expect(commit.commitWorkspace).not.toHaveBeenCalled();
81
+ expect(multiGit.pushRepo).not.toHaveBeenCalled();
82
+ expect(result.repos[0].skipped).toMatch(/not the feature branch/i);
83
+ });
84
+ it('pushes a never-pushed branch (ahead === null)', async () => {
85
+ const unpushed = report([repo({ dirty: false, ahead: null })]);
86
+ vi.mocked(status.getWorkspaceStatusReport).mockResolvedValue(unpushed);
87
+ const result = await finishWorkspace('/ws', {});
88
+ expect(multiGit.pushRepo).toHaveBeenCalledWith('/ws/api', 'feat');
89
+ expect(result.repos[0].pushed).toBe(true);
90
+ });
91
+ it('falls back to a compare URL when gh is unavailable and does not create a PR', async () => {
92
+ const unpushed = report([repo({ dirty: false, ahead: 2 })]);
93
+ vi.mocked(status.getWorkspaceStatusReport).mockResolvedValue(unpushed);
94
+ const result = await finishWorkspace('/ws', { createPrs: true });
95
+ expect(result.ghUsed).toBe(false);
96
+ expect(pr.createPrWithGh).not.toHaveBeenCalled();
97
+ expect(result.repos[0].compareUrl).toContain('/compare/main...feat');
98
+ expect(result.repos[0].prUrl).toBeUndefined();
99
+ });
100
+ it('creates a PR via gh when authenticated', async () => {
101
+ const unpushed = report([repo({ dirty: false, ahead: 2 })]);
102
+ vi.mocked(status.getWorkspaceStatusReport).mockResolvedValue(unpushed);
103
+ vi.mocked(pr.detectGh).mockResolvedValue({ installed: true, authenticated: true });
104
+ vi.mocked(pr.createPrWithGh).mockResolvedValue({ url: 'https://github.com/o/api/pull/7' });
105
+ const result = await finishWorkspace('/ws', { createPrs: true });
106
+ expect(result.ghUsed).toBe(true);
107
+ expect(result.repos[0].prUrl).toBe('https://github.com/o/api/pull/7');
108
+ });
109
+ });
110
+ //# sourceMappingURL=finish.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finish.test.js","sourceRoot":"","sources":["../../src/core/finish.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGrC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACvB,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACvB,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;AACjC,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AAE1B,SAAS,IAAI,CAAC,SAAoC;IAChD,OAAO;QACL,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,MAAM;QACd,cAAc,EAAE,MAAM;QACtB,gBAAgB,EAAE,IAAI;QACtB,KAAK,EAAE,KAAK;QACZ,YAAY,EAAE,EAAE;QAChB,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,8BAA8B;QACzC,aAAa,EAAE,MAAM;QACrB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,KAAyB;IACvC,OAAO;QACL,aAAa,EAAE,KAAK;QACpB,UAAU,EAAE,MAAM;QAClB,KAAK;QACL,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACtC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC;KAC7C,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC9G,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,eAAe,CAAC,uDAAuD,CAAC,CAAC;QACvG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,iBAAiB,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;QACrF,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,iBAAiB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACzD,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAEhD,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACtD,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACzD,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACrG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,iBAAiB,CAAC;YAClD,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC9F,cAAc,EAAE,CAAC;YACjB,WAAW,EAAE,CAAC;SACf,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAEhE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACpG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAClE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAChG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAEhD,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACvF,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAEhE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACtD,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/D,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAEvE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAEhD,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAClE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5D,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAEvE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEjE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACrE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5D,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACvE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,iBAAiB,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACnF,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,iBAAiB,CAAC,EAAE,GAAG,EAAE,iCAAiC,EAAE,CAAC,CAAC;QAE3F,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEjE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @module core/knowledge
3
+ * Single engine for capturing workspace/base knowledge, shared by the CLI
4
+ * `knowledge` command, the dashboard server, and the MCP `add_knowledge` /
5
+ * `promote_knowledge` tools.
6
+ *
7
+ * All file I/O routes through the active storage adapter (`core/storage.ts`)
8
+ * so the local, central-vault, and Obsidian backends keep working — the
9
+ * previous direct-`fs` knowledge routes silently wrote to a file the
10
+ * generators never read under the Obsidian adapter.
11
+ *
12
+ * The markdown helpers (`insertUnderHeading`, `formatEntry`,
13
+ * `parseKnowledgeEntries`) are pure and section-aware: they insert under the
14
+ * correct heading, tolerate leading YAML frontmatter (Obsidian) and CRLF, and
15
+ * never destroy existing content.
16
+ */
17
+ /** Categories of learning that can be captured. */
18
+ export type KnowledgeEntryType = 'decision' | 'gotcha' | 'progress' | 'assumption' | 'question';
19
+ /** A learning to record. */
20
+ export interface KnowledgeEntry {
21
+ type: KnowledgeEntryType;
22
+ message: string;
23
+ /** Short title, used for the heading of a `decision` entry. */
24
+ title?: string;
25
+ /** ISO timestamp; defaults to now. */
26
+ timestamp?: string;
27
+ }
28
+ /** Result of writing a knowledge entry. */
29
+ export interface KnowledgeWriteResult {
30
+ /** Storage-resolved location (adapter URL) of the file written. */
31
+ location: string;
32
+ /** The heading the entry landed under. */
33
+ section: string;
34
+ /** True when the file did not exist and was created. */
35
+ createdFile: boolean;
36
+ }
37
+ /** A parsed existing entry, used when promoting learnings. */
38
+ export interface ParsedKnowledgeEntry {
39
+ /** The `## ` section heading the entry was found under. */
40
+ section: string;
41
+ /** The category, or `null` when the section is not a recognized knowledge section. */
42
+ type: KnowledgeEntryType | null;
43
+ /** The raw markdown of the entry (a bullet line or a `### ` decision block). */
44
+ text: string;
45
+ }
46
+ /** Options for {@link promoteKnowledge}. */
47
+ export interface PromoteOptions {
48
+ repoName: string;
49
+ entries: ParsedKnowledgeEntry[];
50
+ /** `copy` (default) keeps the workspace entry; `move` replaces it with a note. */
51
+ mode?: 'copy' | 'move';
52
+ }
53
+ /** Result of {@link promoteKnowledge}. */
54
+ export interface PromoteResult {
55
+ promotedCount: number;
56
+ baseLocation: string;
57
+ }
58
+ /**
59
+ * Formats a {@link KnowledgeEntry} as the markdown snippet to insert.
60
+ *
61
+ * @param entry - The entry to format.
62
+ * @param _target - Reserved for target-specific formatting (currently identical).
63
+ */
64
+ export declare function formatEntry(entry: KnowledgeEntry, _target: 'workspace' | 'base'): string;
65
+ /**
66
+ * Inserts `entryMarkdown` under the first `## ` heading matching any of
67
+ * `headingAliases` (case-insensitive), stripping placeholder lines. When no
68
+ * matching heading exists, a new section is appended at end-of-file using the
69
+ * first alias. Existing content is never removed. CRLF line endings and a
70
+ * leading YAML frontmatter block are preserved.
71
+ *
72
+ * @returns The updated markdown.
73
+ */
74
+ export declare function insertUnderHeading(markdown: string, headingAliases: string[], entryMarkdown: string): string;
75
+ /**
76
+ * Parses a knowledge markdown document into individual entries: bullet lines
77
+ * and `### ` decision blocks, each tagged with its section and inferred type.
78
+ * Placeholder and comment lines are ignored.
79
+ */
80
+ export declare function parseKnowledgeEntries(markdown: string): ParsedKnowledgeEntry[];
81
+ /** Reads the workspace knowledge file, or `null` when it does not exist. */
82
+ export declare function readWorkspaceKnowledge(workspacePath: string): Promise<string | null>;
83
+ /** Reads a repo's base knowledge file, or `null` when it does not exist. */
84
+ export declare function readBaseKnowledge(workspacePath: string, repoName: string): Promise<string | null>;
85
+ /** Appends a formatted entry to the workspace knowledge file (creating it if missing). */
86
+ export declare function addWorkspaceKnowledge(workspacePath: string, entry: KnowledgeEntry): Promise<KnowledgeWriteResult>;
87
+ /** Appends a formatted entry to a repo's base knowledge file (creating it if missing). */
88
+ export declare function addBaseKnowledge(workspacePath: string, repoName: string, entry: KnowledgeEntry): Promise<KnowledgeWriteResult>;
89
+ /**
90
+ * Promotes selected workspace learnings into a repo's persistent base
91
+ * knowledge so they survive across features. Entries whose type is not
92
+ * promotable (progress, question) are skipped. In `move` mode the source entry
93
+ * in the workspace file is replaced with an auditable "promoted" note.
94
+ */
95
+ export declare function promoteKnowledge(workspacePath: string, options: PromoteOptions): Promise<PromoteResult>;
96
+ //# sourceMappingURL=knowledge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge.d.ts","sourceRoot":"","sources":["../../src/core/knowledge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAoBH,mDAAmD;AACnD,MAAM,MAAM,kBAAkB,GAC1B,UAAU,GACV,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,UAAU,CAAC;AAEf,4BAA4B;AAC5B,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,2CAA2C;AAC3C,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,8DAA8D;AAC9D,MAAM,WAAW,oBAAoB;IACnC,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAChC,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAChC,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,0CAA0C;AAC1C,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAqDD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,MAAM,CAiBxF;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EAAE,EACxB,aAAa,EAAE,MAAM,GACpB,MAAM,CAgDR;AAiBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAiD9E;AAeD,4EAA4E;AAC5E,wBAAsB,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAM1F;AAED,4EAA4E;AAC5E,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAKxB;AAED,0FAA0F;AAC1F,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,oBAAoB,CAAC,CAiB/B;AA+BD,0FAA0F;AAC1F,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,oBAAoB,CAAC,CAG/B;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA2BxB"}
@@ -0,0 +1,299 @@
1
+ /**
2
+ * @module core/knowledge
3
+ * Single engine for capturing workspace/base knowledge, shared by the CLI
4
+ * `knowledge` command, the dashboard server, and the MCP `add_knowledge` /
5
+ * `promote_knowledge` tools.
6
+ *
7
+ * All file I/O routes through the active storage adapter (`core/storage.ts`)
8
+ * so the local, central-vault, and Obsidian backends keep working — the
9
+ * previous direct-`fs` knowledge routes silently wrote to a file the
10
+ * generators never read under the Obsidian adapter.
11
+ *
12
+ * The markdown helpers (`insertUnderHeading`, `formatEntry`,
13
+ * `parseKnowledgeEntries`) are pure and section-aware: they insert under the
14
+ * correct heading, tolerate leading YAML frontmatter (Obsidian) and CRLF, and
15
+ * never destroy existing content.
16
+ */
17
+ import * as path from 'node:path';
18
+ import { loadFeatureConfig } from './workspace.js';
19
+ import { readWorkspaceFile, writeWorkspaceFile, workspaceFileExists, resolveWorkspaceFileUrl, readBaseFile, writeBaseFile, baseFileExists, resolveBaseFileUrl, } from './storage.js';
20
+ import { buildBaseKnowledgeContent } from '../generators/index.js';
21
+ /** The knowledge filename used for both the workspace and base layers. */
22
+ const KNOWLEDGE_FILE = 'nexusflow-knowledge.md';
23
+ /**
24
+ * Heading aliases per entry type for the workspace and base knowledge files.
25
+ * The first alias is the canonical heading used when the section is missing.
26
+ * `base: null` means the type is not promotable to base knowledge.
27
+ */
28
+ const SECTION_ALIASES = {
29
+ decision: {
30
+ workspace: ['Architecture Decisions'],
31
+ base: ['Architecture Decisions'],
32
+ },
33
+ gotcha: {
34
+ workspace: ['Known Gotchas', 'Discovered Gotchas & Watch-outs', 'Discovered Gotchas'],
35
+ base: ['Discovered Gotchas & Watch-outs', 'Known Gotchas', 'Discovered Gotchas'],
36
+ },
37
+ progress: {
38
+ workspace: ['Implementation Progress'],
39
+ base: null,
40
+ },
41
+ assumption: {
42
+ workspace: ['Project Assumptions (verify with user)', 'Project Assumptions'],
43
+ base: ['Coding Conventions & Invariants'],
44
+ },
45
+ question: {
46
+ workspace: ['Clarifying Questions for the User', 'Clarifying Questions'],
47
+ base: null,
48
+ },
49
+ };
50
+ // ─── Pure markdown helpers ──────────────────────────────────────────────────
51
+ /** True for template placeholder lines that should be replaced by real content. */
52
+ function isPlaceholder(line) {
53
+ const t = line.trim();
54
+ if (!t)
55
+ return false;
56
+ if (/^_\(.*\)_$/.test(t))
57
+ return true; // e.g. _(No gotchas recorded yet.)_
58
+ if (/^-\s*None recorded yet\.?$/i.test(t))
59
+ return true;
60
+ return false;
61
+ }
62
+ function todayIso() {
63
+ return new Date().toISOString().slice(0, 10);
64
+ }
65
+ function truncateHeading(text, max = 60) {
66
+ const oneLine = text.replace(/\s+/g, ' ').trim();
67
+ return oneLine.length <= max ? oneLine : `${oneLine.slice(0, max).trimEnd()}…`;
68
+ }
69
+ /**
70
+ * Formats a {@link KnowledgeEntry} as the markdown snippet to insert.
71
+ *
72
+ * @param entry - The entry to format.
73
+ * @param _target - Reserved for target-specific formatting (currently identical).
74
+ */
75
+ export function formatEntry(entry, _target) {
76
+ const date = (entry.timestamp ?? new Date().toISOString()).slice(0, 10);
77
+ const msg = entry.message.trim();
78
+ switch (entry.type) {
79
+ case 'decision': {
80
+ const heading = entry.title?.trim() ? entry.title.trim() : truncateHeading(msg);
81
+ return `### ${date} — ${heading}\n**Decision:** ${msg}`;
82
+ }
83
+ case 'progress':
84
+ return `- [x] ${date} — ${msg}`;
85
+ case 'gotcha':
86
+ case 'assumption':
87
+ case 'question':
88
+ default:
89
+ return `- **${date}:** ${msg}`;
90
+ }
91
+ }
92
+ /**
93
+ * Inserts `entryMarkdown` under the first `## ` heading matching any of
94
+ * `headingAliases` (case-insensitive), stripping placeholder lines. When no
95
+ * matching heading exists, a new section is appended at end-of-file using the
96
+ * first alias. Existing content is never removed. CRLF line endings and a
97
+ * leading YAML frontmatter block are preserved.
98
+ *
99
+ * @returns The updated markdown.
100
+ */
101
+ export function insertUnderHeading(markdown, headingAliases, entryMarkdown) {
102
+ const eol = markdown.includes('\r\n') ? '\r\n' : '\n';
103
+ const lines = markdown.split(/\r?\n/);
104
+ const aliasSet = new Set(headingAliases.map((a) => a.trim().toLowerCase()));
105
+ // Find the target section heading.
106
+ let headingIdx = -1;
107
+ for (let i = 0; i < lines.length; i++) {
108
+ const m = lines[i].match(/^##\s+(.*)$/);
109
+ if (m && aliasSet.has(m[1].trim().toLowerCase())) {
110
+ headingIdx = i;
111
+ break;
112
+ }
113
+ }
114
+ const entryLines = entryMarkdown.split(/\r?\n/);
115
+ if (headingIdx === -1) {
116
+ // Append a fresh section at end-of-file.
117
+ const trimmed = lines.join(eol).replace(/\s+$/, '');
118
+ const prefix = trimmed.length > 0 ? `${trimmed}${eol}${eol}` : '';
119
+ return `${prefix}## ${headingAliases[0]}${eol}${eol}${entryLines.join(eol)}${eol}`;
120
+ }
121
+ // Determine the section body range: until the next h1/h2 or EOF.
122
+ let sectionEnd = lines.length;
123
+ for (let i = headingIdx + 1; i < lines.length; i++) {
124
+ if (/^#{1,2}\s/.test(lines[i])) {
125
+ sectionEnd = i;
126
+ break;
127
+ }
128
+ }
129
+ const before = lines.slice(0, headingIdx + 1);
130
+ const after = lines.slice(sectionEnd);
131
+ // Keep comments and real content; drop placeholders and trailing blanks.
132
+ const body = lines.slice(headingIdx + 1, sectionEnd).filter((l) => !isPlaceholder(l));
133
+ while (body.length > 0 && body[body.length - 1].trim() === '') {
134
+ body.pop();
135
+ }
136
+ // One blank line between the heading (or existing content) and the new entry.
137
+ const newSection = [...before, ...body, '', ...entryLines, ''];
138
+ // Preserve a single blank line before the next section, if any.
139
+ const tail = after.length > 0 ? [...after] : [];
140
+ return [...newSection, ...tail].join(eol);
141
+ }
142
+ /** Reverse lookup: which entry type owns a given `## ` heading, if any. */
143
+ function sectionType(heading) {
144
+ const h = heading.trim().toLowerCase();
145
+ for (const [type, aliases] of Object.entries(SECTION_ALIASES)) {
146
+ const all = [...aliases.workspace, ...(aliases.base ?? [])];
147
+ if (all.some((a) => a.toLowerCase() === h)) {
148
+ return type;
149
+ }
150
+ }
151
+ return null;
152
+ }
153
+ /**
154
+ * Parses a knowledge markdown document into individual entries: bullet lines
155
+ * and `### ` decision blocks, each tagged with its section and inferred type.
156
+ * Placeholder and comment lines are ignored.
157
+ */
158
+ export function parseKnowledgeEntries(markdown) {
159
+ const lines = markdown.split(/\r?\n/);
160
+ const entries = [];
161
+ let currentSection = '';
162
+ let currentType = null;
163
+ let decisionBuffer = null;
164
+ const flushDecision = () => {
165
+ if (decisionBuffer) {
166
+ const text = decisionBuffer.join('\n').trim();
167
+ if (text)
168
+ entries.push({ section: currentSection, type: currentType, text });
169
+ decisionBuffer = null;
170
+ }
171
+ };
172
+ for (const line of lines) {
173
+ const h2 = line.match(/^##\s+(.*)$/);
174
+ if (h2) {
175
+ flushDecision();
176
+ currentSection = h2[1].trim();
177
+ currentType = sectionType(currentSection);
178
+ continue;
179
+ }
180
+ if (/^#\s+/.test(line)) {
181
+ flushDecision();
182
+ currentSection = '';
183
+ currentType = null;
184
+ continue;
185
+ }
186
+ if (line.startsWith('### ')) {
187
+ flushDecision();
188
+ decisionBuffer = [line];
189
+ continue;
190
+ }
191
+ if (decisionBuffer) {
192
+ decisionBuffer.push(line);
193
+ continue;
194
+ }
195
+ const t = line.trim();
196
+ if (t.startsWith('- ') && !isPlaceholder(line)) {
197
+ entries.push({ section: currentSection, type: currentType, text: t });
198
+ }
199
+ }
200
+ flushDecision();
201
+ return entries;
202
+ }
203
+ // ─── Adapter-routed I/O ─────────────────────────────────────────────────────
204
+ async function resolveFeatureId(workspacePath) {
205
+ const feature = await loadFeatureConfig(workspacePath);
206
+ return feature?.id ?? path.basename(workspacePath);
207
+ }
208
+ function assertMessage(message) {
209
+ if (!message || !message.trim()) {
210
+ throw new Error('Knowledge entry message cannot be empty.');
211
+ }
212
+ }
213
+ /** Reads the workspace knowledge file, or `null` when it does not exist. */
214
+ export async function readWorkspaceKnowledge(workspacePath) {
215
+ const featureId = await resolveFeatureId(workspacePath);
216
+ if (!(await workspaceFileExists(workspacePath, featureId, KNOWLEDGE_FILE))) {
217
+ return null;
218
+ }
219
+ return readWorkspaceFile(workspacePath, featureId, KNOWLEDGE_FILE);
220
+ }
221
+ /** Reads a repo's base knowledge file, or `null` when it does not exist. */
222
+ export async function readBaseKnowledge(workspacePath, repoName) {
223
+ if (!(await baseFileExists(workspacePath, repoName, KNOWLEDGE_FILE))) {
224
+ return null;
225
+ }
226
+ return readBaseFile(workspacePath, repoName, KNOWLEDGE_FILE);
227
+ }
228
+ /** Appends a formatted entry to the workspace knowledge file (creating it if missing). */
229
+ export async function addWorkspaceKnowledge(workspacePath, entry) {
230
+ assertMessage(entry.message);
231
+ const featureId = await resolveFeatureId(workspacePath);
232
+ const exists = await workspaceFileExists(workspacePath, featureId, KNOWLEDGE_FILE);
233
+ const content = exists
234
+ ? await readWorkspaceFile(workspacePath, featureId, KNOWLEDGE_FILE)
235
+ : `# Workspace Knowledge — ${featureId}\n`;
236
+ const aliases = SECTION_ALIASES[entry.type].workspace;
237
+ const updated = insertUnderHeading(content, aliases, formatEntry(entry, 'workspace'));
238
+ await writeWorkspaceFile(workspacePath, featureId, KNOWLEDGE_FILE, updated);
239
+ return {
240
+ location: resolveWorkspaceFileUrl(workspacePath, featureId, KNOWLEDGE_FILE),
241
+ section: aliases[0],
242
+ createdFile: !exists,
243
+ };
244
+ }
245
+ /**
246
+ * Inserts already-formatted markdown under a repo's base knowledge section for
247
+ * the given type (creating the file if missing).
248
+ */
249
+ async function insertIntoBase(workspacePath, repoName, type, entryMarkdown) {
250
+ const aliases = SECTION_ALIASES[type].base;
251
+ if (!aliases) {
252
+ throw new Error(`'${type}' entries cannot be stored in base (repo) knowledge.`);
253
+ }
254
+ const exists = await baseFileExists(workspacePath, repoName, KNOWLEDGE_FILE);
255
+ const content = exists
256
+ ? await readBaseFile(workspacePath, repoName, KNOWLEDGE_FILE)
257
+ : buildBaseKnowledgeContent(repoName);
258
+ const updated = insertUnderHeading(content, aliases, entryMarkdown);
259
+ await writeBaseFile(workspacePath, repoName, KNOWLEDGE_FILE, updated);
260
+ return {
261
+ location: resolveBaseFileUrl(workspacePath, repoName, KNOWLEDGE_FILE),
262
+ section: aliases[0],
263
+ createdFile: !exists,
264
+ };
265
+ }
266
+ /** Appends a formatted entry to a repo's base knowledge file (creating it if missing). */
267
+ export async function addBaseKnowledge(workspacePath, repoName, entry) {
268
+ assertMessage(entry.message);
269
+ return insertIntoBase(workspacePath, repoName, entry.type, formatEntry(entry, 'base'));
270
+ }
271
+ /**
272
+ * Promotes selected workspace learnings into a repo's persistent base
273
+ * knowledge so they survive across features. Entries whose type is not
274
+ * promotable (progress, question) are skipped. In `move` mode the source entry
275
+ * in the workspace file is replaced with an auditable "promoted" note.
276
+ */
277
+ export async function promoteKnowledge(workspacePath, options) {
278
+ const { repoName, entries, mode = 'copy' } = options;
279
+ const promotable = entries.filter((e) => e.type && SECTION_ALIASES[e.type].base);
280
+ let baseLocation = resolveBaseFileUrl(workspacePath, repoName, KNOWLEDGE_FILE);
281
+ for (const e of promotable) {
282
+ // Preserve the entry's original markdown rather than reformatting it.
283
+ const res = await insertIntoBase(workspacePath, repoName, e.type, e.text);
284
+ baseLocation = res.location;
285
+ }
286
+ if (mode === 'move' && promotable.length > 0) {
287
+ const featureId = await resolveFeatureId(workspacePath);
288
+ if (await workspaceFileExists(workspacePath, featureId, KNOWLEDGE_FILE)) {
289
+ let content = await readWorkspaceFile(workspacePath, featureId, KNOWLEDGE_FILE);
290
+ const date = todayIso();
291
+ for (const e of promotable) {
292
+ content = content.replace(e.text, `- Promoted to ${repoName} base knowledge on ${date}.`);
293
+ }
294
+ await writeWorkspaceFile(workspacePath, featureId, KNOWLEDGE_FILE, content);
295
+ }
296
+ }
297
+ return { promotedCount: promotable.length, baseLocation };
298
+ }
299
+ //# sourceMappingURL=knowledge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge.js","sourceRoot":"","sources":["../../src/core/knowledge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=knowledge.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge.test.d.ts","sourceRoot":"","sources":["../../src/core/knowledge.test.ts"],"names":[],"mappings":""}