briefed 0.1.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 (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +118 -0
  3. package/dist/bench/metrics.d.ts +31 -0
  4. package/dist/bench/metrics.js +122 -0
  5. package/dist/bench/metrics.js.map +1 -0
  6. package/dist/bench/runner.d.ts +27 -0
  7. package/dist/bench/runner.js +184 -0
  8. package/dist/bench/runner.js.map +1 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +42 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/bench.d.ts +11 -0
  13. package/dist/commands/bench.js +23 -0
  14. package/dist/commands/bench.js.map +1 -0
  15. package/dist/commands/doctor.d.ts +5 -0
  16. package/dist/commands/doctor.js +246 -0
  17. package/dist/commands/doctor.js.map +1 -0
  18. package/dist/commands/init.d.ts +8 -0
  19. package/dist/commands/init.js +319 -0
  20. package/dist/commands/init.js.map +1 -0
  21. package/dist/commands/stats.d.ts +5 -0
  22. package/dist/commands/stats.js +87 -0
  23. package/dist/commands/stats.js.map +1 -0
  24. package/dist/deliver/ci.d.ts +4 -0
  25. package/dist/deliver/ci.js +62 -0
  26. package/dist/deliver/ci.js.map +1 -0
  27. package/dist/deliver/claudemd.d.ts +9 -0
  28. package/dist/deliver/claudemd.js +51 -0
  29. package/dist/deliver/claudemd.js.map +1 -0
  30. package/dist/deliver/cross-tool.d.ts +10 -0
  31. package/dist/deliver/cross-tool.js +49 -0
  32. package/dist/deliver/cross-tool.js.map +1 -0
  33. package/dist/deliver/git-hook.d.ts +10 -0
  34. package/dist/deliver/git-hook.js +104 -0
  35. package/dist/deliver/git-hook.js.map +1 -0
  36. package/dist/deliver/hooks.d.ts +9 -0
  37. package/dist/deliver/hooks.js +315 -0
  38. package/dist/deliver/hooks.js.map +1 -0
  39. package/dist/extract/complexity.d.ts +16 -0
  40. package/dist/extract/complexity.js +46 -0
  41. package/dist/extract/complexity.js.map +1 -0
  42. package/dist/extract/conventions.d.ts +18 -0
  43. package/dist/extract/conventions.js +143 -0
  44. package/dist/extract/conventions.js.map +1 -0
  45. package/dist/extract/depgraph.d.ts +12 -0
  46. package/dist/extract/depgraph.js +70 -0
  47. package/dist/extract/depgraph.js.map +1 -0
  48. package/dist/extract/env.d.ts +17 -0
  49. package/dist/extract/env.js +142 -0
  50. package/dist/extract/env.js.map +1 -0
  51. package/dist/extract/error-patterns.d.ts +15 -0
  52. package/dist/extract/error-patterns.js +107 -0
  53. package/dist/extract/error-patterns.js.map +1 -0
  54. package/dist/extract/frontend.d.ts +30 -0
  55. package/dist/extract/frontend.js +244 -0
  56. package/dist/extract/frontend.js.map +1 -0
  57. package/dist/extract/gotchas.d.ts +12 -0
  58. package/dist/extract/gotchas.js +145 -0
  59. package/dist/extract/gotchas.js.map +1 -0
  60. package/dist/extract/history.d.ts +29 -0
  61. package/dist/extract/history.js +91 -0
  62. package/dist/extract/history.js.map +1 -0
  63. package/dist/extract/infra.d.ts +27 -0
  64. package/dist/extract/infra.js +226 -0
  65. package/dist/extract/infra.js.map +1 -0
  66. package/dist/extract/monorepo.d.ts +16 -0
  67. package/dist/extract/monorepo.js +135 -0
  68. package/dist/extract/monorepo.js.map +1 -0
  69. package/dist/extract/routes.d.ts +16 -0
  70. package/dist/extract/routes.js +156 -0
  71. package/dist/extract/routes.js.map +1 -0
  72. package/dist/extract/scanner.d.ts +18 -0
  73. package/dist/extract/scanner.js +109 -0
  74. package/dist/extract/scanner.js.map +1 -0
  75. package/dist/extract/schema.d.ts +28 -0
  76. package/dist/extract/schema.js +192 -0
  77. package/dist/extract/schema.js.map +1 -0
  78. package/dist/extract/scripts.d.ts +18 -0
  79. package/dist/extract/scripts.js +104 -0
  80. package/dist/extract/scripts.js.map +1 -0
  81. package/dist/extract/security.d.ts +20 -0
  82. package/dist/extract/security.js +95 -0
  83. package/dist/extract/security.js.map +1 -0
  84. package/dist/extract/signatures.d.ts +33 -0
  85. package/dist/extract/signatures.js +608 -0
  86. package/dist/extract/signatures.js.map +1 -0
  87. package/dist/extract/staleness.d.ts +16 -0
  88. package/dist/extract/staleness.js +108 -0
  89. package/dist/extract/staleness.js.map +1 -0
  90. package/dist/extract/tests.d.ts +16 -0
  91. package/dist/extract/tests.js +175 -0
  92. package/dist/extract/tests.js.map +1 -0
  93. package/dist/extract/usage-examples.d.ts +17 -0
  94. package/dist/extract/usage-examples.js +115 -0
  95. package/dist/extract/usage-examples.js.map +1 -0
  96. package/dist/generate/index-file.d.ts +29 -0
  97. package/dist/generate/index-file.js +168 -0
  98. package/dist/generate/index-file.js.map +1 -0
  99. package/dist/generate/rules.d.ts +6 -0
  100. package/dist/generate/rules.js +94 -0
  101. package/dist/generate/rules.js.map +1 -0
  102. package/dist/generate/skeleton.d.ts +14 -0
  103. package/dist/generate/skeleton.js +145 -0
  104. package/dist/generate/skeleton.js.map +1 -0
  105. package/dist/learn/tracker.d.ts +54 -0
  106. package/dist/learn/tracker.js +129 -0
  107. package/dist/learn/tracker.js.map +1 -0
  108. package/dist/utils/detect.d.ts +16 -0
  109. package/dist/utils/detect.js +188 -0
  110. package/dist/utils/detect.js.map +1 -0
  111. package/dist/utils/pagerank.d.ts +19 -0
  112. package/dist/utils/pagerank.js +52 -0
  113. package/dist/utils/pagerank.js.map +1 -0
  114. package/dist/utils/tokens.d.ts +11 -0
  115. package/dist/utils/tokens.js +27 -0
  116. package/dist/utils/tokens.js.map +1 -0
  117. package/package.json +43 -0
@@ -0,0 +1,87 @@
1
+ import { resolve, join } from "path";
2
+ import { existsSync, readFileSync, readdirSync } from "fs";
3
+ import { countTokens, formatTokens } from "../utils/tokens.js";
4
+ import { checkStaleness, formatStaleness } from "../extract/staleness.js";
5
+ export async function statsCommand(opts) {
6
+ const root = resolve(opts.repo);
7
+ console.log("briefed stats\n");
8
+ // L1 Skeleton
9
+ const skeletonPath = join(root, ".briefed", "skeleton.md");
10
+ if (existsSync(skeletonPath)) {
11
+ const skeleton = readFileSync(skeletonPath, "utf-8");
12
+ const tokens = countTokens(skeleton);
13
+ console.log(` L1 Skeleton: ${formatTokens(tokens)} tokens (${skeleton.length} chars)`);
14
+ console.log(` Delivery: CLAUDE.md (always loaded, survives compaction)`);
15
+ }
16
+ else {
17
+ console.log(" L1 Skeleton: not generated (run briefed init)");
18
+ }
19
+ // L3 Gotchas / Rules
20
+ const rulesDir = join(root, ".claude", "rules");
21
+ if (existsSync(rulesDir)) {
22
+ const ruleFiles = readdirSync(rulesDir).filter((f) => f.startsWith("briefed-"));
23
+ let totalTokens = 0;
24
+ let totalGotchas = 0;
25
+ for (const file of ruleFiles) {
26
+ const content = readFileSync(join(rulesDir, file), "utf-8");
27
+ totalTokens += countTokens(content);
28
+ totalGotchas += (content.match(/^- /gm) || []).length;
29
+ }
30
+ console.log(` L3 Gotchas: ${totalGotchas} constraints across ${ruleFiles.length} rule files (~${formatTokens(totalTokens)} tokens)`);
31
+ console.log(` Delivery: .claude/rules/ (path-scoped, loaded on demand)`);
32
+ }
33
+ else {
34
+ console.log(" L3 Gotchas: not generated");
35
+ }
36
+ // L2 Contracts
37
+ const contractsDir = join(root, ".briefed", "contracts");
38
+ if (existsSync(contractsDir)) {
39
+ const contractFiles = readdirSync(contractsDir).filter((f) => f.endsWith(".yaml"));
40
+ let totalTokens = 0;
41
+ for (const file of contractFiles) {
42
+ const content = readFileSync(join(contractsDir, file), "utf-8");
43
+ totalTokens += countTokens(content);
44
+ }
45
+ console.log(` L2 Contracts: ${contractFiles.length} modules (~${formatTokens(totalTokens)} tokens total)`);
46
+ console.log(` Delivery: UserPromptSubmit hook (1-3 modules per prompt)`);
47
+ }
48
+ else {
49
+ console.log(" L2 Contracts: not generated");
50
+ }
51
+ // Module index
52
+ const indexPath = join(root, ".briefed", "index.json");
53
+ if (existsSync(indexPath)) {
54
+ const index = JSON.parse(readFileSync(indexPath, "utf-8"));
55
+ console.log(` Module Index: ${index.modules?.length || 0} modules indexed`);
56
+ console.log(` Generated: ${index.generated || "unknown"}`);
57
+ }
58
+ // Hooks
59
+ const settingsPath = join(root, ".claude", "settings.json");
60
+ if (existsSync(settingsPath)) {
61
+ const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
62
+ const hasBriefedHooks = JSON.stringify(settings.hooks || {}).includes("briefed");
63
+ console.log(` Hooks: ${hasBriefedHooks ? "installed" : "not installed"}`);
64
+ }
65
+ else {
66
+ console.log(" Hooks: not installed");
67
+ }
68
+ console.log("");
69
+ // Estimated per-prompt cost
70
+ const skeletonTokens = existsSync(skeletonPath)
71
+ ? countTokens(readFileSync(skeletonPath, "utf-8"))
72
+ : 0;
73
+ console.log(` Estimated tokens per prompt:`);
74
+ console.log(` L1 (always): ~${formatTokens(skeletonTokens)}`);
75
+ console.log(` L3 (per file): ~100-300`);
76
+ console.log(` L2 (per prompt): ~400-1500`);
77
+ console.log(` Total: ~${formatTokens(skeletonTokens + 700)}-${formatTokens(skeletonTokens + 1800)}`);
78
+ console.log("");
79
+ console.log(` Compare to without briefed:`);
80
+ console.log(` Orientation: ~5000-10000 tokens (3-6 file reads)`);
81
+ console.log(` Time: ~8-12 seconds`);
82
+ // Staleness check
83
+ console.log("");
84
+ const staleness = checkStaleness(root);
85
+ console.log(formatStaleness(staleness));
86
+ }
87
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/commands/stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Generate a GitHub Action workflow that auto-updates briefed context on PRs.
3
+ */
4
+ export declare function generateGitHubAction(root: string): void;
@@ -0,0 +1,62 @@
1
+ import { writeFileSync, mkdirSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ /**
4
+ * Generate a GitHub Action workflow that auto-updates briefed context on PRs.
5
+ */
6
+ export function generateGitHubAction(root) {
7
+ const workflowDir = join(root, ".github", "workflows");
8
+ if (!existsSync(workflowDir))
9
+ mkdirSync(workflowDir, { recursive: true });
10
+ const workflow = `# Auto-update briefed context on pushes to main
11
+ # Generated by briefed — regenerate with: npx briefed ci
12
+ name: Update briefed context
13
+
14
+ on:
15
+ push:
16
+ branches: [main, master]
17
+ paths:
18
+ - 'src/**'
19
+ - 'lib/**'
20
+ - 'app/**'
21
+ - 'packages/**'
22
+ - '*.ts'
23
+ - '*.js'
24
+ - '*.py'
25
+ - '*.go'
26
+ - '*.rs'
27
+
28
+ jobs:
29
+ update-context:
30
+ runs-on: ubuntu-latest
31
+ permissions:
32
+ contents: write
33
+
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ with:
37
+ fetch-depth: 0 # full history for git log
38
+
39
+ - uses: actions/setup-node@v4
40
+ with:
41
+ node-version: '20'
42
+
43
+ - name: Run briefed init
44
+ run: npx briefed@latest init --skip-hooks
45
+
46
+ - name: Check for changes
47
+ id: changes
48
+ run: |
49
+ git diff --quiet CLAUDE.md .claude/rules/ .briefed/ 2>/dev/null || echo "changed=true" >> $GITHUB_OUTPUT
50
+
51
+ - name: Commit updated context
52
+ if: steps.changes.outputs.changed == 'true'
53
+ run: |
54
+ git config user.name "briefed[bot]"
55
+ git config user.email "briefed[bot]@users.noreply.github.com"
56
+ git add CLAUDE.md .claude/rules/ .briefed/
57
+ git commit -m "chore: update briefed context [skip ci]"
58
+ git push
59
+ `;
60
+ writeFileSync(join(workflowDir, "briefed.yml"), workflow);
61
+ }
62
+ //# sourceMappingURL=ci.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci.js","sourceRoot":"","sources":["../../src/deliver/ci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACvD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1E,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDlB,CAAC;IAEA,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Append or update the briefed skeleton section in CLAUDE.md.
3
+ * Preserves existing CLAUDE.md content. Only modifies the briefed section.
4
+ */
5
+ export declare function updateClaudeMd(root: string, skeleton: string): void;
6
+ /**
7
+ * Save the skeleton as a standalone file in .briefed/ for hook re-injection.
8
+ */
9
+ export declare function saveSkeletonFile(root: string, skeleton: string): void;
@@ -0,0 +1,51 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
2
+ import { join } from "path";
3
+ const BRIEFED_START = "<!-- briefed:start -->";
4
+ const BRIEFED_END = "<!-- briefed:end -->";
5
+ /**
6
+ * Append or update the briefed skeleton section in CLAUDE.md.
7
+ * Preserves existing CLAUDE.md content. Only modifies the briefed section.
8
+ */
9
+ export function updateClaudeMd(root, skeleton) {
10
+ const claudeDir = join(root, ".claude");
11
+ const claudeMdPath = join(root, "CLAUDE.md");
12
+ // Ensure directories exist
13
+ if (!existsSync(claudeDir)) {
14
+ mkdirSync(claudeDir, { recursive: true });
15
+ }
16
+ const briefedSection = `${BRIEFED_START}\n${skeleton}\n${BRIEFED_END}`;
17
+ if (existsSync(claudeMdPath)) {
18
+ let content = readFileSync(claudeMdPath, "utf-8");
19
+ if (content.includes(BRIEFED_START)) {
20
+ // Replace existing briefed section
21
+ const startIdx = content.indexOf(BRIEFED_START);
22
+ const endIdx = content.indexOf(BRIEFED_END);
23
+ if (endIdx !== -1) {
24
+ content =
25
+ content.slice(0, startIdx) +
26
+ briefedSection +
27
+ content.slice(endIdx + BRIEFED_END.length);
28
+ }
29
+ }
30
+ else {
31
+ // Append briefed section
32
+ content = content.trimEnd() + "\n\n" + briefedSection + "\n";
33
+ }
34
+ writeFileSync(claudeMdPath, content);
35
+ }
36
+ else {
37
+ // Create new CLAUDE.md with just the briefed section
38
+ writeFileSync(claudeMdPath, briefedSection + "\n");
39
+ }
40
+ }
41
+ /**
42
+ * Save the skeleton as a standalone file in .briefed/ for hook re-injection.
43
+ */
44
+ export function saveSkeletonFile(root, skeleton) {
45
+ const briefedDir = join(root, ".briefed");
46
+ if (!existsSync(briefedDir)) {
47
+ mkdirSync(briefedDir, { recursive: true });
48
+ }
49
+ writeFileSync(join(briefedDir, "skeleton.md"), skeleton);
50
+ }
51
+ //# sourceMappingURL=claudemd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudemd.js","sourceRoot":"","sources":["../../src/deliver/claudemd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,aAAa,GAAG,wBAAwB,CAAC;AAC/C,MAAM,WAAW,GAAG,sBAAsB,CAAC;AAE3C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,QAAgB;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACxC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAE7C,2BAA2B;IAC3B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,cAAc,GAAG,GAAG,aAAa,KAAK,QAAQ,KAAK,WAAW,EAAE,CAAC;IAEvE,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,IAAI,OAAO,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAElD,IAAI,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACpC,mCAAmC;YACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAChD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YAC5C,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;gBAClB,OAAO;oBACL,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC;wBAC1B,cAAc;wBACd,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,yBAAyB;YACzB,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;QAC/D,CAAC;QAED,aAAa,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;SAAM,CAAC;QACN,qDAAqD;QACrD,aAAa,CAAC,YAAY,EAAE,cAAc,GAAG,IAAI,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,QAAgB;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Generate .cursorrules for Cursor IDE users.
3
+ * Same content as the briefed CLAUDE.md skeleton, formatted for Cursor.
4
+ */
5
+ export declare function writeCursorRules(root: string, skeleton: string, conventions: string): void;
6
+ /**
7
+ * Generate AGENTS.md (cross-tool format adopted by multiple AI coding tools).
8
+ * Provides a standardized context file that works with Claude Code, Cursor, Copilot, etc.
9
+ */
10
+ export declare function writeAgentsMd(root: string, skeleton: string, conventions: string): void;
@@ -0,0 +1,49 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "fs";
2
+ import { join } from "path";
3
+ /**
4
+ * Generate .cursorrules for Cursor IDE users.
5
+ * Same content as the briefed CLAUDE.md skeleton, formatted for Cursor.
6
+ */
7
+ export function writeCursorRules(root, skeleton, conventions) {
8
+ const content = `# Project Context (generated by briefed)
9
+ # This file provides Cursor with structural context about this codebase.
10
+ # Regenerate with: npx briefed init
11
+
12
+ ${skeleton}
13
+
14
+ ${conventions}
15
+ `.trim();
16
+ writeFileSync(join(root, ".cursorrules"), content + "\n");
17
+ }
18
+ /**
19
+ * Generate AGENTS.md (cross-tool format adopted by multiple AI coding tools).
20
+ * Provides a standardized context file that works with Claude Code, Cursor, Copilot, etc.
21
+ */
22
+ export function writeAgentsMd(root, skeleton, conventions) {
23
+ const agentsPath = join(root, "AGENTS.md");
24
+ const BRIEFED_START = "<!-- briefed:agents:start -->";
25
+ const BRIEFED_END = "<!-- briefed:agents:end -->";
26
+ const briefedSection = `${BRIEFED_START}
27
+ ${skeleton}
28
+
29
+ ${conventions}
30
+ ${BRIEFED_END}`;
31
+ if (existsSync(agentsPath)) {
32
+ let content = readFileSync(agentsPath, "utf-8");
33
+ if (content.includes(BRIEFED_START)) {
34
+ const startIdx = content.indexOf(BRIEFED_START);
35
+ const endIdx = content.indexOf(BRIEFED_END);
36
+ if (endIdx !== -1) {
37
+ content = content.slice(0, startIdx) + briefedSection + content.slice(endIdx + BRIEFED_END.length);
38
+ }
39
+ }
40
+ else {
41
+ content = content.trimEnd() + "\n\n" + briefedSection + "\n";
42
+ }
43
+ writeFileSync(agentsPath, content);
44
+ }
45
+ else {
46
+ writeFileSync(agentsPath, briefedSection + "\n");
47
+ }
48
+ }
49
+ //# sourceMappingURL=cross-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-tool.js","sourceRoot":"","sources":["../../src/deliver/cross-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,QAAgB,EAAE,WAAmB;IAClF,MAAM,OAAO,GAAG;;;;EAIhB,QAAQ;;EAER,WAAW;CACZ,CAAC,IAAI,EAAE,CAAC;IAEP,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,QAAgB,EAAE,WAAmB;IAC/E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAE3C,MAAM,aAAa,GAAG,+BAA+B,CAAC;IACtD,MAAM,WAAW,GAAG,6BAA6B,CAAC;IAElD,MAAM,cAAc,GAAG,GAAG,aAAa;EACvC,QAAQ;;EAER,WAAW;EACX,WAAW,EAAE,CAAC;IAEd,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAChD,IAAI,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAChD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YAC5C,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;gBAClB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;YACrG,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;QAC/D,CAAC;QACD,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;SAAM,CAAC;QACN,aAAa,CAAC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAC,CAAC;IACnD,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Install a git post-commit hook that auto-updates briefed context.
3
+ * Runs `briefed init --skip-hooks` after every commit (~5 seconds).
4
+ * Developer never thinks about it — context stays fresh automatically.
5
+ */
6
+ export declare function installGitHook(root: string): boolean;
7
+ /**
8
+ * Remove briefed's git hook.
9
+ */
10
+ export declare function removeGitHook(root: string): void;
@@ -0,0 +1,104 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync } from "fs";
2
+ import { join } from "path";
3
+ import { execSync } from "child_process";
4
+ /**
5
+ * Install a git post-commit hook that auto-updates briefed context.
6
+ * Runs `briefed init --skip-hooks` after every commit (~5 seconds).
7
+ * Developer never thinks about it — context stays fresh automatically.
8
+ */
9
+ export function installGitHook(root) {
10
+ // Find the git hooks directory
11
+ let hooksDir;
12
+ try {
13
+ const gitDir = execSync("git rev-parse --git-dir", {
14
+ cwd: root,
15
+ encoding: "utf-8",
16
+ stdio: ["pipe", "pipe", "pipe"],
17
+ }).trim();
18
+ hooksDir = join(root, gitDir, "hooks");
19
+ }
20
+ catch {
21
+ // Not a git repo — skip
22
+ return false;
23
+ }
24
+ if (!existsSync(hooksDir)) {
25
+ mkdirSync(hooksDir, { recursive: true });
26
+ }
27
+ const hookPath = join(hooksDir, "post-commit");
28
+ const briefedMarker = "# briefed: auto-update context";
29
+ const hookScript = `#!/bin/sh
30
+ ${briefedMarker}
31
+ # Re-index codebase after each commit to keep context fresh.
32
+ # Runs in background so it doesn't slow down your commit.
33
+ # Remove this hook with: briefed unhook
34
+ (npx briefed init --skip-hooks > /dev/null 2>&1 &)
35
+ `;
36
+ if (existsSync(hookPath)) {
37
+ const existing = readFileSync(hookPath, "utf-8");
38
+ // Already has briefed hook
39
+ if (existing.includes(briefedMarker))
40
+ return true;
41
+ // Append to existing hook
42
+ writeFileSync(hookPath, existing.trimEnd() + "\n\n" + hookScript);
43
+ }
44
+ else {
45
+ writeFileSync(hookPath, hookScript);
46
+ }
47
+ // Make executable (Unix/Mac)
48
+ try {
49
+ chmodSync(hookPath, 0o755);
50
+ }
51
+ catch {
52
+ // Windows doesn't need chmod
53
+ }
54
+ return true;
55
+ }
56
+ /**
57
+ * Remove briefed's git hook.
58
+ */
59
+ export function removeGitHook(root) {
60
+ let hooksDir;
61
+ try {
62
+ const gitDir = execSync("git rev-parse --git-dir", {
63
+ cwd: root,
64
+ encoding: "utf-8",
65
+ stdio: ["pipe", "pipe", "pipe"],
66
+ }).trim();
67
+ hooksDir = join(root, gitDir, "hooks");
68
+ }
69
+ catch {
70
+ return;
71
+ }
72
+ const hookPath = join(hooksDir, "post-commit");
73
+ if (!existsSync(hookPath))
74
+ return;
75
+ const content = readFileSync(hookPath, "utf-8");
76
+ const briefedMarker = "# briefed: auto-update context";
77
+ if (!content.includes(briefedMarker))
78
+ return;
79
+ // Remove the briefed section
80
+ const lines = content.split("\n");
81
+ const filtered = [];
82
+ let inBriefedBlock = false;
83
+ for (const line of lines) {
84
+ if (line.includes(briefedMarker)) {
85
+ inBriefedBlock = true;
86
+ continue;
87
+ }
88
+ if (inBriefedBlock && (line.startsWith("#") || line.startsWith("(npx briefed"))) {
89
+ continue;
90
+ }
91
+ inBriefedBlock = false;
92
+ filtered.push(line);
93
+ }
94
+ const remaining = filtered.join("\n").trim();
95
+ if (remaining === "#!/bin/sh" || !remaining) {
96
+ // Hook is now empty — remove it
97
+ const { unlinkSync } = require("fs");
98
+ unlinkSync(hookPath);
99
+ }
100
+ else {
101
+ writeFileSync(hookPath, remaining + "\n");
102
+ }
103
+ }
104
+ //# sourceMappingURL=git-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-hook.js","sourceRoot":"","sources":["../../src/deliver/git-hook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Install briefed hooks into .claude/settings.json.
3
+ * Adds SessionStart (compact) and UserPromptSubmit hooks.
4
+ */
5
+ export declare function installHooks(root: string): void;
6
+ /**
7
+ * Generate the hook scripts that get executed by Claude Code.
8
+ */
9
+ export declare function generateHookScripts(root: string): void;