chapterhouse 0.1.1 → 0.2.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.
@@ -0,0 +1,53 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { createLogger, resolveLevel } from "./logger.js";
4
+ // ---------------------------------------------------------------------------
5
+ // resolveLevel — env var to pino level string
6
+ // ---------------------------------------------------------------------------
7
+ test("resolveLevel defaults to info when nothing is set", () => {
8
+ const level = resolveLevel(undefined);
9
+ assert.equal(level, "info");
10
+ });
11
+ test("resolveLevel accepts valid levels case-insensitively", () => {
12
+ assert.equal(resolveLevel("DEBUG"), "debug");
13
+ assert.equal(resolveLevel("WARN"), "warn");
14
+ assert.equal(resolveLevel("trace"), "trace");
15
+ assert.equal(resolveLevel("silent"), "silent");
16
+ });
17
+ test("resolveLevel falls back to info for unknown values", () => {
18
+ assert.equal(resolveLevel("verbose"), "info");
19
+ assert.equal(resolveLevel(""), "info");
20
+ });
21
+ // ---------------------------------------------------------------------------
22
+ // createLogger — level gates
23
+ // ---------------------------------------------------------------------------
24
+ test("logger at info level does NOT emit debug entries", () => {
25
+ const log = createLogger("info");
26
+ // pino.isLevelEnabled tells us whether a given level passes the filter
27
+ assert.equal(log.isLevelEnabled("debug"), false, "debug should be suppressed at info level");
28
+ assert.equal(log.isLevelEnabled("trace"), false, "trace should be suppressed at info level");
29
+ });
30
+ test("logger at info level DOES emit info and above", () => {
31
+ const log = createLogger("info");
32
+ assert.equal(log.isLevelEnabled("info"), true);
33
+ assert.equal(log.isLevelEnabled("warn"), true);
34
+ assert.equal(log.isLevelEnabled("error"), true);
35
+ });
36
+ test("logger at debug level emits debug but not trace", () => {
37
+ const log = createLogger("debug");
38
+ assert.equal(log.isLevelEnabled("debug"), true);
39
+ assert.equal(log.isLevelEnabled("trace"), false);
40
+ });
41
+ test("chat content gating: debug messages do not appear at info level", () => {
42
+ // This is the KEY invariant: chat message content is logged at debug.
43
+ // At the default info level, those messages must be suppressed.
44
+ const log = createLogger("info");
45
+ const chatLevel = "debug"; // the level used for chat content throughout the app
46
+ assert.equal(log.isLevelEnabled(chatLevel), false, `Chat messages logged at '${chatLevel}' must NOT appear when LOG_LEVEL=info`);
47
+ });
48
+ test("chat content becomes visible when LOG_LEVEL=debug", () => {
49
+ const log = createLogger("debug");
50
+ const chatLevel = "debug";
51
+ assert.equal(log.isLevelEnabled(chatLevel), true, `Chat messages logged at '${chatLevel}' MUST appear when LOG_LEVEL=debug`);
52
+ });
53
+ //# sourceMappingURL=logger.test.js.map
@@ -5,6 +5,8 @@ import { getDb, getState, setState } from "../store/db.js";
5
5
  import { ensureWikiStructure, writePage, readPage, writeRawSource, deletePage } from "./fs.js";
6
6
  import { addToIndex, removeFromIndex } from "./index-manager.js";
7
7
  import { appendLog } from "./log-manager.js";
8
+ import { childLogger } from "../util/logger.js";
9
+ const log = childLogger("wiki:migrate");
8
10
  const MIGRATION_KEY = "wiki_migrated";
9
11
  const REORG_KEY = "wiki_reorganized";
10
12
  /** Check whether a migration is needed (wiki not yet populated from SQLite). */
@@ -108,7 +110,7 @@ export function migrateMemoriesToWiki() {
108
110
  const categories = Object.keys(grouped).join(", ");
109
111
  appendLog("migrate", `Migrated ${total} memories across categories: ${categories}`);
110
112
  setState(MIGRATION_KEY, "true");
111
- console.log(`[chapterhouse] Wiki migration complete: ${total} memories → ${Object.keys(grouped).length} pages`);
113
+ log.info({ total, pageCount: Object.keys(grouped).length }, "Wiki migration complete");
112
114
  return total;
113
115
  }
114
116
  // ---------------------------------------------------------------------------
@@ -283,7 +285,7 @@ export function reorganizeWiki() {
283
285
  }
284
286
  setState(REORG_KEY, "true");
285
287
  appendLog("reorg", `Wiki reorganized: ${pagesCreated} entity pages created`);
286
- console.log(`[chapterhouse] Wiki reorganization complete: ${pagesCreated} entity pages created`);
288
+ log.info({ pagesCreated }, "Wiki reorganization complete");
287
289
  return pagesCreated;
288
290
  }
289
291
  function getCategoryDirForReorg(category) {
@@ -3,6 +3,8 @@ import { resolve } from "node:path";
3
3
  import { ensureWikiStructure, readPage, writePage } from "./fs.js";
4
4
  import { addToIndex, buildIndexEntryForPage } from "./index-manager.js";
5
5
  import { generateKPIPage, generateOKRQuarterPage, generateTeamIndexPage, } from "./templates/okr.js";
6
+ import { childLogger } from "../util/logger.js";
7
+ const log = childLogger("wiki:seed");
6
8
  const SAMPLE_OBJECTIVES = [
7
9
  {
8
10
  id: "O1",
@@ -283,13 +285,13 @@ async function main() {
283
285
  const message = result.created.length > 0
284
286
  ? `Seeded ${result.created.length} team wiki page(s): ${result.created.join(", ")}`
285
287
  : "Team wiki seed already up to date; no pages created.";
286
- console.log(`[chapterhouse] ${message}`);
288
+ log.info({ message }, "Team wiki seed result");
287
289
  }
288
290
  const invokedPath = process.argv[1] ? resolve(process.argv[1]) : "";
289
291
  const modulePath = fileURLToPath(import.meta.url);
290
292
  if (invokedPath === modulePath) {
291
293
  main().catch((err) => {
292
- console.error("[chapterhouse] Failed to seed team wiki:", err);
294
+ log.error({ err: err instanceof Error ? err.message : err }, "Failed to seed team wiki");
293
295
  process.exit(1);
294
296
  });
295
297
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "chapterhouse",
3
- "version": "0.1.1",
4
- "description": "Chapterhouse a team-level AI assistant for engineering teams, built on the GitHub Copilot SDK. Web UI only.",
3
+ "version": "0.2.0",
4
+ "description": "Chapterhouse \u2014 a team-level AI assistant for engineering teams, built on the GitHub Copilot SDK. Web UI only.",
5
5
  "bin": {
6
6
  "chapterhouse": "dist/cli.js"
7
7
  },
@@ -57,6 +57,7 @@
57
57
  "helmet": "^8.1.0",
58
58
  "jsonwebtoken": "^9.0.3",
59
59
  "jwks-rsa": "^4.0.1",
60
+ "pino": "^10.3.1",
60
61
  "zod": "^4.3.6"
61
62
  },
62
63
  "devDependencies": {