openclaw-telegram-manager 1.0.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 (138) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +110 -0
  3. package/dist/commands/archive.d.ts +4 -0
  4. package/dist/commands/archive.d.ts.map +1 -0
  5. package/dist/commands/archive.js +71 -0
  6. package/dist/commands/archive.js.map +1 -0
  7. package/dist/commands/doctor-all.d.ts +3 -0
  8. package/dist/commands/doctor-all.d.ts.map +1 -0
  9. package/dist/commands/doctor-all.js +193 -0
  10. package/dist/commands/doctor-all.js.map +1 -0
  11. package/dist/commands/doctor.d.ts +3 -0
  12. package/dist/commands/doctor.d.ts.map +1 -0
  13. package/dist/commands/doctor.js +74 -0
  14. package/dist/commands/doctor.js.map +1 -0
  15. package/dist/commands/help.d.ts +4 -0
  16. package/dist/commands/help.d.ts.map +1 -0
  17. package/dist/commands/help.js +8 -0
  18. package/dist/commands/help.js.map +1 -0
  19. package/dist/commands/init.d.ts +17 -0
  20. package/dist/commands/init.d.ts.map +1 -0
  21. package/dist/commands/init.js +304 -0
  22. package/dist/commands/init.js.map +1 -0
  23. package/dist/commands/list.d.ts +3 -0
  24. package/dist/commands/list.d.ts.map +1 -0
  25. package/dist/commands/list.js +22 -0
  26. package/dist/commands/list.js.map +1 -0
  27. package/dist/commands/rename.d.ts +3 -0
  28. package/dist/commands/rename.d.ts.map +1 -0
  29. package/dist/commands/rename.js +115 -0
  30. package/dist/commands/rename.js.map +1 -0
  31. package/dist/commands/snooze.d.ts +3 -0
  32. package/dist/commands/snooze.d.ts.map +1 -0
  33. package/dist/commands/snooze.js +52 -0
  34. package/dist/commands/snooze.js.map +1 -0
  35. package/dist/commands/status.d.ts +3 -0
  36. package/dist/commands/status.d.ts.map +1 -0
  37. package/dist/commands/status.js +48 -0
  38. package/dist/commands/status.js.map +1 -0
  39. package/dist/commands/sync.d.ts +3 -0
  40. package/dist/commands/sync.d.ts.map +1 -0
  41. package/dist/commands/sync.js +38 -0
  42. package/dist/commands/sync.js.map +1 -0
  43. package/dist/commands/upgrade.d.ts +3 -0
  44. package/dist/commands/upgrade.d.ts.map +1 -0
  45. package/dist/commands/upgrade.js +52 -0
  46. package/dist/commands/upgrade.js.map +1 -0
  47. package/dist/index.d.ts +25 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +30 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/lib/audit.d.ts +12 -0
  52. package/dist/lib/audit.d.ts.map +1 -0
  53. package/dist/lib/audit.js +35 -0
  54. package/dist/lib/audit.js.map +1 -0
  55. package/dist/lib/auth.d.ts +26 -0
  56. package/dist/lib/auth.d.ts.map +1 -0
  57. package/dist/lib/auth.js +73 -0
  58. package/dist/lib/auth.js.map +1 -0
  59. package/dist/lib/capsule.d.ts +27 -0
  60. package/dist/lib/capsule.d.ts.map +1 -0
  61. package/dist/lib/capsule.js +130 -0
  62. package/dist/lib/capsule.js.map +1 -0
  63. package/dist/lib/config-restart.d.ts +23 -0
  64. package/dist/lib/config-restart.d.ts.map +1 -0
  65. package/dist/lib/config-restart.js +129 -0
  66. package/dist/lib/config-restart.js.map +1 -0
  67. package/dist/lib/doctor-checks.d.ts +50 -0
  68. package/dist/lib/doctor-checks.d.ts.map +1 -0
  69. package/dist/lib/doctor-checks.js +421 -0
  70. package/dist/lib/doctor-checks.js.map +1 -0
  71. package/dist/lib/include-generator.d.ts +35 -0
  72. package/dist/lib/include-generator.d.ts.map +1 -0
  73. package/dist/lib/include-generator.js +140 -0
  74. package/dist/lib/include-generator.js.map +1 -0
  75. package/dist/lib/registry.d.ts +27 -0
  76. package/dist/lib/registry.d.ts.map +1 -0
  77. package/dist/lib/registry.js +154 -0
  78. package/dist/lib/registry.js.map +1 -0
  79. package/dist/lib/security.d.ts +57 -0
  80. package/dist/lib/security.d.ts.map +1 -0
  81. package/dist/lib/security.js +133 -0
  82. package/dist/lib/security.js.map +1 -0
  83. package/dist/lib/telegram.d.ts +55 -0
  84. package/dist/lib/telegram.d.ts.map +1 -0
  85. package/dist/lib/telegram.js +254 -0
  86. package/dist/lib/telegram.js.map +1 -0
  87. package/dist/lib/types.d.ts +120 -0
  88. package/dist/lib/types.d.ts.map +1 -0
  89. package/dist/lib/types.js +85 -0
  90. package/dist/lib/types.js.map +1 -0
  91. package/dist/setup.d.ts +3 -0
  92. package/dist/setup.d.ts.map +1 -0
  93. package/dist/setup.js +333 -0
  94. package/dist/setup.js.map +1 -0
  95. package/dist/tool.d.ts +15 -0
  96. package/dist/tool.d.ts.map +1 -0
  97. package/dist/tool.js +201 -0
  98. package/dist/tool.js.map +1 -0
  99. package/openclaw.plugin.json +9 -0
  100. package/package.json +48 -0
  101. package/skills/topic/SKILL.md +35 -0
  102. package/src/commands/archive.ts +89 -0
  103. package/src/commands/doctor-all.ts +243 -0
  104. package/src/commands/doctor.ts +100 -0
  105. package/src/commands/help.ts +11 -0
  106. package/src/commands/init.ts +376 -0
  107. package/src/commands/list.ts +28 -0
  108. package/src/commands/rename.ts +140 -0
  109. package/src/commands/snooze.ts +69 -0
  110. package/src/commands/status.ts +59 -0
  111. package/src/commands/sync.ts +46 -0
  112. package/src/commands/upgrade.ts +64 -0
  113. package/src/index.ts +54 -0
  114. package/src/lib/audit.ts +44 -0
  115. package/src/lib/auth.ts +96 -0
  116. package/src/lib/capsule.ts +206 -0
  117. package/src/lib/config-restart.ts +167 -0
  118. package/src/lib/doctor-checks.ts +639 -0
  119. package/src/lib/include-generator.ts +174 -0
  120. package/src/lib/registry.ts +197 -0
  121. package/src/lib/security.ts +174 -0
  122. package/src/lib/telegram.ts +311 -0
  123. package/src/lib/types.ts +172 -0
  124. package/src/setup.ts +402 -0
  125. package/src/templates/base/COMMANDS.md +3 -0
  126. package/src/templates/base/CRON.md +3 -0
  127. package/src/templates/base/LINKS.md +3 -0
  128. package/src/templates/base/NOTES.md +3 -0
  129. package/src/templates/base/README.md +3 -0
  130. package/src/templates/base/STATUS.md +13 -0
  131. package/src/templates/base/TODO.md +11 -0
  132. package/src/templates/overlays/coding/ARCHITECTURE.md +3 -0
  133. package/src/templates/overlays/coding/DEPLOY.md +3 -0
  134. package/src/templates/overlays/marketing/CAMPAIGNS.md +3 -0
  135. package/src/templates/overlays/marketing/METRICS.md +3 -0
  136. package/src/templates/overlays/research/FINDINGS.md +3 -0
  137. package/src/templates/overlays/research/SOURCES.md +3 -0
  138. package/src/tool.ts +282 -0
@@ -0,0 +1,129 @@
1
+ // ── Config restart via config.patch no-op ──────────────────────────────
2
+ //
3
+ // Triggers Gateway restart by patching a no-op value, which causes
4
+ // OpenClaw to reload all $include files.
5
+ // ── Cooldown tracking (module-level) ───────────────────────────────────
6
+ const COOLDOWN_MS = 60_000; // 60 seconds
7
+ let lastRestartTimestamp = 0;
8
+ // ── Backoff config ─────────────────────────────────────────────────────
9
+ const MAX_RETRIES = 3;
10
+ const BASE_DELAY_MS = 1000; // 1s, 2s, 4s exponential backoff
11
+ // ── Main function ──────────────────────────────────────────────────────
12
+ /**
13
+ * Trigger a Gateway restart via config.patch no-op.
14
+ *
15
+ * - Enforces a 60-second cooldown between calls
16
+ * - Retries up to 3 times on baseHash mismatch with exponential backoff
17
+ * - Falls back to a user message if RPC is unavailable
18
+ */
19
+ export async function triggerRestart(rpc, logger) {
20
+ // Cooldown check
21
+ const now = Date.now();
22
+ if (now - lastRestartTimestamp < COOLDOWN_MS) {
23
+ const remainingSec = Math.ceil((COOLDOWN_MS - (now - lastRestartTimestamp)) / 1000);
24
+ logger.info(`Config restart cooldown active. ${remainingSec}s remaining.`);
25
+ return {
26
+ success: true, // Not a failure — just throttled
27
+ };
28
+ }
29
+ // If RPC is not available, return fallback
30
+ if (!rpc) {
31
+ return {
32
+ success: false,
33
+ fallbackMessage: 'Config updated. Run `openclaw gateway restart` or send SIGUSR1 to apply.',
34
+ };
35
+ }
36
+ // Retry loop with exponential backoff
37
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
38
+ try {
39
+ // Get current config to capture baseHash
40
+ const configResult = await rpc.call('config.get', {});
41
+ const baseHash = configResult['baseHash'];
42
+ if (!baseHash) {
43
+ logger.warn('config.get did not return baseHash; attempting patch without it');
44
+ }
45
+ // Patch with no-op change to trigger restart
46
+ const patchParams = {
47
+ patch: {
48
+ skills: {
49
+ entries: {
50
+ 'telegram-manager': {
51
+ lastSync: new Date().toISOString(),
52
+ },
53
+ },
54
+ },
55
+ },
56
+ };
57
+ if (baseHash) {
58
+ patchParams['baseHash'] = baseHash;
59
+ }
60
+ await rpc.call('config.patch', patchParams);
61
+ // Success — update cooldown timestamp
62
+ lastRestartTimestamp = Date.now();
63
+ logger.info('Gateway restart triggered via config.patch');
64
+ return { success: true };
65
+ }
66
+ catch (err) {
67
+ const isBaseHashMismatch = isHashMismatchError(err);
68
+ if (isBaseHashMismatch && attempt < MAX_RETRIES) {
69
+ const delay = BASE_DELAY_MS * Math.pow(2, attempt);
70
+ logger.warn(`config.patch baseHash mismatch (attempt ${attempt + 1}/${MAX_RETRIES + 1}). Retrying in ${delay}ms...`);
71
+ await sleep(delay);
72
+ continue;
73
+ }
74
+ // All retries exhausted or non-retryable error
75
+ const errMsg = err instanceof Error ? err.message : String(err);
76
+ logger.error(`config.patch failed after ${attempt + 1} attempt(s): ${errMsg}`);
77
+ return {
78
+ success: false,
79
+ fallbackMessage: 'Config updated. Run `openclaw gateway restart` or send SIGUSR1 to apply.',
80
+ };
81
+ }
82
+ }
83
+ // Should not reach here, but just in case
84
+ return {
85
+ success: false,
86
+ fallbackMessage: 'Config updated. Run `openclaw gateway restart` or send SIGUSR1 to apply.',
87
+ };
88
+ }
89
+ // ── Helpers ────────────────────────────────────────────────────────────
90
+ function isHashMismatchError(err) {
91
+ if (err && typeof err === 'object') {
92
+ // Check for common error shape
93
+ if ('code' in err && err.code === 'BASE_HASH_MISMATCH') {
94
+ return true;
95
+ }
96
+ if ('message' in err) {
97
+ const msg = err.message;
98
+ return msg.toLowerCase().includes('basehash') || msg.toLowerCase().includes('hash mismatch');
99
+ }
100
+ }
101
+ return false;
102
+ }
103
+ function sleep(ms) {
104
+ return new Promise((resolve) => setTimeout(resolve, ms));
105
+ }
106
+ /**
107
+ * Check if configWrites is enabled in the plugin config via RPC.
108
+ */
109
+ export async function getConfigWrites(rpc) {
110
+ if (!rpc)
111
+ return false;
112
+ try {
113
+ const config = await rpc.call('config.get', {});
114
+ const skills = config['skills'];
115
+ const entries = skills?.['entries'];
116
+ const tmConfig = entries?.['telegram-manager'];
117
+ return tmConfig?.['configWrites'] === true;
118
+ }
119
+ catch {
120
+ return false;
121
+ }
122
+ }
123
+ /**
124
+ * Reset the cooldown timer (for testing purposes).
125
+ */
126
+ export function resetCooldown() {
127
+ lastRestartTimestamp = 0;
128
+ }
129
+ //# sourceMappingURL=config-restart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-restart.js","sourceRoot":"","sources":["../../src/lib/config-restart.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { TopicEntry, DoctorCheckResult, Registry } from './types.js';
2
+ /**
3
+ * Check that the registry entry's capsule path exists on disk.
4
+ */
5
+ export declare function runRegistryChecks(entry: TopicEntry, projectsBase: string): DoctorCheckResult[];
6
+ /**
7
+ * Check for capsule folders in projects/ that have no matching registry entry.
8
+ */
9
+ export declare function runOrphanCheck(projectsBase: string, registrySlugs: Set<string>): DoctorCheckResult[];
10
+ /**
11
+ * Check capsule structure: required files, overlay files, capsule version.
12
+ */
13
+ export declare function runCapsuleChecks(entry: TopicEntry, projectsBase: string): DoctorCheckResult[];
14
+ /**
15
+ * Check STATUS.md content quality.
16
+ */
17
+ export declare function runStatusQualityChecks(statusContent: string, entry: TopicEntry): DoctorCheckResult[];
18
+ /**
19
+ * Check that task IDs in "Next 3 actions" exist in TODO.md.
20
+ */
21
+ export declare function runNextVsTodoChecks(statusContent: string, todoContent: string): DoctorCheckResult[];
22
+ /**
23
+ * Check COMMANDS.md and LINKS.md for relevant topic types.
24
+ */
25
+ export declare function runCommandsLinksChecks(entry: TopicEntry, capsuleFiles: Map<string, string>): DoctorCheckResult[];
26
+ /**
27
+ * Check CRON.md for job ID presence and optionally validate against cron/jobs.json.
28
+ */
29
+ export declare function runCronChecks(cronContent: string, cronJobsPath?: string): DoctorCheckResult[];
30
+ /**
31
+ * Check per-topic systemPrompt and skills against canonical templates.
32
+ */
33
+ export declare function runConfigChecks(entry: TopicEntry, includeContent: string, registry: Registry): DoctorCheckResult[];
34
+ /**
35
+ * Check if the generated include file's registry-hash matches the current registry.
36
+ */
37
+ export declare function runIncludeDriftCheck(includeFileContent: string, registry: Registry): DoctorCheckResult[];
38
+ /**
39
+ * Check for spam control: if consecutiveSilentDoctors >= 3, suggest auto-snooze.
40
+ */
41
+ export declare function runSpamControlCheck(entry: TopicEntry): DoctorCheckResult[];
42
+ /**
43
+ * Run all applicable doctor checks for a single topic entry.
44
+ * Returns combined results from all check categories.
45
+ *
46
+ * This is a convenience function for command handlers.
47
+ * It reads capsule files and runs all checks.
48
+ */
49
+ export declare function runAllChecksForTopic(entry: TopicEntry, projectsBase: string, includeContent?: string, registry?: Registry, cronJobsPath?: string): DoctorCheckResult[];
50
+ //# sourceMappingURL=doctor-checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-checks.d.ts","sourceRoot":"","sources":["../../src/lib/doctor-checks.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAqB1E;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,YAAY,EAAE,MAAM,GACnB,iBAAiB,EAAE,CA2BrB;AAID;;GAEG;AACH,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GACzB,iBAAiB,EAAE,CA4BrB;AAID;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EACjB,YAAY,EAAE,MAAM,GACnB,iBAAiB,EAAE,CAkDrB;AAUD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,UAAU,GAChB,iBAAiB,EAAE,CAiFrB;AAID;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAClB,iBAAiB,EAAE,CAoCrB;AAID;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,UAAU,EACjB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,iBAAiB,EAAE,CA4BrB;AAmBD;;GAEG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,GACpB,iBAAiB,EAAE,CA4CrB;AAID;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EACjB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,QAAQ,GACjB,iBAAiB,EAAE,CA2DrB;AAID;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,kBAAkB,EAAE,MAAM,EAC1B,QAAQ,EAAE,QAAQ,GACjB,iBAAiB,EAAE,CA8BrB;AAID;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,GAChB,iBAAiB,EAAE,CAerB;AAID;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EACjB,YAAY,EAAE,MAAM,EACpB,cAAc,CAAC,EAAE,MAAM,EACvB,QAAQ,CAAC,EAAE,QAAQ,EACnB,YAAY,CAAC,EAAE,MAAM,GACpB,iBAAiB,EAAE,CAmDrB"}
@@ -0,0 +1,421 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { Severity, CAPSULE_VERSION, OVERLAY_FILES, SPAM_THRESHOLD, } from './types.js';
4
+ import { jailCheck } from './security.js';
5
+ import { computeRegistryHash, extractRegistryHash } from './include-generator.js';
6
+ // ── Helper: check if a checkId should be ignored ───────────────────────
7
+ function isIgnored(entry, checkId) {
8
+ return entry.ignoreChecks.includes(checkId);
9
+ }
10
+ function check(severity, checkId, message, fixable) {
11
+ return { severity, checkId, message, fixable };
12
+ }
13
+ // ── Registry / mapping checks ──────────────────────────────────────────
14
+ /**
15
+ * Check that the registry entry's capsule path exists on disk.
16
+ */
17
+ export function runRegistryChecks(entry, projectsBase) {
18
+ const results = [];
19
+ const capsuleDir = path.join(projectsBase, entry.slug);
20
+ // Check path exists
21
+ if (!fs.existsSync(capsuleDir)) {
22
+ results.push(check(Severity.ERROR, 'pathMissing', `Capsule path does not exist: projects/${entry.slug}/`, false));
23
+ return results; // No point checking further if path doesn't exist
24
+ }
25
+ // Check that the folder name matches the slug
26
+ try {
27
+ const stat = fs.statSync(capsuleDir);
28
+ if (!stat.isDirectory()) {
29
+ results.push(check(Severity.ERROR, 'pathNotDir', `projects/${entry.slug} exists but is not a directory`, false));
30
+ }
31
+ }
32
+ catch {
33
+ results.push(check(Severity.ERROR, 'pathStatFailed', `Cannot stat projects/${entry.slug}/`, false));
34
+ }
35
+ return results;
36
+ }
37
+ // ── Orphan detection ───────────────────────────────────────────────────
38
+ /**
39
+ * Check for capsule folders in projects/ that have no matching registry entry.
40
+ */
41
+ export function runOrphanCheck(projectsBase, registrySlugs) {
42
+ const results = [];
43
+ let entries;
44
+ try {
45
+ entries = fs.readdirSync(projectsBase, { withFileTypes: true });
46
+ }
47
+ catch {
48
+ return results; // Can't read directory — skip
49
+ }
50
+ for (const dirent of entries) {
51
+ if (!dirent.isDirectory())
52
+ continue;
53
+ // Skip hidden dirs and special files
54
+ if (dirent.name.startsWith('.') || dirent.name === 'audit.jsonl')
55
+ continue;
56
+ if (!registrySlugs.has(dirent.name)) {
57
+ results.push(check(Severity.WARN, 'orphanFolder', `Folder projects/${dirent.name}/ has no registry entry. Register with /topic init or delete.`, false));
58
+ }
59
+ }
60
+ return results;
61
+ }
62
+ // ── Capsule structure checks ───────────────────────────────────────────
63
+ /**
64
+ * Check capsule structure: required files, overlay files, capsule version.
65
+ */
66
+ export function runCapsuleChecks(entry, projectsBase) {
67
+ const results = [];
68
+ const capsuleDir = path.join(projectsBase, entry.slug);
69
+ if (!fs.existsSync(capsuleDir))
70
+ return results;
71
+ // STATUS.md is critical
72
+ if (!fs.existsSync(path.join(capsuleDir, 'STATUS.md'))) {
73
+ results.push(check(Severity.ERROR, 'statusMissing', 'STATUS.md is missing from capsule', true));
74
+ }
75
+ // TODO.md is important
76
+ if (!fs.existsSync(path.join(capsuleDir, 'TODO.md'))) {
77
+ if (!isIgnored(entry, 'todoMissing')) {
78
+ results.push(check(Severity.WARN, 'todoMissing', 'TODO.md is missing from capsule', true));
79
+ }
80
+ }
81
+ // Overlay files are optional but worth noting
82
+ const overlays = OVERLAY_FILES[entry.type] ?? [];
83
+ for (const file of overlays) {
84
+ if (!fs.existsSync(path.join(capsuleDir, file))) {
85
+ const checkId = `overlayMissing:${file}`;
86
+ if (!isIgnored(entry, checkId)) {
87
+ results.push(check(Severity.INFO, checkId, `Optional overlay ${file} missing for type "${entry.type}"`, true));
88
+ }
89
+ }
90
+ }
91
+ // Capsule version behind
92
+ if (entry.capsuleVersion < CAPSULE_VERSION) {
93
+ if (!isIgnored(entry, 'capsuleVersionBehind')) {
94
+ results.push(check(Severity.INFO, 'capsuleVersionBehind', `Capsule version ${entry.capsuleVersion} is behind current ${CAPSULE_VERSION}. Run /topic upgrade.`, false));
95
+ }
96
+ }
97
+ return results;
98
+ }
99
+ // ── STATUS.md quality checks ───────────────────────────────────────────
100
+ const LAST_DONE_RE = /^##\s*Last done\s*\(UTC\)/im;
101
+ const NEXT_ACTIONS_RE = /^##\s*Next 3 actions/im;
102
+ const TIMESTAMP_RE = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/;
103
+ const TASK_ID_RE = /\[T-\d+\]/g;
104
+ const ADHOC_RE = /\[AD-HOC\]/g;
105
+ /**
106
+ * Check STATUS.md content quality.
107
+ */
108
+ export function runStatusQualityChecks(statusContent, entry) {
109
+ const results = [];
110
+ // "Last done (UTC)" section check
111
+ if (!LAST_DONE_RE.test(statusContent)) {
112
+ if (!isIgnored(entry, 'lastDoneMissing')) {
113
+ results.push(check(Severity.ERROR, 'lastDoneMissing', 'STATUS.md missing "Last done (UTC)" section', true));
114
+ }
115
+ }
116
+ else {
117
+ // Check for timestamp in the section
118
+ const lastDoneIndex = statusContent.search(LAST_DONE_RE);
119
+ const sectionAfter = statusContent.slice(lastDoneIndex);
120
+ const nextSectionIndex = sectionAfter.indexOf('\n## ', 1);
121
+ const lastDoneSection = nextSectionIndex > 0
122
+ ? sectionAfter.slice(0, nextSectionIndex)
123
+ : sectionAfter;
124
+ if (!TIMESTAMP_RE.test(lastDoneSection)) {
125
+ if (!isIgnored(entry, 'lastDoneNoTimestamp')) {
126
+ results.push(check(Severity.ERROR, 'lastDoneNoTimestamp', 'STATUS.md "Last done" section has no timestamp', true));
127
+ }
128
+ }
129
+ else if (entry.status === 'active') {
130
+ // Check timestamp age (default: 3 days)
131
+ const tsMatch = lastDoneSection.match(TIMESTAMP_RE);
132
+ if (tsMatch) {
133
+ const ts = new Date(tsMatch[0]);
134
+ const ageDays = (Date.now() - ts.getTime()) / (1000 * 60 * 60 * 24);
135
+ if (ageDays > 3) {
136
+ if (!isIgnored(entry, 'lastDoneStale')) {
137
+ results.push(check(Severity.WARN, 'lastDoneStale', `STATUS.md "Last done" timestamp is ${Math.floor(ageDays)} days old`, false));
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
143
+ // "Next 3 actions" section check
144
+ if (!NEXT_ACTIONS_RE.test(statusContent)) {
145
+ if (!isIgnored(entry, 'nextActionsMissing')) {
146
+ results.push(check(Severity.ERROR, 'nextActionsMissing', 'STATUS.md missing "Next 3 actions" section', true));
147
+ }
148
+ }
149
+ else {
150
+ // Check that next actions contain task IDs
151
+ const nextActionsIndex = statusContent.search(NEXT_ACTIONS_RE);
152
+ const sectionAfter = statusContent.slice(nextActionsIndex);
153
+ const nextSectionIndex = sectionAfter.indexOf('\n## ', 1);
154
+ const nextActionsSection = nextSectionIndex > 0
155
+ ? sectionAfter.slice(0, nextSectionIndex)
156
+ : sectionAfter;
157
+ const taskIds = nextActionsSection.match(TASK_ID_RE) ?? [];
158
+ const adhocs = nextActionsSection.match(ADHOC_RE) ?? [];
159
+ if (taskIds.length === 0 && adhocs.length === 0) {
160
+ if (!isIgnored(entry, 'nextActionsEmpty')) {
161
+ results.push(check(Severity.WARN, 'nextActionsEmpty', '"Next 3 actions" has no task IDs or entries', false));
162
+ }
163
+ }
164
+ }
165
+ return results;
166
+ }
167
+ // ── Next vs TODO cross-reference ───────────────────────────────────────
168
+ /**
169
+ * Check that task IDs in "Next 3 actions" exist in TODO.md.
170
+ */
171
+ export function runNextVsTodoChecks(statusContent, todoContent) {
172
+ const results = [];
173
+ // Extract next actions section
174
+ const nextActionsIndex = statusContent.search(NEXT_ACTIONS_RE);
175
+ if (nextActionsIndex < 0)
176
+ return results;
177
+ const sectionAfter = statusContent.slice(nextActionsIndex);
178
+ const nextSectionIndex = sectionAfter.indexOf('\n## ', 1);
179
+ const nextActionsSection = nextSectionIndex > 0
180
+ ? sectionAfter.slice(0, nextSectionIndex)
181
+ : sectionAfter;
182
+ // Get task IDs from next actions
183
+ const nextTaskIds = nextActionsSection.match(TASK_ID_RE) ?? [];
184
+ if (nextTaskIds.length === 0)
185
+ return results;
186
+ // Get task IDs from TODO
187
+ const todoTaskIds = new Set(todoContent.match(TASK_ID_RE) ?? []);
188
+ // Find task IDs in next that are not in TODO
189
+ const missing = nextTaskIds.filter((id) => !todoTaskIds.has(id));
190
+ // Only warn if 2+ are missing (allows 1 stale reference)
191
+ if (missing.length >= 2) {
192
+ results.push(check(Severity.WARN, 'nextNotInTodo', `${missing.length} task IDs in "Next 3 actions" not found in TODO.md: ${missing.join(', ')}`, false));
193
+ }
194
+ return results;
195
+ }
196
+ // ── Commands / Links checks ────────────────────────────────────────────
197
+ /**
198
+ * Check COMMANDS.md and LINKS.md for relevant topic types.
199
+ */
200
+ export function runCommandsLinksChecks(entry, capsuleFiles) {
201
+ const results = [];
202
+ // COMMANDS.md empty for coding topics
203
+ if (entry.type === 'coding') {
204
+ const commandsContent = capsuleFiles.get('COMMANDS.md');
205
+ if (commandsContent !== undefined && isEffectivelyEmpty(commandsContent)) {
206
+ if (!isIgnored(entry, 'commandsEmpty')) {
207
+ results.push(check(Severity.INFO, 'commandsEmpty', 'COMMANDS.md is empty for a coding topic', false));
208
+ }
209
+ }
210
+ }
211
+ // LINKS.md empty for coding or research
212
+ if (entry.type === 'coding' || entry.type === 'research') {
213
+ const linksContent = capsuleFiles.get('LINKS.md');
214
+ if (linksContent !== undefined && isEffectivelyEmpty(linksContent)) {
215
+ if (!isIgnored(entry, 'linksEmpty')) {
216
+ results.push(check(Severity.INFO, 'linksEmpty', 'LINKS.md is empty for a coding/research topic', false));
217
+ }
218
+ }
219
+ }
220
+ return results;
221
+ }
222
+ /**
223
+ * Check if a markdown file is effectively empty (only has a heading and template text).
224
+ */
225
+ function isEffectivelyEmpty(content) {
226
+ // Remove markdown heading lines and template placeholders
227
+ const stripped = content
228
+ .replace(/^#.*$/gm, '') // headings
229
+ .replace(/^_.*_$/gm, '') // italic template text
230
+ .replace(/\s+/g, '') // whitespace
231
+ .trim();
232
+ return stripped.length === 0;
233
+ }
234
+ // ── Cron checks ────────────────────────────────────────────────────────
235
+ const JOB_ID_RE = /[a-zA-Z0-9_-]{8,}/;
236
+ /**
237
+ * Check CRON.md for job ID presence and optionally validate against cron/jobs.json.
238
+ */
239
+ export function runCronChecks(cronContent, cronJobsPath) {
240
+ const results = [];
241
+ // Skip if cron content is effectively empty
242
+ if (isEffectivelyEmpty(cronContent))
243
+ return results;
244
+ // Check for job IDs in CRON.md
245
+ const lines = cronContent.split('\n').filter((l) => !l.startsWith('#') && l.trim().length > 0);
246
+ const hasJobIds = lines.some((line) => JOB_ID_RE.test(line));
247
+ if (!hasJobIds) {
248
+ results.push(check(Severity.WARN, 'cronNoJobIds', 'CRON.md lists jobs but has no recognizable job IDs', false));
249
+ return results;
250
+ }
251
+ // Optionally validate job IDs against cron/jobs.json
252
+ if (cronJobsPath && fs.existsSync(cronJobsPath)) {
253
+ try {
254
+ const jobsRaw = fs.readFileSync(cronJobsPath, 'utf-8');
255
+ const jobs = JSON.parse(jobsRaw);
256
+ const knownJobIds = new Set(Object.keys(jobs));
257
+ // Extract job IDs from CRON.md lines
258
+ for (const line of lines) {
259
+ const match = line.match(JOB_ID_RE);
260
+ if (match && !knownJobIds.has(match[0])) {
261
+ results.push(check(Severity.WARN, 'cronJobNotFound', `Job ID "${match[0]}" from CRON.md not found in cron/jobs.json`, false));
262
+ }
263
+ }
264
+ }
265
+ catch {
266
+ // Can't read jobs file — skip validation
267
+ }
268
+ }
269
+ return results;
270
+ }
271
+ // ── Config enforcement checks ──────────────────────────────────────────
272
+ /**
273
+ * Check per-topic systemPrompt and skills against canonical templates.
274
+ */
275
+ export function runConfigChecks(entry, includeContent, registry) {
276
+ const results = [];
277
+ // Parse the include to check this topic's config
278
+ let includeObj;
279
+ try {
280
+ // Strip comment lines before parsing
281
+ const stripped = includeContent
282
+ .split('\n')
283
+ .filter((l) => !l.startsWith('//'))
284
+ .join('\n');
285
+ includeObj = JSON.parse(stripped);
286
+ }
287
+ catch {
288
+ // Try json5 parsing - but we don't import json5 here to keep this pure
289
+ // If we can't parse, skip
290
+ return results;
291
+ }
292
+ const groupConfig = includeObj[entry.groupId];
293
+ if (!groupConfig) {
294
+ if (!isIgnored(entry, 'configGroupMissing')) {
295
+ results.push(check(Severity.WARN, 'configGroupMissing', `Group ${entry.groupId} missing from generated include`, false));
296
+ }
297
+ return results;
298
+ }
299
+ const topics = groupConfig['topics'];
300
+ const topicConfig = topics?.[entry.threadId];
301
+ if (!topicConfig) {
302
+ if (!isIgnored(entry, 'configTopicMissing')) {
303
+ results.push(check(Severity.WARN, 'configTopicMissing', `Topic config missing for thread ${entry.threadId}`, false));
304
+ }
305
+ return results;
306
+ }
307
+ // Check systemPrompt exists
308
+ if (!topicConfig['systemPrompt']) {
309
+ if (!isIgnored(entry, 'configNoSystemPrompt')) {
310
+ results.push(check(Severity.WARN, 'configNoSystemPrompt', 'Per-topic systemPrompt is missing in generated include', false));
311
+ }
312
+ }
313
+ // Check skills exist
314
+ if (!topicConfig['skills'] || !Array.isArray(topicConfig['skills'])) {
315
+ if (!isIgnored(entry, 'configNoSkills')) {
316
+ results.push(check(Severity.WARN, 'configNoSkills', 'Per-topic skills list is missing in generated include', false));
317
+ }
318
+ }
319
+ return results;
320
+ }
321
+ // ── Include drift detection ────────────────────────────────────────────
322
+ /**
323
+ * Check if the generated include file's registry-hash matches the current registry.
324
+ */
325
+ export function runIncludeDriftCheck(includeFileContent, registry) {
326
+ const results = [];
327
+ const fileHash = extractRegistryHash(includeFileContent);
328
+ if (!fileHash) {
329
+ results.push(check(Severity.WARN, 'includeDrift', 'Generated include file has no registry-hash comment. Run /topic sync.', false));
330
+ return results;
331
+ }
332
+ const currentHash = computeRegistryHash(registry.topics);
333
+ if (fileHash !== currentHash) {
334
+ results.push(check(Severity.WARN, 'includeDrift', 'Generated include is out of sync with registry. Run /topic sync.', false));
335
+ }
336
+ return results;
337
+ }
338
+ // ── Spam control check ─────────────────────────────────────────────────
339
+ /**
340
+ * Check for spam control: if consecutiveSilentDoctors >= 3, suggest auto-snooze.
341
+ */
342
+ export function runSpamControlCheck(entry) {
343
+ const results = [];
344
+ if (entry.consecutiveSilentDoctors >= SPAM_THRESHOLD) {
345
+ results.push(check(Severity.INFO, 'spamControl', `${entry.consecutiveSilentDoctors} consecutive doctor reports with no user interaction. Auto-snoozing for 30 days.`, true));
346
+ }
347
+ return results;
348
+ }
349
+ // ── Convenience: run all checks for a single topic ─────────────────────
350
+ /**
351
+ * Run all applicable doctor checks for a single topic entry.
352
+ * Returns combined results from all check categories.
353
+ *
354
+ * This is a convenience function for command handlers.
355
+ * It reads capsule files and runs all checks.
356
+ */
357
+ export function runAllChecksForTopic(entry, projectsBase, includeContent, registry, cronJobsPath) {
358
+ const results = [];
359
+ const capsuleDir = path.join(projectsBase, entry.slug);
360
+ // Registry checks
361
+ results.push(...runRegistryChecks(entry, projectsBase));
362
+ // If path doesn't exist, skip capsule-dependent checks
363
+ if (!fs.existsSync(capsuleDir))
364
+ return results;
365
+ // Capsule structure checks
366
+ results.push(...runCapsuleChecks(entry, projectsBase));
367
+ // Read capsule files for content-based checks
368
+ const capsuleFiles = readCapsuleFiles(capsuleDir);
369
+ // STATUS quality checks
370
+ const statusContent = capsuleFiles.get('STATUS.md');
371
+ if (statusContent) {
372
+ results.push(...runStatusQualityChecks(statusContent, entry));
373
+ // Next vs TODO checks
374
+ const todoContent = capsuleFiles.get('TODO.md');
375
+ if (todoContent && !isIgnored(entry, 'nextNotInTodo')) {
376
+ results.push(...runNextVsTodoChecks(statusContent, todoContent));
377
+ }
378
+ }
379
+ // Commands / Links checks
380
+ results.push(...runCommandsLinksChecks(entry, capsuleFiles));
381
+ // Cron checks
382
+ const cronContent = capsuleFiles.get('CRON.md');
383
+ if (cronContent) {
384
+ results.push(...runCronChecks(cronContent, cronJobsPath));
385
+ }
386
+ // Config checks (if include content provided)
387
+ if (includeContent && registry) {
388
+ results.push(...runConfigChecks(entry, includeContent, registry));
389
+ }
390
+ // Include drift (if include content provided)
391
+ if (includeContent && registry) {
392
+ results.push(...runIncludeDriftCheck(includeContent, registry));
393
+ }
394
+ // Spam control
395
+ results.push(...runSpamControlCheck(entry));
396
+ return results;
397
+ }
398
+ // ── File reading helper ────────────────────────────────────────────────
399
+ function readCapsuleFiles(capsuleDir) {
400
+ const files = new Map();
401
+ const filenames = [
402
+ 'STATUS.md', 'TODO.md', 'COMMANDS.md', 'LINKS.md',
403
+ 'CRON.md', 'NOTES.md', 'README.md',
404
+ 'ARCHITECTURE.md', 'DEPLOY.md',
405
+ 'SOURCES.md', 'FINDINGS.md',
406
+ 'CAMPAIGNS.md', 'METRICS.md',
407
+ ];
408
+ for (const name of filenames) {
409
+ const filePath = path.join(capsuleDir, name);
410
+ try {
411
+ if (fs.existsSync(filePath)) {
412
+ files.set(name, fs.readFileSync(filePath, 'utf-8'));
413
+ }
414
+ }
415
+ catch {
416
+ // Skip unreadable files
417
+ }
418
+ }
419
+ return files;
420
+ }
421
+ //# sourceMappingURL=doctor-checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-checks.js","sourceRoot":"","sources":["../../src/lib/doctor-checks.ts"],"names":[],"mappings":"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"}