instar 0.9.11 → 0.9.13

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 (53) hide show
  1. package/dist/commands/init.d.ts.map +1 -1
  2. package/dist/commands/init.js +78 -0
  3. package/dist/commands/init.js.map +1 -1
  4. package/dist/commands/server.d.ts.map +1 -1
  5. package/dist/commands/server.js +86 -7
  6. package/dist/commands/server.js.map +1 -1
  7. package/dist/core/CanonicalState.d.ts +132 -0
  8. package/dist/core/CanonicalState.d.ts.map +1 -0
  9. package/dist/core/CanonicalState.js +297 -0
  10. package/dist/core/CanonicalState.js.map +1 -0
  11. package/dist/core/CoherenceGate.d.ts +122 -0
  12. package/dist/core/CoherenceGate.d.ts.map +1 -0
  13. package/dist/core/CoherenceGate.js +347 -0
  14. package/dist/core/CoherenceGate.js.map +1 -0
  15. package/dist/core/ContextHierarchy.d.ts +100 -0
  16. package/dist/core/ContextHierarchy.d.ts.map +1 -0
  17. package/dist/core/ContextHierarchy.js +454 -0
  18. package/dist/core/ContextHierarchy.js.map +1 -0
  19. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  20. package/dist/core/PostUpdateMigrator.js +140 -0
  21. package/dist/core/PostUpdateMigrator.js.map +1 -1
  22. package/dist/core/ProjectMapper.d.ts +97 -0
  23. package/dist/core/ProjectMapper.d.ts.map +1 -0
  24. package/dist/core/ProjectMapper.js +364 -0
  25. package/dist/core/ProjectMapper.js.map +1 -0
  26. package/dist/index.d.ts +8 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +4 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/messaging/TelegramAdapter.d.ts +5 -0
  31. package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
  32. package/dist/messaging/TelegramAdapter.js +7 -0
  33. package/dist/messaging/TelegramAdapter.js.map +1 -1
  34. package/dist/monitoring/StallTriageNurse.d.ts.map +1 -1
  35. package/dist/monitoring/StallTriageNurse.js +77 -13
  36. package/dist/monitoring/StallTriageNurse.js.map +1 -1
  37. package/dist/scaffold/templates.d.ts.map +1 -1
  38. package/dist/scaffold/templates.js +10 -0
  39. package/dist/scaffold/templates.js.map +1 -1
  40. package/dist/scheduler/JobLoader.d.ts.map +1 -1
  41. package/dist/scheduler/JobLoader.js +1 -0
  42. package/dist/scheduler/JobLoader.js.map +1 -1
  43. package/dist/server/AgentServer.d.ts +4 -0
  44. package/dist/server/AgentServer.d.ts.map +1 -1
  45. package/dist/server/AgentServer.js +4 -0
  46. package/dist/server/AgentServer.js.map +1 -1
  47. package/dist/server/routes.d.ts +8 -0
  48. package/dist/server/routes.d.ts.map +1 -1
  49. package/dist/server/routes.js +228 -0
  50. package/dist/server/routes.js.map +1 -1
  51. package/package.json +1 -1
  52. package/upgrades/0.9.12.md +42 -0
  53. package/upgrades/0.9.13.md +55 -0
@@ -0,0 +1,454 @@
1
+ /**
2
+ * Context Hierarchy — Tiered context loading for efficient agent awareness.
3
+ *
4
+ * Inspired by Dawn's context dispatch system (PROP-088): right context at
5
+ * the right moment > all context all the time.
6
+ *
7
+ * Three tiers:
8
+ * Tier 0: Always loaded (identity, project scope, safety rules)
9
+ * Tier 1: Session boundaries (continuity, compaction recovery, topic context)
10
+ * Tier 2: On-demand (task-specific depth when context matches)
11
+ *
12
+ * The hierarchy creates a `.instar/context/` directory with structured
13
+ * segment files that hooks and sessions can load selectively.
14
+ *
15
+ * Born from the Luna incident (2026-02-25): An agent had no systematic
16
+ * way to load task-relevant context efficiently. Without a hierarchy,
17
+ * agents either load everything (context bloat) or nothing (incoherence).
18
+ */
19
+ import fs from 'node:fs';
20
+ import path from 'node:path';
21
+ /** The canonical list of context segments every agent should have. */
22
+ const DEFAULT_SEGMENTS = [
23
+ {
24
+ id: 'identity',
25
+ name: 'Identity & Scope',
26
+ tier: 0,
27
+ triggers: ['always'],
28
+ file: 'identity.md',
29
+ description: 'Agent name, role, principles, project scope. Always loaded.',
30
+ },
31
+ {
32
+ id: 'safety',
33
+ name: 'Safety Rules',
34
+ tier: 0,
35
+ triggers: ['always'],
36
+ file: 'safety.md',
37
+ description: 'Constraints, blocked commands, destructive action rules.',
38
+ },
39
+ {
40
+ id: 'project',
41
+ name: 'Project Map',
42
+ tier: 0,
43
+ triggers: ['always'],
44
+ file: 'project.md',
45
+ description: 'Auto-generated project structure, key files, deployment targets.',
46
+ },
47
+ {
48
+ id: 'session',
49
+ name: 'Session Continuity',
50
+ tier: 1,
51
+ triggers: ['session-start', 'compaction', 'resume'],
52
+ file: 'session.md',
53
+ description: 'Session lifecycle, ownership, recovery procedures.',
54
+ },
55
+ {
56
+ id: 'relationships',
57
+ name: 'Relationship Context',
58
+ tier: 1,
59
+ triggers: ['session-start', 'messaging'],
60
+ file: 'relationships.md',
61
+ description: 'Known people, interaction patterns, relationship maintenance.',
62
+ },
63
+ {
64
+ id: 'development',
65
+ name: 'Development Patterns',
66
+ tier: 2,
67
+ triggers: ['writing-code', 'modifying-files', 'debugging'],
68
+ file: 'development.md',
69
+ description: 'Code conventions, testing patterns, architectural decisions for this project.',
70
+ },
71
+ {
72
+ id: 'deployment',
73
+ name: 'Deployment Guide',
74
+ tier: 2,
75
+ triggers: ['deploying', 'building', 'pushing-to-git'],
76
+ file: 'deployment.md',
77
+ description: 'Deployment targets, CI/CD setup, environment variables, rollback procedures.',
78
+ },
79
+ {
80
+ id: 'communication',
81
+ name: 'Communication Patterns',
82
+ tier: 2,
83
+ triggers: ['messaging-user', 'sending-email', 'writing-report'],
84
+ file: 'communication.md',
85
+ description: 'User preferences, tone guidelines, when to proactively reach out.',
86
+ },
87
+ ];
88
+ export class ContextHierarchy {
89
+ config;
90
+ contextDir;
91
+ constructor(config) {
92
+ this.config = config;
93
+ this.contextDir = path.join(config.stateDir, 'context');
94
+ }
95
+ /**
96
+ * Initialize the context directory with default segment files.
97
+ * Only creates files that don't already exist (additive only).
98
+ */
99
+ initialize() {
100
+ fs.mkdirSync(this.contextDir, { recursive: true });
101
+ const created = [];
102
+ const skipped = [];
103
+ for (const segment of DEFAULT_SEGMENTS) {
104
+ const filePath = path.join(this.contextDir, segment.file);
105
+ if (fs.existsSync(filePath)) {
106
+ skipped.push(segment.file);
107
+ continue;
108
+ }
109
+ const content = this.generateSegmentTemplate(segment);
110
+ fs.writeFileSync(filePath, content);
111
+ created.push(segment.file);
112
+ }
113
+ // Write the dispatch table
114
+ this.writeDispatchTable();
115
+ return { created, skipped };
116
+ }
117
+ /**
118
+ * Get the dispatch table — a mapping of triggers to context files.
119
+ * This is what agents read to know "when X happens, load Y."
120
+ */
121
+ getDispatchTable() {
122
+ return DEFAULT_SEGMENTS
123
+ .filter(s => s.tier === 2)
124
+ .flatMap(s => s.triggers.map(trigger => ({
125
+ trigger,
126
+ file: `.instar/context/${s.file}`,
127
+ reason: s.description,
128
+ })));
129
+ }
130
+ /**
131
+ * Write the dispatch table to a human-readable file.
132
+ */
133
+ writeDispatchTable() {
134
+ const table = this.getDispatchTable();
135
+ const lines = [
136
+ '# Context Dispatch Table',
137
+ '',
138
+ '> When certain work arises, deeper context helps you be fully present.',
139
+ '> This table guides which context to surface.',
140
+ '',
141
+ '| When you\'re about to... | Read this context | Why |',
142
+ '|------------------------|-------------------|-----|',
143
+ ];
144
+ for (const entry of table) {
145
+ lines.push(`| ${entry.trigger} | \`${entry.file}\` | ${entry.reason} |`);
146
+ }
147
+ // Add tier 0 and 1 explanations
148
+ lines.push('');
149
+ lines.push('## Always-Loaded Context (Tier 0)');
150
+ lines.push('');
151
+ lines.push('These are injected automatically at every session start:');
152
+ for (const s of DEFAULT_SEGMENTS.filter(s => s.tier === 0)) {
153
+ lines.push(`- \`.instar/context/${s.file}\` — ${s.description}`);
154
+ }
155
+ lines.push('');
156
+ lines.push('## Session-Boundary Context (Tier 1)');
157
+ lines.push('');
158
+ lines.push('These are loaded at session start, compaction, and resume:');
159
+ for (const s of DEFAULT_SEGMENTS.filter(s => s.tier === 1)) {
160
+ lines.push(`- \`.instar/context/${s.file}\` — ${s.description}`);
161
+ }
162
+ lines.push('');
163
+ lines.push('*Auto-generated by Instar Context Hierarchy.*');
164
+ fs.writeFileSync(path.join(this.contextDir, 'DISPATCH.md'), lines.join('\n'));
165
+ }
166
+ /**
167
+ * Load all segments for a given tier.
168
+ * Returns concatenated content suitable for hook injection.
169
+ */
170
+ loadTier(tier) {
171
+ const segments = DEFAULT_SEGMENTS.filter(s => s.tier <= tier);
172
+ const parts = [];
173
+ for (const segment of segments) {
174
+ const filePath = path.join(this.contextDir, segment.file);
175
+ if (fs.existsSync(filePath)) {
176
+ try {
177
+ const content = fs.readFileSync(filePath, 'utf-8').trim();
178
+ if (content && !content.startsWith('<!--') || content.includes('\n\n')) {
179
+ parts.push(content);
180
+ }
181
+ }
182
+ catch { /* corrupt file */ }
183
+ }
184
+ }
185
+ return parts.join('\n\n');
186
+ }
187
+ /**
188
+ * Load a specific context segment by ID.
189
+ */
190
+ loadSegment(segmentId) {
191
+ const segment = DEFAULT_SEGMENTS.find(s => s.id === segmentId);
192
+ if (!segment)
193
+ return null;
194
+ const filePath = path.join(this.contextDir, segment.file);
195
+ try {
196
+ if (fs.existsSync(filePath)) {
197
+ return fs.readFileSync(filePath, 'utf-8');
198
+ }
199
+ }
200
+ catch { /* corrupt file */ }
201
+ return null;
202
+ }
203
+ /**
204
+ * List all context segments with their status.
205
+ */
206
+ listSegments() {
207
+ return DEFAULT_SEGMENTS.map(s => {
208
+ const filePath = path.join(this.contextDir, s.file);
209
+ let exists = false;
210
+ let sizeBytes = 0;
211
+ try {
212
+ if (fs.existsSync(filePath)) {
213
+ exists = true;
214
+ sizeBytes = fs.statSync(filePath).size;
215
+ }
216
+ }
217
+ catch { /* ignore */ }
218
+ return { ...s, exists, sizeBytes };
219
+ });
220
+ }
221
+ /**
222
+ * Get the context directory path.
223
+ */
224
+ getContextDir() {
225
+ return this.contextDir;
226
+ }
227
+ // ── Template Generation ─────────────────────────────────────────
228
+ generateSegmentTemplate(segment) {
229
+ switch (segment.id) {
230
+ case 'identity':
231
+ return this.identityTemplate();
232
+ case 'safety':
233
+ return this.safetyTemplate();
234
+ case 'project':
235
+ return this.projectTemplate();
236
+ case 'session':
237
+ return this.sessionTemplate();
238
+ case 'relationships':
239
+ return this.relationshipsTemplate();
240
+ case 'development':
241
+ return this.developmentTemplate();
242
+ case 'deployment':
243
+ return this.deploymentTemplate();
244
+ case 'communication':
245
+ return this.communicationTemplate();
246
+ default:
247
+ return `# ${segment.name}\n\n<!-- Add context for: ${segment.description} -->\n`;
248
+ }
249
+ }
250
+ identityTemplate() {
251
+ return `# Identity & Scope
252
+
253
+ <!-- This file is auto-generated by Instar. Customize it for your agent. -->
254
+
255
+ ## Who I Am
256
+
257
+ Read .instar/AGENT.md for full identity. This is a quick-reference summary.
258
+
259
+ ## Project Scope
260
+
261
+ - **Project**: ${this.config.projectName}
262
+ - **Directory**: ${this.config.projectDir}
263
+ - Read .instar/project-map.md for full project structure.
264
+
265
+ ## Core Truths
266
+
267
+ 1. I am a builder. When I see work, I do it.
268
+ 2. I know my tools. I check /capabilities before saying "I can't."
269
+ 3. I verify before claiming. "Did I actually check this, or am I assuming?"
270
+ `;
271
+ }
272
+ safetyTemplate() {
273
+ return `# Safety Rules
274
+
275
+ ## Hard Blocks
276
+
277
+ These commands are ALWAYS blocked regardless of context:
278
+ - \`rm -rf /\` or \`rm -rf ~\` — catastrophic filesystem destruction
279
+ - \`> /dev/sda\` — disk overwrite
280
+ - Fork bombs, disk formatting commands
281
+
282
+ ## Soft Blocks (Safety Level Dependent)
283
+
284
+ At Safety Level 1 (default): ask user before running.
285
+ At Safety Level 2 (autonomous): self-verify before running.
286
+
287
+ - \`git push --force\` — overwrites remote history
288
+ - \`git reset --hard\` — discards uncommitted work
289
+ - \`DROP TABLE/DATABASE\` — irreversible data loss
290
+ - \`rm -rf .\` — project directory destruction
291
+
292
+ ## Coherence Gate
293
+
294
+ Before deploying, pushing, or modifying files outside this project:
295
+ 1. Check coherence: POST /coherence/check
296
+ 2. If BLOCK — stop. You're likely in the wrong project.
297
+ 3. If WARN — pause and verify.
298
+
299
+ ## Topic-Project Bindings
300
+
301
+ Each Telegram topic may be bound to a specific project. Verify before acting.
302
+ `;
303
+ }
304
+ projectTemplate() {
305
+ return `# Project Context
306
+
307
+ <!-- Auto-populated from project-map.json. Refresh: POST /project-map/refresh -->
308
+
309
+ Read .instar/project-map.md for the full project structure map.
310
+ Read .instar/project-map.json for programmatic access.
311
+
312
+ Quick reference: GET /project-map?format=compact
313
+ `;
314
+ }
315
+ sessionTemplate() {
316
+ return `# Session Continuity
317
+
318
+ ## On Session Start
319
+
320
+ 1. Note the current topic (if Telegram session)
321
+ 2. Read thread history for conversational context
322
+ 3. Check for pending upgrade guides
323
+ 4. Verify identity (AGENT.md exists and is readable)
324
+
325
+ ## On Compaction
326
+
327
+ Context was compressed. Recovery priority:
328
+ 1. Topic context (what am I working on?)
329
+ 2. Identity (who am I?)
330
+ 3. Memory (what have I learned?)
331
+ 4. Project context (where am I?)
332
+ 5. Capabilities (what can I do?)
333
+
334
+ ## On Resume
335
+
336
+ Re-read recent activity. Check if anything changed while you were paused.
337
+
338
+ ## Session Handoff
339
+
340
+ When ending a session that another might continue:
341
+ - Update MEMORY.md with anything learned
342
+ - Note any incomplete work
343
+ - Save conversation context via topic memory
344
+ `;
345
+ }
346
+ relationshipsTemplate() {
347
+ return `# Relationship Context
348
+
349
+ ## Before Interacting with Anyone
350
+
351
+ 1. Check if they're tracked: GET /relationships
352
+ 2. If tracked, read their file for context before responding
353
+ 3. Note the interaction type and update the relationship record after
354
+
355
+ ## Key Patterns
356
+
357
+ - **First contact**: Be welcoming but verify identity
358
+ - **Returning user**: Reference shared history naturally
359
+ - **Stale contact**: Consider reaching out if significance >= 3
360
+
361
+ ## Relationship Files
362
+
363
+ All relationship records are in .instar/relationships/*.json
364
+ Each contains: name, interactions, significance, themes, notes
365
+ `;
366
+ }
367
+ developmentTemplate() {
368
+ return `# Development Patterns
369
+
370
+ <!-- Customize this for your project's specific conventions. -->
371
+
372
+ ## Before Writing Code
373
+
374
+ 1. Read existing code before modifying it
375
+ 2. Check the project map for file locations
376
+ 3. Follow existing patterns in the codebase
377
+
378
+ ## Testing
379
+
380
+ - Run tests before committing
381
+ - Match the project's existing test patterns
382
+ - Write tests for new features
383
+
384
+ ## Git Workflow
385
+
386
+ - Commit with clear messages
387
+ - Check coherence gate before pushing
388
+ - Verify CI passes after push
389
+
390
+ ## Project-Specific Conventions
391
+
392
+ <!-- Add your project's coding standards, linting rules,
393
+ naming conventions, architecture patterns, etc. -->
394
+ `;
395
+ }
396
+ deploymentTemplate() {
397
+ return `# Deployment Guide
398
+
399
+ <!-- Customize this for your project's deployment setup. -->
400
+
401
+ ## Pre-Deployment Checklist
402
+
403
+ 1. Run coherence check: POST /coherence/check with action "deploy"
404
+ 2. Verify you're in the correct project directory
405
+ 3. Verify the deployment target matches the current topic/project
406
+ 4. Run tests
407
+ 5. Check CI status: GET /ci
408
+
409
+ ## Deployment Targets
410
+
411
+ <!-- List your deployment targets here, e.g.:
412
+ - Production: https://myapp.vercel.app (Vercel)
413
+ - Staging: https://staging.myapp.com
414
+ -->
415
+
416
+ Check project map for auto-detected targets: GET /project-map
417
+
418
+ ## Rollback Procedure
419
+
420
+ <!-- Document how to rollback if a deployment goes wrong -->
421
+
422
+ ## Environment Variables
423
+
424
+ <!-- List required environment variables and where they're configured -->
425
+ `;
426
+ }
427
+ communicationTemplate() {
428
+ return `# Communication Patterns
429
+
430
+ ## Telegram
431
+
432
+ - Always acknowledge messages immediately
433
+ - Relay responses via telegram-reply script
434
+ - Strip [telegram:N] prefix before interpreting
435
+ - Read thread history for context on new sessions
436
+
437
+ ## Reporting
438
+
439
+ - Use Private Viewer for sensitive content (POST /view)
440
+ - Use Telegraph for public content (POST /publish)
441
+ - Always include artifact links, not just summaries
442
+
443
+ ## User Preferences
444
+
445
+ <!-- Document your user's communication preferences:
446
+ - Preferred response length
447
+ - When to proactively reach out
448
+ - When to stay silent
449
+ - Topics they care about vs. internal details
450
+ -->
451
+ `;
452
+ }
453
+ }
454
+ //# sourceMappingURL=ContextHierarchy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContextHierarchy.js","sourceRoot":"","sources":["../../src/core/ContextHierarchy.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kCAAkC;IAClC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAiB;gBAEnB,MAAM,EAAE,cAAc;IAIlC;;;OAGG;IACH,OAAO,IAAI,eAAe;IAgB1B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAkCpB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAuKvB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAiCtB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAyGvB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAuCrB;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAAG,MAAM;IAOrE,OAAO,CAAC,mBAAmB;IAqL3B,OAAO,CAAC,wBAAwB;IA2ChC,OAAO,CAAC,2BAA2B;IAenC,OAAO,CAAC,qBAAqB;IAmJ7B,OAAO,CAAC,sBAAsB;IAyD9B,OAAO,CAAC,iBAAiB;CAuB1B"}
1
+ {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kCAAkC;IAClC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAiB;gBAEnB,MAAM,EAAE,cAAc;IAIlC;;;OAGG;IACH,OAAO,IAAI,eAAe;IAgB1B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAkCpB;;;OAGG;IACH,OAAO,CAAC,eAAe;IA4NvB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAiCtB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAyGvB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAuCrB;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAAG,MAAM;IAOrE,OAAO,CAAC,mBAAmB;IA8N3B,OAAO,CAAC,wBAAwB;IAkEhC,OAAO,CAAC,2BAA2B;IAenC,OAAO,CAAC,qBAAqB;IAyK7B,OAAO,CAAC,sBAAsB;IAyD9B,OAAO,CAAC,iBAAiB;CAuB1B"}
@@ -237,6 +237,60 @@ Strip the \`[telegram:N]\` prefix before interpreting the message. Respond natur
237
237
  else {
238
238
  result.skipped.push('CLAUDE.md: Dashboard section already present');
239
239
  }
240
+ // Coherence Gate section — pre-action verification for high-risk actions
241
+ if (!content.includes('Coherence Gate') && !content.includes('/coherence/check')) {
242
+ const section = `
243
+ ### Coherence Gate (Pre-Action Verification)
244
+
245
+ **BEFORE any high-risk action** (deploying, pushing to git, modifying files outside this project, calling external APIs):
246
+
247
+ 1. **Check coherence**: \`curl -X POST http://localhost:${port}/coherence/check -H 'Content-Type: application/json' -d '{"action":"deploy","context":{"topicId":TOPIC_ID}}'\`
248
+ 2. **If result says "block"** — STOP. You may be working on the wrong project for this topic.
249
+ 3. **If result says "warn"** — Pause and verify before proceeding.
250
+ 4. **Generate a reflection prompt**: \`POST http://localhost:${port}/coherence/reflect\` — produces a self-verification checklist.
251
+
252
+ **Topic-Project Bindings**: Each Telegram topic can be bound to a specific project. When switching topics, verify the binding matches your current working directory.
253
+ - View bindings: \`GET http://localhost:${port}/topic-bindings\`
254
+ - Create binding: \`POST http://localhost:${port}/topic-bindings\` with \`{"topicId": N, "binding": {"projectName": "...", "projectDir": "..."}}\`
255
+
256
+ **Project Map**: Your spatial awareness of the working environment.
257
+ - View: \`GET http://localhost:${port}/project-map?format=compact\`
258
+ - Refresh: \`POST http://localhost:${port}/project-map/refresh\`
259
+ `;
260
+ // Insert before Scripts or append
261
+ const insertBefore = content.indexOf('**Scripts**');
262
+ if (insertBefore >= 0) {
263
+ content = content.slice(0, insertBefore) + section + '\n' + content.slice(insertBefore);
264
+ }
265
+ else {
266
+ content += '\n' + section;
267
+ }
268
+ patched = true;
269
+ result.upgraded.push('CLAUDE.md: added Coherence Gate section');
270
+ }
271
+ else {
272
+ result.skipped.push('CLAUDE.md: Coherence Gate section already present');
273
+ }
274
+ // Session Continuity — ensure agents know how to handle respawn context
275
+ if (this.config.hasTelegram && !content.includes('Session Continuity') && !content.includes('CONTINUATION')) {
276
+ const section = `
277
+ ### Session Continuity (CRITICAL)
278
+
279
+ When your first message starts with \`CONTINUATION\`, you are **resuming an existing conversation**. The inline context contains a summary and recent messages from the prior session. You MUST:
280
+
281
+ 1. **Read the context first** — it tells you what the conversation is about
282
+ 2. **Pick up where you left off** — do NOT introduce yourself or ask "how can I help?"
283
+ 3. **Reference the prior context** — show the user you know what they were discussing
284
+
285
+ The user has been talking to you (possibly for days). A generic greeting like "Hey! What can I help you with?" after dozens of messages of conversation history is a critical failure — it signals you lost all context and the user has to repeat everything. The context is right there in your input. Use it.
286
+ `;
287
+ content += '\n' + section;
288
+ patched = true;
289
+ result.upgraded.push('CLAUDE.md: added Session Continuity section');
290
+ }
291
+ else if (this.config.hasTelegram && content.includes('Session Continuity')) {
292
+ result.skipped.push('CLAUDE.md: Session Continuity section already present');
293
+ }
240
294
  if (patched) {
241
295
  try {
242
296
  fs.writeFileSync(claudeMdPath, content);
@@ -508,12 +562,53 @@ if [ -f "$INSTAR_DIR/AGENT.md" ]; then
508
562
  sed -n '/^## Personality/,/^## [^P]/p' "$INSTAR_DIR/AGENT.md" 2>/dev/null | head -10
509
563
  fi
510
564
 
565
+ # PROJECT MAP — spatial awareness of the working environment
566
+ if [ -f "$INSTAR_DIR/project-map.json" ]; then
567
+ echo ""
568
+ echo "--- PROJECT CONTEXT ---"
569
+ python3 -c "
570
+ import json, sys
571
+ try:
572
+ m = json.load(open('$INSTAR_DIR/project-map.json'))
573
+ print(f'Project: {m[\"projectName\"]} ({m[\"projectType\"]})')
574
+ print(f'Path: {m[\"projectDir\"]}')
575
+ r = m.get('gitRemote')
576
+ b = m.get('gitBranch')
577
+ if r: print(f'Git: {r}' + (f' [{b}]' if b else ''))
578
+ t = m.get('deploymentTargets', [])
579
+ if t: print(f'Deploy targets: {(\", \").join(t)}')
580
+ d = m.get('directories', [])
581
+ print(f'Files: {m[\"totalFiles\"]} across {len(d)} directories')
582
+ for dd in d[:6]:
583
+ print(f' {dd[\"name\"]}/ ({dd[\"fileCount\"]}) — {dd[\"description\"]}')
584
+ if len(d) > 6: print(f' ... and {len(d) - 6} more')
585
+ except Exception as e:
586
+ print(f'(project map load failed: {e})', file=sys.stderr)
587
+ " 2>/dev/null
588
+ echo "--- END PROJECT CONTEXT ---"
589
+ fi
590
+
591
+ # COHERENCE SCOPE — before ANY high-risk action, verify alignment
592
+ if [ -f "$INSTAR_DIR/config.json" ]; then
593
+ echo ""
594
+ echo "--- COHERENCE SCOPE ---"
595
+ echo "BEFORE deploying, pushing, or modifying files outside this project:"
596
+ echo " 1. Verify you are in the RIGHT project for the current topic/task"
597
+ echo " 2. Check: curl -X POST http://localhost:\${PORT:-4040}/coherence/check \\\\"
598
+ echo " -H 'Content-Type: application/json' \\\\"
599
+ echo " -d '{\"action\":\"deploy\",\"context\":{\"topicId\":N}}'"
600
+ echo " 3. If the check says BLOCK — STOP. You may be in the wrong project."
601
+ echo " 4. Read the full reflection: POST /coherence/reflect"
602
+ echo "--- END COHERENCE SCOPE ---"
603
+ fi
604
+
511
605
  # Key files
512
606
  echo ""
513
607
  echo "Key files:"
514
608
  [ -f "$INSTAR_DIR/AGENT.md" ] && echo " .instar/AGENT.md — Your identity (read for full context)"
515
609
  [ -f "$INSTAR_DIR/USER.md" ] && echo " .instar/USER.md — Your collaborator"
516
610
  [ -f "$INSTAR_DIR/MEMORY.md" ] && echo " .instar/MEMORY.md — Persistent learnings"
611
+ [ -f "$INSTAR_DIR/project-map.md" ] && echo " .instar/project-map.md — Project structure map"
517
612
 
518
613
  # Relationship count
519
614
  if [ -d "$INSTAR_DIR/relationships" ]; then
@@ -641,6 +736,29 @@ for pattern in "rm -rf /" "rm -rf ~" "> /dev/sda" "mkfs\\." "dd if=" ":(){:|:&};
641
736
  fi
642
737
  done
643
738
 
739
+ # Deployment/push commands — check coherence gate first
740
+ for pattern in "vercel deploy" "vercel --prod" "git push" "npm publish" "npx wrangler deploy" "fly deploy" "railway up"; do
741
+ if echo "$INPUT" | grep -qi "$pattern"; then
742
+ if [ -f "$INSTAR_DIR/config.json" ]; then
743
+ PORT=$(python3 -c "import json; print(json.load(open('$INSTAR_DIR/config.json')).get('port', 4040))" 2>/dev/null || echo "4040")
744
+ TOPIC_ID="\${INSTAR_TELEGRAM_TOPIC:-}"
745
+ ACTION="deploy"
746
+ echo "$INPUT" | grep -qi "git push" && ACTION="git-push"
747
+ echo "$INPUT" | grep -qi "npm publish" && ACTION="git-push"
748
+ CTX="{}"
749
+ [ -n "$TOPIC_ID" ] && CTX="{\\\"topicId\\\": $TOPIC_ID}"
750
+ CHECK=$(curl -s -X POST "http://localhost:$PORT/coherence/check" -H 'Content-Type: application/json' -d "{\\\"action\\\":\\\"$ACTION\\\",\\\"context\\\":$CTX}" 2>/dev/null)
751
+ if echo "$CHECK" | grep -q '"recommendation":"block"'; then
752
+ SUMMARY=$(echo "$CHECK" | python3 -c "import sys,json; print(json.load(sys.stdin).get('summary','Coherence check failed'))" 2>/dev/null || echo "Coherence check failed")
753
+ echo "BLOCKED: Coherence gate blocked this action." >&2
754
+ echo "$SUMMARY" >&2
755
+ echo "Run POST /coherence/reflect for a detailed self-verification checklist." >&2
756
+ exit 2
757
+ fi
758
+ fi
759
+ fi
760
+ done
761
+
644
762
  # Risky commands — behavior depends on safety level
645
763
  for pattern in "rm -rf \\." "git push --force" "git push -f" "git reset --hard" "git clean -fd" "DROP TABLE" "DROP DATABASE" "TRUNCATE" "DELETE FROM"; do
646
764
  if echo "$INPUT" | grep -qi "$pattern"; then
@@ -748,6 +866,28 @@ if [ -f "\$INSTAR_DIR/AGENT.md" ]; then
748
866
  echo "--- End Identity ---"
749
867
  fi
750
868
 
869
+ # ── 2b. PROJECT CONTEXT (where am I working?) ──
870
+ if [ -f "\$INSTAR_DIR/project-map.json" ]; then
871
+ echo ""
872
+ echo "--- PROJECT CONTEXT ---"
873
+ python3 -c "
874
+ import json, sys
875
+ try:
876
+ m = json.load(open('\$INSTAR_DIR/project-map.json'))
877
+ print(f'Project: {m[\"projectName\"]} ({m[\"projectType\"]})')
878
+ print(f'Path: {m[\"projectDir\"]}')
879
+ r = m.get('gitRemote')
880
+ b = m.get('gitBranch')
881
+ if r: print(f'Git: {r}' + (f' [{b}]' if b else ''))
882
+ t = m.get('deploymentTargets', [])
883
+ if t: print(f'Deploy targets: {(\", \").join(t)}')
884
+ print(f'Files: {m[\"totalFiles\"]} across {len(m.get(\"directories\", []))} directories')
885
+ except Exception as e:
886
+ print(f'(project map load failed: {e})', file=sys.stderr)
887
+ " 2>/dev/null
888
+ echo "--- END PROJECT CONTEXT ---"
889
+ fi
890
+
751
891
  # ── 3. MEMORY (first 50 lines — what have I learned?) ──
752
892
  if [ -f "\$INSTAR_DIR/MEMORY.md" ]; then
753
893
  LINES=\$(wc -l < "\$INSTAR_DIR/MEMORY.md" | tr -d ' ')