chapterhouse 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +363 -0
  3. package/agents/chapterhouse.agent.md +40 -0
  4. package/agents/coder.agent.md +38 -0
  5. package/agents/designer.agent.md +43 -0
  6. package/agents/general-purpose.agent.md +30 -0
  7. package/dist/api/auth.js +159 -0
  8. package/dist/api/auth.test.js +463 -0
  9. package/dist/api/errors.js +95 -0
  10. package/dist/api/errors.test.js +89 -0
  11. package/dist/api/rate-limit.js +85 -0
  12. package/dist/api/server-runtime.js +62 -0
  13. package/dist/api/server.js +651 -0
  14. package/dist/api/server.test.js +385 -0
  15. package/dist/api/sse.integration.test.js +270 -0
  16. package/dist/api/sse.js +7 -0
  17. package/dist/api/team.js +196 -0
  18. package/dist/api/team.test.js +466 -0
  19. package/dist/cli.js +102 -0
  20. package/dist/config.js +299 -0
  21. package/dist/config.phase3.test.js +20 -0
  22. package/dist/config.test.js +148 -0
  23. package/dist/copilot/agents.js +447 -0
  24. package/dist/copilot/agents.squad.test.js +72 -0
  25. package/dist/copilot/classifier.js +72 -0
  26. package/dist/copilot/client.js +32 -0
  27. package/dist/copilot/client.test.js +100 -0
  28. package/dist/copilot/episode-writer.js +219 -0
  29. package/dist/copilot/episode-writer.test.js +41 -0
  30. package/dist/copilot/mcp-config.js +22 -0
  31. package/dist/copilot/okr-mapper.js +196 -0
  32. package/dist/copilot/okr-mapper.test.js +114 -0
  33. package/dist/copilot/orchestrator.js +685 -0
  34. package/dist/copilot/orchestrator.test.js +523 -0
  35. package/dist/copilot/router.js +142 -0
  36. package/dist/copilot/router.test.js +119 -0
  37. package/dist/copilot/skills.js +125 -0
  38. package/dist/copilot/standup.js +138 -0
  39. package/dist/copilot/standup.test.js +132 -0
  40. package/dist/copilot/system-message.js +143 -0
  41. package/dist/copilot/system-message.test.js +17 -0
  42. package/dist/copilot/tools.js +1212 -0
  43. package/dist/copilot/tools.okr.test.js +260 -0
  44. package/dist/copilot/tools.squad.test.js +168 -0
  45. package/dist/daemon.js +235 -0
  46. package/dist/home-path.js +12 -0
  47. package/dist/home-path.test.js +11 -0
  48. package/dist/integrations/ado-analytics.js +178 -0
  49. package/dist/integrations/ado-analytics.test.js +284 -0
  50. package/dist/integrations/ado-client.js +227 -0
  51. package/dist/integrations/ado-client.test.js +176 -0
  52. package/dist/integrations/ado-schema.js +25 -0
  53. package/dist/integrations/ado-schema.test.js +39 -0
  54. package/dist/integrations/ado-skill.js +55 -0
  55. package/dist/integrations/report-generator.js +114 -0
  56. package/dist/integrations/report-generator.test.js +62 -0
  57. package/dist/integrations/team-push.js +144 -0
  58. package/dist/integrations/team-push.test.js +178 -0
  59. package/dist/integrations/teams-notify.js +108 -0
  60. package/dist/integrations/teams-notify.test.js +135 -0
  61. package/dist/paths.js +41 -0
  62. package/dist/setup.js +149 -0
  63. package/dist/shutdown-signals.js +13 -0
  64. package/dist/shutdown-signals.test.js +33 -0
  65. package/dist/squad/charter.js +108 -0
  66. package/dist/squad/charter.test.js +89 -0
  67. package/dist/squad/context.js +48 -0
  68. package/dist/squad/context.test.js +59 -0
  69. package/dist/squad/discovery.js +280 -0
  70. package/dist/squad/discovery.test.js +93 -0
  71. package/dist/squad/index.js +7 -0
  72. package/dist/squad/mirror.js +81 -0
  73. package/dist/squad/mirror.scheduler.js +78 -0
  74. package/dist/squad/mirror.scheduler.test.js +197 -0
  75. package/dist/squad/mirror.test.js +172 -0
  76. package/dist/squad/registry.js +162 -0
  77. package/dist/squad/registry.test.js +31 -0
  78. package/dist/squad/squad-coordinator-system-message.test.js +190 -0
  79. package/dist/squad/squad-session-routing.test.js +260 -0
  80. package/dist/squad/types.js +4 -0
  81. package/dist/status.js +25 -0
  82. package/dist/status.test.js +22 -0
  83. package/dist/store/db.js +290 -0
  84. package/dist/store/db.test.js +126 -0
  85. package/dist/store/squad-sessions.test.js +341 -0
  86. package/dist/test/setup-env.js +3 -0
  87. package/dist/update.js +112 -0
  88. package/dist/update.test.js +25 -0
  89. package/dist/wiki/context.js +138 -0
  90. package/dist/wiki/fs.js +195 -0
  91. package/dist/wiki/fs.test.js +39 -0
  92. package/dist/wiki/index-manager.js +359 -0
  93. package/dist/wiki/index-manager.test.js +129 -0
  94. package/dist/wiki/lock.js +26 -0
  95. package/dist/wiki/lock.test.js +30 -0
  96. package/dist/wiki/log-manager.js +20 -0
  97. package/dist/wiki/migrate.js +306 -0
  98. package/dist/wiki/okr.test.js +101 -0
  99. package/dist/wiki/path-utils.js +4 -0
  100. package/dist/wiki/path-utils.test.js +8 -0
  101. package/dist/wiki/seed-team-wiki.js +296 -0
  102. package/dist/wiki/seed-team-wiki.test.js +69 -0
  103. package/dist/wiki/team-sync.js +212 -0
  104. package/dist/wiki/team-sync.test.js +185 -0
  105. package/dist/wiki/templates/okr.js +98 -0
  106. package/package.json +72 -0
  107. package/skills/.gitkeep +0 -0
  108. package/skills/find-skills/SKILL.md +161 -0
  109. package/skills/find-skills/_meta.json +4 -0
  110. package/skills/frontend-design/LICENSE.txt +177 -0
  111. package/skills/frontend-design/SKILL.md +42 -0
  112. package/skills/squad/SKILL.md +76 -0
  113. package/web/dist/assets/index-D-e7K-fT.css +10 -0
  114. package/web/dist/assets/index-DAg9IrpO.js +142 -0
  115. package/web/dist/assets/index-DAg9IrpO.js.map +1 -0
  116. package/web/dist/chapterhouse-icon.png +0 -0
  117. package/web/dist/chapterhouse-icon.svg +42 -0
  118. package/web/dist/chapterhouse-logo.svg +46 -0
  119. package/web/dist/index.html +15 -0
@@ -0,0 +1,114 @@
1
+ import assert from "node:assert/strict";
2
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import test from "node:test";
6
+ async function loadOkrMapperModule() {
7
+ try {
8
+ return await import(new URL(`./okr-mapper.js?cachebust=${Date.now()}-${Math.random()}`, import.meta.url).href);
9
+ }
10
+ catch {
11
+ return null;
12
+ }
13
+ }
14
+ test.beforeEach(() => {
15
+ process.env.CHAPTERHOUSE_HOME = mkdtempSync(join(tmpdir(), "chapterhouse-okr-mapper-"));
16
+ });
17
+ test.afterEach(() => {
18
+ const home = process.env.CHAPTERHOUSE_HOME;
19
+ if (home) {
20
+ rmSync(home, { recursive: true, force: true });
21
+ }
22
+ });
23
+ const sampleOkrPage = `# OKRs — 2026 Q2
24
+
25
+ > Period: 2026-04-01 to 2026-06-30
26
+
27
+ ## O1: Improve auth platform reliability
28
+ **Owner**: Ada Lovelace
29
+
30
+ ### O1-KR1: Reduce auth service latency
31
+ - **Owner**: Ada Lovelace
32
+ - **Target**: 100%
33
+ - **Current**: 40%
34
+ - **Unit**: %
35
+ - **Due**: 2026-06-30
36
+
37
+ ### O1-KR2: Migrate legacy auth flows
38
+ - **Owner**: Grace Hopper
39
+ - **Target**: 100%
40
+ - **Current**: 60%
41
+ - **Unit**: %
42
+ - **Due**: 2026-06-30
43
+ `;
44
+ test("findMatchingKRs returns the best KR candidates for a natural language activity", async () => {
45
+ const okrMapperModule = await loadOkrMapperModule();
46
+ assert.ok(okrMapperModule, "okr mapper module should exist");
47
+ const requestedPaths = [];
48
+ const mapper = new okrMapperModule.OKRMapper({
49
+ async fetchPage(path) {
50
+ requestedPaths.push(path);
51
+ return path === "pages/okrs/2026-Q2.md" ? sampleOkrPage : null;
52
+ },
53
+ });
54
+ const matches = await mapper.findMatchingKRs("merged auth refactor PR that reduced login latency", "2026-Q2");
55
+ assert.deepEqual(requestedPaths, ["pages/okrs/2026-Q2.md"]);
56
+ assert.equal(matches.length > 0, true);
57
+ assert.deepEqual(matches[0], {
58
+ krId: "O1-KR1",
59
+ title: "Reduce auth service latency",
60
+ objectiveTitle: "Improve auth platform reliability",
61
+ confidence: "high",
62
+ });
63
+ });
64
+ test("formatUpdatePrompt asks the user to confirm the suggested KR and delta", async () => {
65
+ const okrMapperModule = await loadOkrMapperModule();
66
+ assert.ok(okrMapperModule, "okr mapper module should exist");
67
+ const mapper = new okrMapperModule.OKRMapper({
68
+ async fetchPage() {
69
+ return null;
70
+ },
71
+ });
72
+ const prompt = mapper.formatUpdatePrompt("merged auth refactor PR", [
73
+ {
74
+ krId: "O1-KR1",
75
+ title: "Reduce auth service latency",
76
+ objectiveTitle: "Improve auth platform reliability",
77
+ confidence: "high",
78
+ },
79
+ ]);
80
+ assert.match(prompt, /You mentioned: "merged auth refactor PR"/);
81
+ assert.match(prompt, /O1-KR1/);
82
+ assert.match(prompt, /Reduce auth service latency/);
83
+ assert.match(prompt, /what's the delta \(0-100\)\?/i);
84
+ });
85
+ test("recordConfirmedMapping persists keyword history and reuses it for high-confidence matches", async () => {
86
+ const okrMapperModule = await loadOkrMapperModule();
87
+ assert.ok(okrMapperModule, "okr mapper module should exist");
88
+ const mapper = new okrMapperModule.OKRMapper({
89
+ async fetchPage(path) {
90
+ return path === "pages/okrs/2026-Q2.md" ? sampleOkrPage : null;
91
+ },
92
+ });
93
+ mapper.recordConfirmedMapping("merged auth refactor PR that reduced login latency", "O1-KR1");
94
+ mapper.recordConfirmedMapping("merged auth refactor PR that reduced login latency", "O1-KR1");
95
+ const memoryPath = join(process.env.CHAPTERHOUSE_HOME, ".chapterhouse", "wiki", ".okr-memory.json");
96
+ assert.equal(existsSync(memoryPath), true);
97
+ const memory = JSON.parse(readFileSync(memoryPath, "utf-8"));
98
+ assert.equal(memory.auth?.krId, "O1-KR1");
99
+ assert.equal(memory.auth?.confirmedCount, 2);
100
+ assert.match(memory.auth?.lastUsed ?? "", /^\d{4}-\d{2}-\d{2}T/);
101
+ const freshMapper = new okrMapperModule.OKRMapper({
102
+ async fetchPage(path) {
103
+ return path === "pages/okrs/2026-Q2.md" ? sampleOkrPage : null;
104
+ },
105
+ });
106
+ const matches = await freshMapper.findMatchingKRs("latency cleanup in auth login flow", "2026-Q2");
107
+ assert.deepEqual(matches[0], {
108
+ krId: "O1-KR1",
109
+ title: "Reduce auth service latency",
110
+ objectiveTitle: "Improve auth platform reliability",
111
+ confidence: "high",
112
+ });
113
+ });
114
+ //# sourceMappingURL=okr-mapper.test.js.map