@ctxkit/cli 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.
Files changed (85) hide show
  1. package/dist/commands/apply.d.ts +3 -0
  2. package/dist/commands/apply.d.ts.map +1 -0
  3. package/dist/commands/apply.js +45 -0
  4. package/dist/commands/apply.js.map +1 -0
  5. package/dist/commands/bootstrap-cmd.d.ts +3 -0
  6. package/dist/commands/bootstrap-cmd.d.ts.map +1 -0
  7. package/dist/commands/bootstrap-cmd.js +104 -0
  8. package/dist/commands/bootstrap-cmd.js.map +1 -0
  9. package/dist/commands/codex.d.ts +3 -0
  10. package/dist/commands/codex.d.ts.map +1 -0
  11. package/dist/commands/codex.js +64 -0
  12. package/dist/commands/codex.js.map +1 -0
  13. package/dist/commands/conflicts-cmd.d.ts +3 -0
  14. package/dist/commands/conflicts-cmd.d.ts.map +1 -0
  15. package/dist/commands/conflicts-cmd.js +178 -0
  16. package/dist/commands/conflicts-cmd.js.map +1 -0
  17. package/dist/commands/daemon.d.ts +4 -0
  18. package/dist/commands/daemon.d.ts.map +1 -0
  19. package/dist/commands/daemon.js +107 -0
  20. package/dist/commands/daemon.js.map +1 -0
  21. package/dist/commands/drift.d.ts +3 -0
  22. package/dist/commands/drift.d.ts.map +1 -0
  23. package/dist/commands/drift.js +65 -0
  24. package/dist/commands/drift.js.map +1 -0
  25. package/dist/commands/history-cmd.d.ts +3 -0
  26. package/dist/commands/history-cmd.d.ts.map +1 -0
  27. package/dist/commands/history-cmd.js +100 -0
  28. package/dist/commands/history-cmd.js.map +1 -0
  29. package/dist/commands/hooks-cmd.d.ts +3 -0
  30. package/dist/commands/hooks-cmd.d.ts.map +1 -0
  31. package/dist/commands/hooks-cmd.js +98 -0
  32. package/dist/commands/hooks-cmd.js.map +1 -0
  33. package/dist/commands/index-cmd.d.ts +3 -0
  34. package/dist/commands/index-cmd.d.ts.map +1 -0
  35. package/dist/commands/index-cmd.js +112 -0
  36. package/dist/commands/index-cmd.js.map +1 -0
  37. package/dist/commands/init.d.ts +3 -0
  38. package/dist/commands/init.d.ts.map +1 -0
  39. package/dist/commands/init.js +158 -0
  40. package/dist/commands/init.js.map +1 -0
  41. package/dist/commands/inject.d.ts +3 -0
  42. package/dist/commands/inject.d.ts.map +1 -0
  43. package/dist/commands/inject.js +68 -0
  44. package/dist/commands/inject.js.map +1 -0
  45. package/dist/commands/migrate-cmd.d.ts +3 -0
  46. package/dist/commands/migrate-cmd.d.ts.map +1 -0
  47. package/dist/commands/migrate-cmd.js +132 -0
  48. package/dist/commands/migrate-cmd.js.map +1 -0
  49. package/dist/commands/plugin.d.ts +3 -0
  50. package/dist/commands/plugin.d.ts.map +1 -0
  51. package/dist/commands/plugin.js +327 -0
  52. package/dist/commands/plugin.js.map +1 -0
  53. package/dist/commands/pr-context-cmd.d.ts +3 -0
  54. package/dist/commands/pr-context-cmd.d.ts.map +1 -0
  55. package/dist/commands/pr-context-cmd.js +128 -0
  56. package/dist/commands/pr-context-cmd.js.map +1 -0
  57. package/dist/commands/propose.d.ts +3 -0
  58. package/dist/commands/propose.d.ts.map +1 -0
  59. package/dist/commands/propose.js +109 -0
  60. package/dist/commands/propose.js.map +1 -0
  61. package/dist/commands/run.d.ts +3 -0
  62. package/dist/commands/run.d.ts.map +1 -0
  63. package/dist/commands/run.js +133 -0
  64. package/dist/commands/run.js.map +1 -0
  65. package/dist/commands/sessions.d.ts +3 -0
  66. package/dist/commands/sessions.d.ts.map +1 -0
  67. package/dist/commands/sessions.js +93 -0
  68. package/dist/commands/sessions.js.map +1 -0
  69. package/dist/commands/speckit-cmd.d.ts +3 -0
  70. package/dist/commands/speckit-cmd.d.ts.map +1 -0
  71. package/dist/commands/speckit-cmd.js +196 -0
  72. package/dist/commands/speckit-cmd.js.map +1 -0
  73. package/dist/commands/validate.d.ts +3 -0
  74. package/dist/commands/validate.d.ts.map +1 -0
  75. package/dist/commands/validate.js +75 -0
  76. package/dist/commands/validate.js.map +1 -0
  77. package/dist/index.d.ts +3 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +49 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/services/agents-md.d.ts +34 -0
  82. package/dist/services/agents-md.d.ts.map +1 -0
  83. package/dist/services/agents-md.js +248 -0
  84. package/dist/services/agents-md.js.map +1 -0
  85. package/package.json +45 -0
@@ -0,0 +1,196 @@
1
+ import { Command } from 'commander';
2
+ import { execSync } from 'node:child_process';
3
+ export const speckitCommand = new Command('speckit')
4
+ .description('Spec-kit integration bridge');
5
+ function getRepoRoot() {
6
+ try {
7
+ return execSync('git rev-parse --show-toplevel', {
8
+ encoding: 'utf-8',
9
+ timeout: 3000,
10
+ stdio: ['pipe', 'pipe', 'pipe'],
11
+ }).trim();
12
+ }
13
+ catch {
14
+ console.error('Error: Not a git repository');
15
+ process.exit(1);
16
+ return '';
17
+ }
18
+ }
19
+ speckitCommand
20
+ .command('import')
21
+ .description('Import spec-kit artifacts into .ctx files')
22
+ .option('--constitution <path>', 'Path to constitution file', '.specify/memory/constitution.md')
23
+ .option('--specs <dir>', 'Path to spec-kit specs directory', 'specs/')
24
+ .option('--dry-run', 'Preview changes without writing')
25
+ .option('--json', 'Output as JSON')
26
+ .action(async (options) => {
27
+ try {
28
+ const repoRoot = getRepoRoot();
29
+ const { importConstitution, importSpecs } = await import('@ctxkit/speckit-bridge');
30
+ let totalDecisions = 0;
31
+ let totalContracts = 0;
32
+ let totalGotchas = 0;
33
+ const allFilesUpdated = [];
34
+ // Import constitution
35
+ const constResult = importConstitution(repoRoot, options.constitution, options.dryRun);
36
+ totalDecisions += constResult.decisions;
37
+ totalContracts += constResult.contracts;
38
+ allFilesUpdated.push(...constResult.files_updated);
39
+ // Import specs
40
+ const specsResult = importSpecs(repoRoot, options.specs, options.dryRun);
41
+ totalContracts += specsResult.contracts;
42
+ totalGotchas += specsResult.gotchas;
43
+ allFilesUpdated.push(...specsResult.files_updated);
44
+ if (options.json) {
45
+ console.log(JSON.stringify({
46
+ imported: {
47
+ decisions: totalDecisions,
48
+ contracts: totalContracts,
49
+ gotchas: totalGotchas,
50
+ },
51
+ files_updated: allFilesUpdated,
52
+ dry_run: !!options.dryRun,
53
+ }, null, 2));
54
+ }
55
+ else {
56
+ console.log(`Import ${options.dryRun ? '(dry-run) ' : ''}complete:`);
57
+ console.log(` Decisions: ${totalDecisions}`);
58
+ console.log(` Contracts: ${totalContracts}`);
59
+ console.log(` Gotchas: ${totalGotchas}`);
60
+ if (allFilesUpdated.length > 0) {
61
+ console.log(` Files updated: ${allFilesUpdated.join(', ')}`);
62
+ }
63
+ }
64
+ }
65
+ catch (error) {
66
+ const message = error instanceof Error ? error.message : String(error);
67
+ if (options.json) {
68
+ console.log(JSON.stringify({ error: message }));
69
+ }
70
+ else {
71
+ console.error(`Error: ${message}`);
72
+ }
73
+ process.exit(1);
74
+ }
75
+ });
76
+ speckitCommand
77
+ .command('export')
78
+ .description('Export .ctx content to spec-kit format')
79
+ .option('--output <dir>', 'Output directory for spec-kit files', 'specs/exported/')
80
+ .option('--format <md|yaml>', 'Output format', 'md')
81
+ .option('--json', 'Output as JSON')
82
+ .action(async (options) => {
83
+ try {
84
+ const repoRoot = getRepoRoot();
85
+ const { exportToSpecKit } = await import('@ctxkit/speckit-bridge');
86
+ const result = exportToSpecKit(repoRoot, options.output, options.format);
87
+ if (options.json) {
88
+ console.log(JSON.stringify(result, null, 2));
89
+ }
90
+ else {
91
+ if (result.exported_files.length === 0) {
92
+ console.log('No .ctx files with exportable content found.');
93
+ }
94
+ else {
95
+ console.log('Export complete:');
96
+ for (const f of result.exported_files) {
97
+ console.log(` - ${f}`);
98
+ }
99
+ }
100
+ }
101
+ }
102
+ catch (error) {
103
+ const message = error instanceof Error ? error.message : String(error);
104
+ if (options.json) {
105
+ console.log(JSON.stringify({ error: message }));
106
+ }
107
+ else {
108
+ console.error(`Error: ${message}`);
109
+ }
110
+ process.exit(1);
111
+ }
112
+ });
113
+ speckitCommand
114
+ .command('validate')
115
+ .description('Validate .ctx files against constitution')
116
+ .option('--constitution <path>', 'Path to constitution file', '.specify/memory/constitution.md')
117
+ .option('--json', 'Output as JSON')
118
+ .action(async (options) => {
119
+ try {
120
+ const repoRoot = getRepoRoot();
121
+ const { validateConstitution } = await import('@ctxkit/speckit-bridge');
122
+ const result = validateConstitution(repoRoot, options.constitution);
123
+ if (options.json) {
124
+ console.log(JSON.stringify(result, null, 2));
125
+ }
126
+ else {
127
+ if (result.valid) {
128
+ console.log('All .ctx files are compliant with the constitution.');
129
+ }
130
+ else {
131
+ console.log('Validation failed:');
132
+ for (const v of result.violations) {
133
+ console.log(` [${v.severity}] ${v.ctx_path}: ${v.violation}`);
134
+ console.log(` Principle: ${v.principle}`);
135
+ }
136
+ }
137
+ }
138
+ if (!result.valid) {
139
+ process.exit(1);
140
+ }
141
+ }
142
+ catch (error) {
143
+ const message = error instanceof Error ? error.message : String(error);
144
+ if (options.json) {
145
+ console.log(JSON.stringify({ error: message }));
146
+ }
147
+ else {
148
+ console.error(`Error: ${message}`);
149
+ }
150
+ process.exit(1);
151
+ }
152
+ });
153
+ speckitCommand
154
+ .command('sync')
155
+ .description('Bidirectional sync between spec-kit and .ctx')
156
+ .option('--dry-run', 'Preview changes without writing')
157
+ .option('--force <direction>', 'Force sync direction (spec-to-ctx | ctx-to-spec)')
158
+ .option('--json', 'Output as JSON')
159
+ .action(async (options) => {
160
+ try {
161
+ const repoRoot = getRepoRoot();
162
+ const { syncBidirectional } = await import('@ctxkit/speckit-bridge');
163
+ const result = syncBidirectional(repoRoot, {
164
+ dryRun: options.dryRun,
165
+ forceDirection: options.force,
166
+ });
167
+ if (options.json) {
168
+ console.log(JSON.stringify(result, null, 2));
169
+ }
170
+ else {
171
+ console.log(`Sync ${options.dryRun ? '(dry-run) ' : ''}complete:`);
172
+ console.log(` Synced: ${result.synced}`);
173
+ console.log(` Conflicts: ${result.conflicts}`);
174
+ if (result.files_updated.length > 0) {
175
+ console.log(` .ctx files updated: ${result.files_updated.join(', ')}`);
176
+ }
177
+ if (result.specs_updated.length > 0) {
178
+ console.log(` Spec files updated: ${result.specs_updated.join(', ')}`);
179
+ }
180
+ if (result.conflicts > 0) {
181
+ console.log('\n Conflicts detected. Use --force to resolve.');
182
+ }
183
+ }
184
+ }
185
+ catch (error) {
186
+ const message = error instanceof Error ? error.message : String(error);
187
+ if (options.json) {
188
+ console.log(JSON.stringify({ error: message }));
189
+ }
190
+ else {
191
+ console.error(`Error: ${message}`);
192
+ }
193
+ process.exit(1);
194
+ }
195
+ });
196
+ //# sourceMappingURL=speckit-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speckit-cmd.js","sourceRoot":"","sources":["../../src/commands/speckit-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const validateCommand: Command;
3
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,eAAe,SA8ExB,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { Command } from 'commander';
2
+ import { readFileSync, existsSync } from 'node:fs';
3
+ import { resolve, join, dirname } from 'node:path';
4
+ import { parseCtxFile, validateCtxFile } from '@ctxkit/core';
5
+ export const validateCommand = new Command('validate')
6
+ .description('Validate a .ctx file for structural correctness')
7
+ .argument('[path]', 'Path to .ctx file or directory containing one', '.')
8
+ .option('--check-files', 'Verify referenced files exist on disk', false)
9
+ .action((pathArg, options) => {
10
+ const targetPath = resolve(pathArg);
11
+ const ctxPath = targetPath.endsWith('.ctx')
12
+ ? targetPath
13
+ : join(targetPath, '.ctx');
14
+ if (!existsSync(ctxPath)) {
15
+ console.error(`Error: No .ctx file found at ${ctxPath}`);
16
+ process.exitCode = 1;
17
+ return;
18
+ }
19
+ let content;
20
+ try {
21
+ content = readFileSync(ctxPath, 'utf-8');
22
+ }
23
+ catch (err) {
24
+ console.error(`Error reading ${ctxPath}: ${err.message}`);
25
+ process.exitCode = 1;
26
+ return;
27
+ }
28
+ let ctx;
29
+ try {
30
+ const result = parseCtxFile(content);
31
+ ctx = result.ctx;
32
+ if (result.warnings.length > 0) {
33
+ for (const w of result.warnings) {
34
+ console.error(`Warning: ${w}`);
35
+ }
36
+ }
37
+ }
38
+ catch (err) {
39
+ console.error(`Parse error: ${err.message}`);
40
+ process.exitCode = 1;
41
+ return;
42
+ }
43
+ const errors = validateCtxFile(ctx);
44
+ // Check referenced files exist
45
+ if (options.checkFiles) {
46
+ const ctxDir = dirname(ctxPath);
47
+ for (const kf of ctx.key_files) {
48
+ if (kf.path && !existsSync(join(ctxDir, kf.path))) {
49
+ errors.push({
50
+ path: `key_files: ${kf.path}`,
51
+ message: `Referenced file does not exist: ${kf.path}`,
52
+ severity: 'warning',
53
+ });
54
+ }
55
+ }
56
+ }
57
+ // Output results
58
+ const errorCount = errors.filter((e) => e.severity === 'error').length;
59
+ const warningCount = errors.filter((e) => e.severity === 'warning').length;
60
+ if (errors.length === 0) {
61
+ console.log(`✓ ${ctxPath} is valid`);
62
+ return;
63
+ }
64
+ console.log(`Validation results for ${ctxPath}:\n`);
65
+ for (const err of errors) {
66
+ const prefix = err.severity === 'error' ? '✗ ERROR' : '⚠ WARN ';
67
+ console.log(` ${prefix} ${err.path}: ${err.message}`);
68
+ }
69
+ console.log();
70
+ console.log(` ${errorCount} error(s), ${warningCount} warning(s)`);
71
+ if (errorCount > 0) {
72
+ process.exitCode = 1;
73
+ }
74
+ });
75
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { injectCommand } from './commands/inject.js';
4
+ import { initCommand } from './commands/init.js';
5
+ import { validateCommand } from './commands/validate.js';
6
+ import { proposeCommand } from './commands/propose.js';
7
+ import { applyCommand } from './commands/apply.js';
8
+ import { sessionsCommand } from './commands/sessions.js';
9
+ import { driftCommand } from './commands/drift.js';
10
+ import { daemonCommand, dashboardCommand } from './commands/daemon.js';
11
+ import { runCommand } from './commands/run.js';
12
+ import { codexCommand } from './commands/codex.js';
13
+ import { pluginCommand } from './commands/plugin.js';
14
+ import { indexCommand } from './commands/index-cmd.js';
15
+ import { historyCommand } from './commands/history-cmd.js';
16
+ import { conflictsCommand } from './commands/conflicts-cmd.js';
17
+ import { bootstrapCommand } from './commands/bootstrap-cmd.js';
18
+ import { migrateCommand } from './commands/migrate-cmd.js';
19
+ import { hooksCommand } from './commands/hooks-cmd.js';
20
+ import { speckitCommand } from './commands/speckit-cmd.js';
21
+ import { prContextCommand } from './commands/pr-context-cmd.js';
22
+ const program = new Command();
23
+ program
24
+ .name('ctxkit')
25
+ .description('Context & Memory Manager CLI')
26
+ .version('0.1.0');
27
+ // Register subcommands
28
+ program.addCommand(injectCommand);
29
+ program.addCommand(initCommand);
30
+ program.addCommand(validateCommand);
31
+ program.addCommand(proposeCommand);
32
+ program.addCommand(applyCommand);
33
+ program.addCommand(sessionsCommand);
34
+ program.addCommand(driftCommand);
35
+ program.addCommand(daemonCommand);
36
+ program.addCommand(dashboardCommand);
37
+ program.addCommand(runCommand);
38
+ program.addCommand(codexCommand);
39
+ program.addCommand(pluginCommand);
40
+ program.addCommand(indexCommand);
41
+ program.addCommand(historyCommand);
42
+ program.addCommand(conflictsCommand);
43
+ program.addCommand(bootstrapCommand);
44
+ program.addCommand(migrateCommand);
45
+ program.addCommand(hooksCommand);
46
+ program.addCommand(speckitCommand);
47
+ program.addCommand(prContextCommand);
48
+ program.parse();
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,8BAA8B,CAAC;KAC3C,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,uBAAuB;AACvB,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AAErC,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { type CtxFile } from '@ctxkit/core';
2
+ export interface SyncResult {
3
+ dir: string;
4
+ relativePath: string;
5
+ action: 'created' | 'updated' | 'unchanged';
6
+ tokens: number;
7
+ }
8
+ export interface SyncOptions {
9
+ repoRoot: string;
10
+ budget: number;
11
+ dryRun: boolean;
12
+ }
13
+ /**
14
+ * Walk the repo to find all directories containing .ctx files.
15
+ */
16
+ export declare function findCtxDirectories(repoRoot: string): string[];
17
+ /**
18
+ * Generate the CtxKit-managed content block for a directory's .ctx file.
19
+ */
20
+ export declare function generateCtxKitSection(ctx: CtxFile, dir: string, repoRoot: string, budget: number): string;
21
+ /**
22
+ * Merge CtxKit-managed content into an existing AGENTS.md file,
23
+ * preserving user-written content outside the markers.
24
+ */
25
+ export declare function mergeWithExisting(existingContent: string, ctxkitSection: string): string;
26
+ /**
27
+ * Extract the CtxKit-managed section from an existing file.
28
+ */
29
+ export declare function extractManagedSection(content: string): string | null;
30
+ /**
31
+ * Run the sync-agents command: walk .ctx hierarchy, generate AGENTS.md files.
32
+ */
33
+ export declare function syncAgents(options: SyncOptions): SyncResult[];
34
+ //# sourceMappingURL=agents-md.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents-md.d.ts","sourceRoot":"","sources":["../../src/services/agents-md.ts"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,OAAO,EAEb,MAAM,cAAc,CAAC;AAKtB,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiC7D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,CAsGR;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,GACpB,MAAM,CAgBR;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKpE;AAUD;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,EAAE,CA+E7D"}
@@ -0,0 +1,248 @@
1
+ import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from 'node:fs';
2
+ import { join, relative } from 'node:path';
3
+ import { parseCtxFile, redactSecrets, estimateTokens, loadProfile, } from '@ctxkit/core';
4
+ const CTXKIT_BEGIN = '<!-- CTXKIT:BEGIN - Managed by CtxKit. Do not edit this section. -->';
5
+ const CTXKIT_END = '<!-- CTXKIT:END -->';
6
+ /**
7
+ * Walk the repo to find all directories containing .ctx files.
8
+ */
9
+ export function findCtxDirectories(repoRoot) {
10
+ const dirs = [];
11
+ function walk(dir) {
12
+ const ctxPath = join(dir, '.ctx');
13
+ if (existsSync(ctxPath) && statSync(ctxPath).isFile()) {
14
+ dirs.push(dir);
15
+ }
16
+ let entries;
17
+ try {
18
+ entries = readdirSync(dir);
19
+ }
20
+ catch {
21
+ return;
22
+ }
23
+ for (const entry of entries) {
24
+ if (entry.startsWith('.') || entry === 'node_modules' || entry === 'dist') {
25
+ continue;
26
+ }
27
+ const fullPath = join(dir, entry);
28
+ try {
29
+ if (statSync(fullPath).isDirectory()) {
30
+ walk(fullPath);
31
+ }
32
+ }
33
+ catch {
34
+ // Skip inaccessible dirs
35
+ }
36
+ }
37
+ }
38
+ walk(repoRoot);
39
+ return dirs;
40
+ }
41
+ /**
42
+ * Generate the CtxKit-managed content block for a directory's .ctx file.
43
+ */
44
+ export function generateCtxKitSection(ctx, dir, repoRoot, budget) {
45
+ const contextBudget = Math.floor(budget * 0.7);
46
+ const lines = [];
47
+ lines.push(`<!-- Generated: ${new Date().toISOString()} | Source: .ctx hierarchy -->`);
48
+ lines.push('');
49
+ lines.push('## CtxKit Project Context');
50
+ lines.push('');
51
+ if (ctx.summary) {
52
+ lines.push(redactSecrets(ctx.summary));
53
+ lines.push('');
54
+ }
55
+ // Key Files
56
+ if (ctx.key_files.length > 0) {
57
+ lines.push('### Key Files');
58
+ for (const kf of ctx.key_files) {
59
+ const purpose = kf.purpose ? ` \u2014 ${redactSecrets(kf.purpose)}` : '';
60
+ lines.push(`- \`${kf.path}\`${purpose}`);
61
+ }
62
+ lines.push('');
63
+ }
64
+ // Decisions (only active ones)
65
+ const activeDecisions = ctx.decisions.filter((d) => d.status === 'accepted');
66
+ if (activeDecisions.length > 0) {
67
+ lines.push('### Decisions');
68
+ for (const d of activeDecisions) {
69
+ const date = d.date ? ` (decided ${d.date})` : '';
70
+ lines.push(`- ${redactSecrets(d.title)}${date}`);
71
+ }
72
+ lines.push('');
73
+ }
74
+ // Gotchas
75
+ if (ctx.gotchas.length > 0) {
76
+ lines.push('### Gotchas');
77
+ for (const g of ctx.gotchas) {
78
+ lines.push(`- ${redactSecrets(g.text)}`);
79
+ }
80
+ lines.push('');
81
+ }
82
+ // Contracts
83
+ if (ctx.contracts.length > 0) {
84
+ lines.push('### Contracts');
85
+ for (const c of ctx.contracts) {
86
+ lines.push(`- **${c.name}**: ${redactSecrets(c.content).slice(0, 100)}`);
87
+ }
88
+ lines.push('');
89
+ }
90
+ // Check context budget — truncate if needed
91
+ let contextContent = lines.join('\n');
92
+ let contextTokens = estimateTokens(contextContent);
93
+ if (contextTokens > contextBudget) {
94
+ // Progressively remove sections to fit budget
95
+ // Remove contracts first (least critical for AGENTS.md)
96
+ if (ctx.contracts.length > 0) {
97
+ const contractIdx = contextContent.indexOf('### Contracts');
98
+ if (contractIdx >= 0) {
99
+ contextContent = contextContent.slice(0, contractIdx).trimEnd() + '\n';
100
+ contextTokens = estimateTokens(contextContent);
101
+ }
102
+ }
103
+ // If still over, remove gotchas
104
+ if (contextTokens > contextBudget && ctx.gotchas.length > 0) {
105
+ const gotchaIdx = contextContent.indexOf('### Gotchas');
106
+ if (gotchaIdx >= 0) {
107
+ contextContent = contextContent.slice(0, gotchaIdx).trimEnd() + '\n';
108
+ contextTokens = estimateTokens(contextContent);
109
+ }
110
+ }
111
+ }
112
+ // Policy section (uses remaining budget)
113
+ const policyLines = [];
114
+ policyLines.push('## CtxKit Usage Policy');
115
+ policyLines.push('');
116
+ policyLines.push('When working in this project, you have access to CtxKit tools for context and memory management.');
117
+ policyLines.push('');
118
+ policyLines.push('### Preferred: MCP Tools');
119
+ policyLines.push('If CtxKit MCP server is available (check with `/mcp`), use these tools:');
120
+ policyLines.push('- `ctxkit.context_pack` \u2014 Get relevant context before responding');
121
+ policyLines.push('- `ctxkit.log_event` \u2014 Log tool calls for session tracking');
122
+ policyLines.push('- `ctxkit.propose_update` \u2014 Propose .ctx memory updates');
123
+ policyLines.push('- `ctxkit.memory.search` \u2014 Search project memory');
124
+ policyLines.push('');
125
+ policyLines.push('### Fallback: CLI Commands');
126
+ policyLines.push('If MCP is unavailable, use the CLI directly:');
127
+ policyLines.push('- `ctxkit inject "<request>" --json` \u2014 Get context pack');
128
+ policyLines.push('- `ctxkit sessions list --json` \u2014 List sessions');
129
+ policyLines.push('- `ctxkit propose --json` \u2014 Propose updates');
130
+ policyLines.push('');
131
+ policyLines.push('### Best Practices');
132
+ policyLines.push('- Call `ctxkit.context_pack(mode=turn)` before responding to user prompts');
133
+ policyLines.push('- Call `ctxkit.log_event` after each tool invocation');
134
+ policyLines.push('- Call `ctxkit.propose_update` when you learn something new about the project');
135
+ const fullContent = contextContent + '\n' + policyLines.join('\n');
136
+ return fullContent;
137
+ }
138
+ /**
139
+ * Merge CtxKit-managed content into an existing AGENTS.md file,
140
+ * preserving user-written content outside the markers.
141
+ */
142
+ export function mergeWithExisting(existingContent, ctxkitSection) {
143
+ const beginIdx = existingContent.indexOf(CTXKIT_BEGIN);
144
+ const endIdx = existingContent.indexOf(CTXKIT_END);
145
+ const managedBlock = `${CTXKIT_BEGIN}\n${ctxkitSection}\n${CTXKIT_END}`;
146
+ if (beginIdx >= 0 && endIdx >= 0) {
147
+ // Replace existing managed section
148
+ const before = existingContent.slice(0, beginIdx);
149
+ const after = existingContent.slice(endIdx + CTXKIT_END.length);
150
+ return before + managedBlock + after;
151
+ }
152
+ // No markers found — append at the end
153
+ const separator = existingContent.endsWith('\n') ? '\n' : '\n\n';
154
+ return existingContent + separator + managedBlock + '\n';
155
+ }
156
+ /**
157
+ * Extract the CtxKit-managed section from an existing file.
158
+ */
159
+ export function extractManagedSection(content) {
160
+ const beginIdx = content.indexOf(CTXKIT_BEGIN);
161
+ const endIdx = content.indexOf(CTXKIT_END);
162
+ if (beginIdx < 0 || endIdx < 0)
163
+ return null;
164
+ return content.slice(beginIdx + CTXKIT_BEGIN.length, endIdx).trim();
165
+ }
166
+ /**
167
+ * Strip the generated timestamp line for idempotency comparison.
168
+ * The timestamp changes on every run but the content is otherwise identical.
169
+ */
170
+ function stripTimestamp(text) {
171
+ return text.replace(/<!-- Generated: .* \| Source: .ctx hierarchy -->\n?/, '');
172
+ }
173
+ /**
174
+ * Run the sync-agents command: walk .ctx hierarchy, generate AGENTS.md files.
175
+ */
176
+ export function syncAgents(options) {
177
+ const { repoRoot, budget, dryRun } = options;
178
+ const results = [];
179
+ // Load profile for ignore policies
180
+ const profile = loadProfile(repoRoot);
181
+ const neverRead = new Set(profile.ignore.never_read);
182
+ // Find all directories with .ctx files
183
+ const ctxDirs = findCtxDirectories(repoRoot);
184
+ for (const dir of ctxDirs) {
185
+ const ctxPath = join(dir, '.ctx');
186
+ const relDir = relative(repoRoot, dir) || '.';
187
+ const agentsPath = join(dir, 'AGENTS.md');
188
+ // Check ignore policy
189
+ const relCtxPath = relative(repoRoot, ctxPath);
190
+ if (neverRead.has(relCtxPath) || neverRead.has(relDir)) {
191
+ continue;
192
+ }
193
+ // Parse .ctx file
194
+ let ctx;
195
+ try {
196
+ const raw = readFileSync(ctxPath, 'utf-8');
197
+ const result = parseCtxFile(raw);
198
+ ctx = result.ctx;
199
+ }
200
+ catch {
201
+ continue; // Skip invalid .ctx files
202
+ }
203
+ // Generate CtxKit section
204
+ const section = generateCtxKitSection(ctx, dir, repoRoot, budget);
205
+ const tokens = estimateTokens(section);
206
+ // Check existing file for idempotency
207
+ if (existsSync(agentsPath)) {
208
+ const existing = readFileSync(agentsPath, 'utf-8');
209
+ const existingManaged = extractManagedSection(existing);
210
+ // Compare without timestamps (they change every run)
211
+ if (existingManaged !== null && stripTimestamp(existingManaged) === stripTimestamp(section.trim())) {
212
+ results.push({
213
+ dir: relDir,
214
+ relativePath: relative(repoRoot, agentsPath),
215
+ action: 'unchanged',
216
+ tokens,
217
+ });
218
+ continue;
219
+ }
220
+ // Merge with existing content (preserve user sections)
221
+ const merged = mergeWithExisting(existing, section);
222
+ if (!dryRun) {
223
+ writeFileSync(agentsPath, merged, 'utf-8');
224
+ }
225
+ results.push({
226
+ dir: relDir,
227
+ relativePath: relative(repoRoot, agentsPath),
228
+ action: 'updated',
229
+ tokens,
230
+ });
231
+ }
232
+ else {
233
+ // Create new file
234
+ const newContent = `${CTXKIT_BEGIN}\n${section}\n${CTXKIT_END}\n`;
235
+ if (!dryRun) {
236
+ writeFileSync(agentsPath, newContent, 'utf-8');
237
+ }
238
+ results.push({
239
+ dir: relDir,
240
+ relativePath: relative(repoRoot, agentsPath),
241
+ action: 'created',
242
+ tokens,
243
+ });
244
+ }
245
+ }
246
+ return results;
247
+ }
248
+ //# sourceMappingURL=agents-md.js.map