greprag 5.49.6 → 5.49.9

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 (51) hide show
  1. package/dist/commands/collision-reminder.d.ts +14 -0
  2. package/dist/commands/collision-reminder.js +40 -0
  3. package/dist/commands/collision-reminder.js.map +1 -0
  4. package/dist/commands/coordinate-gate.d.ts +12 -6
  5. package/dist/commands/coordinate-gate.js +24 -10
  6. package/dist/commands/coordinate-gate.js.map +1 -1
  7. package/dist/commands/corpus/client.d.ts +5 -1
  8. package/dist/commands/corpus/client.js +10 -3
  9. package/dist/commands/corpus/client.js.map +1 -1
  10. package/dist/commands/corpus/index.js +21 -1
  11. package/dist/commands/corpus/index.js.map +1 -1
  12. package/dist/commands/corpus/manage.js +31 -5
  13. package/dist/commands/corpus/manage.js.map +1 -1
  14. package/dist/commands/corpus/search.js +13 -6
  15. package/dist/commands/corpus/search.js.map +1 -1
  16. package/dist/commands/corpus/status.js +2 -1
  17. package/dist/commands/corpus/status.js.map +1 -1
  18. package/dist/commands/corpus/tags.d.ts +17 -0
  19. package/dist/commands/corpus/tags.js +91 -0
  20. package/dist/commands/corpus/tags.js.map +1 -0
  21. package/dist/commands/corpus-reminder.d.ts +15 -0
  22. package/dist/commands/corpus-reminder.js +34 -0
  23. package/dist/commands/corpus-reminder.js.map +1 -0
  24. package/dist/commands/friction-reminder.d.ts +22 -44
  25. package/dist/commands/friction-reminder.js +45 -63
  26. package/dist/commands/friction-reminder.js.map +1 -1
  27. package/dist/commands/init.js +7 -14
  28. package/dist/commands/init.js.map +1 -1
  29. package/dist/commands/load-primer-reminder.d.ts +28 -0
  30. package/dist/commands/load-primer-reminder.js +51 -0
  31. package/dist/commands/load-primer-reminder.js.map +1 -0
  32. package/dist/commands/load.d.ts +15 -0
  33. package/dist/commands/load.js +112 -0
  34. package/dist/commands/load.js.map +1 -0
  35. package/dist/commands/memory-reflex.d.ts +17 -112
  36. package/dist/commands/memory-reflex.js +24 -233
  37. package/dist/commands/memory-reflex.js.map +1 -1
  38. package/dist/commands/reminder-registry.d.ts +12 -1
  39. package/dist/commands/reminder-registry.js +48 -4
  40. package/dist/commands/reminder-registry.js.map +1 -1
  41. package/dist/commands/reminder-types.d.ts +33 -0
  42. package/dist/commands/version-reminder.d.ts +15 -0
  43. package/dist/commands/version-reminder.js +34 -0
  44. package/dist/commands/version-reminder.js.map +1 -0
  45. package/dist/hook.js +134 -274
  46. package/dist/hook.js.map +1 -1
  47. package/dist/index.js +6 -0
  48. package/dist/index.js.map +1 -1
  49. package/package.json +1 -1
  50. package/skill/templates/chip-leader.md +188 -0
  51. package/skill/templates/chip-spawn.md +4 -4
@@ -1,243 +1,34 @@
1
1
  "use strict";
2
- /** memory-reflexgreprag episodic memory as a context-fill reflex (the first
3
- * "greprag service as a reminder-interrupt module" beyond the harness's own arm/mechanic).
4
- * docs/reminder-interrupt.md §Registry spec + the announce-featureset discussion (2026-06-20).
2
+ /** memory-primerthe SessionStart announce that teaches greprag's episodic memory
3
+ * as a capability the agent operates on its OWN judgment (`greprag memory search` /
4
+ * `recap`). A PRIMER (full doctrine inline), nothing else.
5
5
  *
6
- * THE IDEA: when the agent is about to answer without context it could have, surface the
7
- * relevant project memory inline seamlessly, no tool call. Three trigger layers feed ONE
8
- * reminder (the hybrid): keyword (user signals recall) · self-report (agent flags its own
9
- * gap) · nano (implicit gap). P1 = keyword (this file's `hasRecallIntent`) + the announce
10
- * that teaches the capability; self-report (the marker below) + nano land next.
11
- *
12
- * SEARCH-THEN-INJECT, not nudge: a trigger fires a memory search in the hook; only a hit
13
- * ABOVE the confidence gate is injected (top 1-2, capped). A miss = silence — so the search
14
- * result is its own precision filter and the reflex never becomes wallpaper (the
15
- * banner-blindness failure mode, fix `16a29a8b`). PURE module: the hook owns the search
16
- * (I/O) + frames the hit via `buildMemoryInjection`, then routes the string through env —
17
- * exactly the front-desk module's shape.
18
- *
19
- * EXCESSIVENESS is the watched risk (operator's call 2026-06-20): two filters bound it —
20
- * high-precision keyword phrases (low fire rate) + the confidence gate (low inject rate) —
21
- * and every fire is tallied (`MemoryReflexStats`) so /mechanic can monitor the rate and the
22
- * inject/fire ratio, and auto-quiet if it turns noisy. adr: adr/memory-reflex.md */
6
+ * HISTORY: this module once also did per-turn AUTO-INJECTION recall-intent keyword
7
+ * match inline memory search surface a hit. That was DROPPED 2026-06-22. Two
8
+ * reasons: (1) it was knowledge injection, NOT a behavioral reminder a different,
9
+ * undeveloped system that was jammed into the reminder registry for lack of a slot;
10
+ * (2) it collided with the agent's own, better-targeted `greprag memory search` (the
11
+ * auto-search just threw the raw prompt at the index). Same call that retired the
12
+ * `[[recall:]]` self-report marker: prefer a strong primer + agent judgment over a
13
+ * passive auto-surface. If a real "knowledge injection" system is built later, it gets
14
+ * its own home it is not a reminder. docs/reminder-interrupt.md (the landed map). */
23
15
  Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.memoryReflexModule = exports.MEMORY_QUIET_CACHE_TTL_MS = exports.MEMORY_CONFIDENCE_GATE = exports.RECALL_MARKER_RE = void 0;
25
- exports.hasRecallIntent = hasRecallIntent;
26
- exports.extractRecallMarker = extractRecallMarker;
27
- exports.selectGatedHits = selectGatedHits;
28
- exports.gatedHitText = gatedHitText;
29
- exports.buildMemoryInjection = buildMemoryInjection;
16
+ exports.memoryPrimerModule = void 0;
30
17
  exports.buildMemoryAnnounce = buildMemoryAnnounce;
31
- exports.injectionWasUsed = injectionWasUsed;
32
- exports.tallyMemoryFire = tallyMemoryFire;
33
- exports.tallyMemoryUsed = tallyMemoryUsed;
34
- exports.quietCacheSaysSilent = quietCacheSaysSilent;
35
- // ---------- Layer 1: keyword trigger (free, same-turn) -----------------------
36
- /** High-precision recall-intent phrases — MULTI-WORD by design (a single word like
37
- * "previously" over-fires). Each strongly implies the agent needs recalled project
38
- * context it may not hold. Tuned conservatively; the /mechanic monitor reports the
39
- * false-fire rate and this list is where we'd loosen/tighten. */
40
- const RECALL_PHRASES = [
41
- 'last time', 'we decided', 'we agreed', 'we chose', 'we discussed',
42
- 'we talked about', 'you said', 'you mentioned', 'you told me',
43
- 'remember when', 'remember that', 'what did we', 'what was our',
44
- 'as we discussed', 'as i mentioned', 'earlier you', 'earlier we',
45
- 'refresh my memory', 'catch me up', 'where did we leave',
46
- 'the bug we', 'that bug we', 'the plan we', 'did we ever', 'how did we',
47
- ];
48
- const RECALL_RE = new RegExp(`\\b(${RECALL_PHRASES.join('|').replace(/ /g, '\\s+')})\\b`, 'i');
49
- /** Does this prompt signal a recall need? Pure, total — the hook gates the inline search
50
- * on it. The query handed to the search is the prompt itself (the search is built for
51
- * natural queries; fragile noun-extraction buys nothing). */
52
- function hasRecallIntent(prompt) {
53
- return !!prompt && RECALL_RE.test(prompt);
54
- }
55
- // ---------- Layer 2: self-report marker (free, next-turn — scan lands in P1b) -
56
- /** The marker the announce teaches the agent to emit when it notices its OWN context gap.
57
- * Distinctive + greppable + cheap to type. The Stop-hook scan that consumes it (→ a
58
- * next-turn pull) is P1b; defined here now so the announce + the regex share one source. */
59
- exports.RECALL_MARKER_RE = /\[\[recall:\s*([^\]]+)\]\]/i;
60
- /** Extract the topic from a self-report marker in the agent's response (P1b — the Stop-scan).
61
- * Returns the trimmed, capped topic, or null when no marker. Pure, total. */
62
- function extractRecallMarker(response) {
63
- const m = exports.RECALL_MARKER_RE.exec(response || '');
64
- if (!m)
65
- return null;
66
- const topic = (m[1] || '').trim();
67
- return topic ? topic.slice(0, 200) : null;
68
- }
69
- /** Confidence gate — a hit must clear this to be injected. Below it, the reflex stays
70
- * silent (the search result IS the precision filter). Reranked hits carry a calibrated
71
- * `confidence` (0-1); unreranked hits fall back to a raw-score floor. */
72
- exports.MEMORY_CONFIDENCE_GATE = 0.5;
73
- const RAW_SCORE_FLOOR = 0.15;
74
- /** Hard cap — never inject more than this many hits (context-bloat discipline; we just
75
- * spent a session draining the heap). */
76
- const MAX_INJECTED = 2;
77
- /** Per-hit trim — keep each injected snippet tight. */
78
- const HIT_TRIM = 280;
79
- function passesGate(h) {
80
- return typeof h.confidence === 'number'
81
- ? h.confidence >= exports.MEMORY_CONFIDENCE_GATE
82
- : h.score >= RAW_SCORE_FLOOR;
83
- }
84
- /** The hits that clear the gate, capped — the SINGLE source of "what gets shown", shared by the
85
- * injection framing AND the efficacy capture, so the overlap is scored against exactly what
86
- * was injected. */
87
- function selectGatedHits(hits) {
88
- return (hits || []).filter(passesGate).slice(0, MAX_INJECTED);
89
- }
90
- /** Raw content of the gated hits (no framing boilerplate) — stashed at inject-time so the
91
- * Stop-hook overlap scores the response against the actual memory, not the frame. */
92
- function gatedHitText(hits) {
93
- return selectGatedHits(hits).map(h => h.content || '').join('\n');
94
- }
95
- function trim(s, n) {
96
- const t = (s || '').replace(/\s+/g, ' ').trim();
97
- return t.length > n ? t.slice(0, n - 1) + '…' : t;
98
- }
99
- /** Frame the gated top hits into the inline injection block; null when nothing clears the
100
- * gate (→ the module stays silent that turn). Tier is ambient (soft context, never a
101
- * forced-decision directive). Tight + capped by design. */
102
- function buildMemoryInjection(hits) {
103
- const passing = selectGatedHits(hits);
104
- if (passing.length === 0)
105
- return null;
106
- const lines = ['[📁 greprag memory — possibly relevant, auto-surfaced (pull more: `greprag memory search`):'];
107
- for (const h of passing) {
108
- const meta = [h.shape, h.createdAt ? h.createdAt.slice(0, 10) : null, h.projectName]
109
- .filter(Boolean).join(', ');
110
- lines.push(` · ${trim(h.content, HIT_TRIM)}${meta ? ` (${meta})` : ''}`);
111
- }
112
- lines.push(']');
113
- return lines.join('\n');
114
- }
115
- // ---------- SessionStart announce (teach the capability once) -----------------
116
- /** The business card, loaded once. Teaches BOTH the passive auto-surface AND (P1b, now live)
117
- * the active self-report marker. Action-first, token-minimal, per the reminder-interrupt
118
- * authoring rules. */
18
+ /** The business card, loaded once. Teaches the on-demand search/recap reflex —
19
+ * action-first, token-minimal, per the reminder-interrupt authoring rules. */
119
20
  function buildMemoryAnnounce() {
120
21
  return [
121
- '[greprag memory — this project has episodic memory (every past session, searchable).]',
122
- 'When THIS turn leans on earlier worka past decision, a bug you hit before, what was discussed relevant memory is auto-surfaced inline; use it.',
123
- 'When you notice you are MISSING context this project would hold and it did NOT surface, emit `[[recall: <topic>]]` in your reply — that topic is pulled in on your next turn.',
124
- 'Or pull on demand any time: `greprag memory search "<topic>"` (`greprag memory recap` to catch up).',
22
+ '[greprag memory — this project remembers. Every past session (decisions, bugs, what was discussed, who did what) is captured and searchable.]',
23
+ 'On demand, the moment you suspect this project knows something you don\'t: `greprag memory search "<topic>"` (semantic ask in natural language), `greprag memory recap` to catch up on the session, `greprag memory recap --last N` for deeper history. Searching is cheap reach for it rather than guessing or asking the operator to re-explain.',
125
24
  ].join('\n');
126
25
  }
127
- // ---------- Efficacy: did the injection get USED (the overlap proxy) ----------
128
- /** Free overlap proxy for "did the response draw on the injected memory" — the efficacy
129
- * numerator's cheap first rung. (The Flash-Lite judge calibrates/replaces it later,
130
- * server-side; greprag's judge model is Gemini Flash-Lite, never nano.) Distinctive CONTENT
131
- * terms the injection introduced in the hit, NOT already in the prompt, not stopwords /
132
- * frame boilerplate — that reappear in the response. ≥ USED_MIN_TERMS reused → used.
133
- * Imperfect (paraphrase escapes it, coincidence trips it) but a real aggregate signal at
134
- * zero cost + zero latency. */
135
- const USED_MIN_TERMS = 2;
136
- const MIN_TERM_LEN = 4;
137
- const TERM_STOPWORDS = new Set([
138
- 'this', 'that', 'with', 'from', 'have', 'were', 'your', 'they', 'them', 'then', 'than',
139
- 'will', 'would', 'could', 'should', 'about', 'there', 'their', 'what', 'when', 'which',
140
- 'into', 'over', 'also', 'been', 'more', 'most', 'some', 'such', 'only', 'just', 'like',
141
- 'here', 'where', 'these', 'those', 'them', 'because',
142
- // injection-frame boilerplate — never count these as "used":
143
- 'greprag', 'memory', 'relevant', 'surfaced', 'auto', 'session', 'project', 'search', 'recap', 'pull',
144
- ]);
145
- function contentTerms(text) {
146
- const out = new Set();
147
- for (const raw of (text || '').toLowerCase().split(/[^a-z0-9]+/)) {
148
- if (raw.length >= MIN_TERM_LEN && !TERM_STOPWORDS.has(raw))
149
- out.add(raw);
150
- }
151
- return out;
152
- }
153
- /** Did the agent's response reuse distinctive content from the injection? Pure, total. */
154
- function injectionWasUsed(hitText, prompt, response) {
155
- const hitTerms = contentTerms(hitText);
156
- if (hitTerms.size === 0)
157
- return false;
158
- const promptTerms = contentTerms(prompt);
159
- const respTerms = contentTerms(response);
160
- let used = 0;
161
- for (const t of hitTerms) {
162
- if (promptTerms.has(t))
163
- continue; // not distinctive — already in the prompt
164
- if (respTerms.has(t) && ++used >= USED_MIN_TERMS)
165
- return true;
166
- }
167
- return false;
168
- }
169
- function normalizeStats(prior) {
170
- const p = (prior && typeof prior === 'object') ? prior : {};
171
- const bt = (p.byTrigger && typeof p.byTrigger === 'object') ? p.byTrigger : {};
172
- return {
173
- fires: Number.isFinite(p.fires) ? p.fires : 0,
174
- injected: Number.isFinite(p.injected) ? p.injected : 0,
175
- silent: Number.isFinite(p.silent) ? p.silent : 0,
176
- used: Number.isFinite(p.used) ? p.used : 0,
177
- byTrigger: {
178
- keyword: Number.isFinite(bt.keyword) ? bt.keyword : 0,
179
- selfReport: Number.isFinite(bt.selfReport) ? bt.selfReport : 0,
180
- flash: Number.isFinite(bt.flash) ? bt.flash : 0,
181
- },
182
- firstFiredAt: p.firstFiredAt,
183
- lastFiredAt: p.lastFiredAt,
184
- lastTurnCount: p.lastTurnCount,
185
- };
186
- }
187
- /** Tally one fire — PURE (the hook supplies the clock). `didInject` splits the
188
- * fire into injected vs silent so the monitor can read the inject/fire ratio. */
189
- function tallyMemoryFire(prior, trigger, didInject, turnCount, nowIso) {
190
- const s = normalizeStats(prior);
191
- s.fires += 1;
192
- if (didInject)
193
- s.injected += 1;
194
- else
195
- s.silent += 1;
196
- s.byTrigger[trigger] += 1;
197
- s.firstFiredAt = s.firstFiredAt || nowIso;
198
- s.lastFiredAt = nowIso;
199
- if (Number.isFinite(turnCount))
200
- s.lastTurnCount = turnCount;
201
- return s;
202
- }
203
- /** Record that an injection was USED (the efficacy numerator) — PURE; bumped at Stop when the
204
- * overlap proxy (or, later, the Flash-Lite judge) finds the response drew on the injection.
205
- * Never decrements; `used ≤ injected` by construction of the call sites. */
206
- function tallyMemoryUsed(prior) {
207
- const s = normalizeStats(prior);
208
- s.used += 1;
209
- return s;
210
- }
211
- // ---------- Auto-quiet (server efficacy verdict, cached locally) --------------
212
- /** The server (the Flash-Lite judge, `@greprag/core` memory-efficacy) owns the
213
- * auto-quiet THRESHOLD and ships its verdict on the /v1/memory/query response.
214
- * The hook caches that boolean and honors it with a TTL — how long to trust a
215
- * cached verdict before re-probing. While quiet the reflex skips the search, so
216
- * no fresh verdict arrives and the cache ages; once stale the reflex fires again
217
- * to re-probe and the server re-judges. That gives auto-quiet TEETH (a real
218
- * silent window) while staying self-healing — a reflex that recovers is never
219
- * permanently silenced (unlike the hard, manual mechanicKilled() switch). */
220
- exports.MEMORY_QUIET_CACHE_TTL_MS = 12 * 60 * 60 * 1000; // 12h
221
- /** Does the locally-cached server verdict say "stay silent THIS turn"? PURE +
222
- * total. Silent only when the cache is present, says quiet, and is still fresh.
223
- * Fail-open everywhere else (missing / malformed / stale → NOT silent) so a bad
224
- * cache can never permanently kill the reflex. */
225
- function quietCacheSaysSilent(cache, nowMs) {
226
- if (!cache || cache.quiet !== true || typeof cache.cachedAt !== 'string')
227
- return false;
228
- const t = Date.parse(cache.cachedAt);
229
- if (!Number.isFinite(t))
230
- return false;
231
- return (nowMs - t) < exports.MEMORY_QUIET_CACHE_TTL_MS;
232
- }
233
- // ---------- The registry module ----------------------------------------------
234
- /** memory-reflex as a reminder-interrupt module. announce teaches memory once; reminder
235
- * routes the hook-supplied injection (env.memoryHit); detect gates on its presence. PURE —
236
- * the hook owns the keyword gate + the search + the framing + the tally. */
237
- exports.memoryReflexModule = {
238
- id: 'memory-reflex',
239
- detect: (env) => (env.memoryHit ? { tier: 'ambient' } : { tier: 'silent' }),
240
- announce: () => buildMemoryAnnounce(),
241
- reminder: (_d, env) => env.memoryHit ?? null,
26
+ /** memory-primer as a reminder-interrupt module: announce-only (a PRIMER). detect →
27
+ * silent, reminder null. PURE. */
28
+ exports.memoryPrimerModule = {
29
+ id: 'memory-primer',
30
+ detect: (_env) => ({ tier: 'silent' }),
31
+ announce: (_env) => buildMemoryAnnounce(),
32
+ reminder: () => null,
242
33
  };
243
34
  //# sourceMappingURL=memory-reflex.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory-reflex.js","sourceRoot":"","sources":["../../src/commands/memory-reflex.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory-reflex.js","sourceRoot":"","sources":["../../src/commands/memory-reflex.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;wFAYwF;;;AAMxF,kDAKC;AAPD;+EAC+E;AAC/E,SAAgB,mBAAmB;IACjC,OAAO;QACL,+IAA+I;QAC/I,wVAAwV;KACzV,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;qCACqC;AACxB,QAAA,kBAAkB,GAAmB;IAChD,EAAE,EAAE,eAAe;IACnB,MAAM,EAAE,CAAC,IAAiB,EAAa,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC9D,QAAQ,EAAE,CAAC,IAAiB,EAAiB,EAAE,CAAC,mBAAmB,EAAE;IACrE,QAAQ,EAAE,GAAkB,EAAE,CAAC,IAAI;CACpC,CAAC"}
@@ -11,6 +11,11 @@ import { ReminderEnv, ReminderModule, Detection } from './reminder-types';
11
11
  * loud, action-first modules last (watcher-arm → mechanic) so they read most-recent at
12
12
  * SessionStart. Add a module here to wire it into BOTH surfaces at once. */
13
13
  export declare const REGISTRY: ReminderModule[];
14
+ /** Split the registry by READ surface (docs/reminder-interrupt.md). UserPromptSubmit
15
+ * evaluates `prompt`-source modules (the default); PreToolUse evaluates `command`-source
16
+ * modules (they read env.toolCommand). Announces are always prompt-side (SessionStart). */
17
+ export declare const promptModules: (registry?: ReminderModule[]) => ReminderModule[];
18
+ export declare const commandModules: (registry?: ReminderModule[]) => ReminderModule[];
14
19
  export interface FiredReminder {
15
20
  id: string;
16
21
  tier: Detection['tier'];
@@ -20,5 +25,11 @@ export interface FiredReminder {
20
25
  * Stacking — a turn may carry several. A detector or reminder that throws drops that
21
26
  * module for the turn; it never blocks the others or the turn. */
22
27
  export declare function collectReminders(env: ReminderEnv, registry?: ReminderModule[]): FiredReminder[];
23
- /** SessionStart: every module's announce (skipping null), in registry order. */
28
+ /** Boot-sequence sort: a STABLE topological order over `dependsOn` (docs/load-system.md).
29
+ * Registry array order is the tie-breaker, so a dependency-free registry is emitted
30
+ * verbatim; declared deps only ever pull a module EARLIER. A missing/cyclic dep degrades
31
+ * gracefully to array order (never throws — a boot order is not worth crashing a turn). */
32
+ export declare function bootOrder(registry: ReminderModule[]): ReminderModule[];
33
+ /** SessionStart: every module's announce (skipping null), in BOOT-SEQUENCE order
34
+ * (dependsOn topo-sort, array order as tie-breaker). */
24
35
  export declare function collectAnnounces(env: ReminderEnv, registry?: ReminderModule[]): string[];
@@ -5,10 +5,13 @@
5
5
  * PURE over ReminderEnv — the hook assembles env (i/o) and emits the returned lines;
6
6
  * a broken module never blocks a turn (fail-open per module). */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.REGISTRY = void 0;
8
+ exports.commandModules = exports.promptModules = exports.REGISTRY = void 0;
9
9
  exports.collectReminders = collectReminders;
10
+ exports.bootOrder = bootOrder;
10
11
  exports.collectAnnounces = collectAnnounces;
11
12
  const inbox_primer_reminder_1 = require("./inbox-primer-reminder");
13
+ const load_primer_reminder_1 = require("./load-primer-reminder");
14
+ const corpus_reminder_1 = require("./corpus-reminder");
12
15
  const setup_reminder_1 = require("./setup-reminder");
13
16
  const frontdesk_reminder_1 = require("./frontdesk-reminder");
14
17
  const checkpoint_reminder_1 = require("./checkpoint-reminder");
@@ -16,6 +19,8 @@ const assistant_reminder_1 = require("./assistant-reminder");
16
19
  const memory_reflex_1 = require("./memory-reflex");
17
20
  const arm_reminder_1 = require("./arm-reminder");
18
21
  const friction_reminder_1 = require("./friction-reminder");
22
+ const collision_reminder_1 = require("./collision-reminder");
23
+ const version_reminder_1 = require("./version-reminder");
19
24
  /** Registry order = display order. THE single agent-facing announce/reminder assembly:
20
25
  * the hook does I/O → fills ReminderEnv → collectAnnounces (SessionStart) / collectReminders
21
26
  * (per turn) render every module here in this order. Order preserves the historical recap
@@ -24,14 +29,26 @@ const friction_reminder_1 = require("./friction-reminder");
24
29
  * SessionStart. Add a module here to wire it into BOTH surfaces at once. */
25
30
  exports.REGISTRY = [
26
31
  inbox_primer_reminder_1.inboxPrimerModule,
32
+ load_primer_reminder_1.loadPrimerModule,
33
+ load_primer_reminder_1.chipSpawnPointerModule,
34
+ corpus_reminder_1.corpusAnnounceModule,
27
35
  setup_reminder_1.setupWarningModule,
36
+ version_reminder_1.versionUpgradeModule, // Deficiency-gated announce — silent unless a newer release exists
28
37
  frontdesk_reminder_1.frontDeskModule,
29
38
  checkpoint_reminder_1.checkpointModule,
30
39
  assistant_reminder_1.assistantDoctrineModule,
31
- memory_reflex_1.memoryReflexModule,
40
+ memory_reflex_1.memoryPrimerModule,
32
41
  arm_reminder_1.watcherArmModule,
33
42
  friction_reminder_1.mechanicFrictionModule,
43
+ collision_reminder_1.collisionMatchModule, // source: 'command' — evaluated at PreToolUse, not UserPromptSubmit
34
44
  ];
45
+ /** Split the registry by READ surface (docs/reminder-interrupt.md). UserPromptSubmit
46
+ * evaluates `prompt`-source modules (the default); PreToolUse evaluates `command`-source
47
+ * modules (they read env.toolCommand). Announces are always prompt-side (SessionStart). */
48
+ const promptModules = (registry = exports.REGISTRY) => registry.filter((m) => (m.source ?? 'prompt') === 'prompt');
49
+ exports.promptModules = promptModules;
50
+ const commandModules = (registry = exports.REGISTRY) => registry.filter((m) => m.source === 'command');
51
+ exports.commandModules = commandModules;
35
52
  /** Per-turn: every module's live reminder line (skipping silent), in registry order.
36
53
  * Stacking — a turn may carry several. A detector or reminder that throws drops that
37
54
  * module for the turn; it never blocks the others or the turn. */
@@ -59,10 +76,37 @@ function collectReminders(env, registry = exports.REGISTRY) {
59
76
  }
60
77
  return out;
61
78
  }
62
- /** SessionStart: every module's announce (skipping null), in registry order. */
79
+ /** Boot-sequence sort: a STABLE topological order over `dependsOn` (docs/load-system.md).
80
+ * Registry array order is the tie-breaker, so a dependency-free registry is emitted
81
+ * verbatim; declared deps only ever pull a module EARLIER. A missing/cyclic dep degrades
82
+ * gracefully to array order (never throws — a boot order is not worth crashing a turn). */
83
+ function bootOrder(registry) {
84
+ const byId = new Map(registry.map((m) => [m.id, m]));
85
+ const ordered = [];
86
+ const placed = new Set();
87
+ const visiting = new Set();
88
+ const visit = (m) => {
89
+ if (placed.has(m.id) || visiting.has(m.id))
90
+ return; // placed, or a cycle → bail
91
+ visiting.add(m.id);
92
+ for (const dep of m.dependsOn ?? []) {
93
+ const d = byId.get(dep);
94
+ if (d)
95
+ visit(d); // unknown dep id → ignored (graceful)
96
+ }
97
+ visiting.delete(m.id);
98
+ placed.add(m.id);
99
+ ordered.push(m);
100
+ };
101
+ for (const m of registry)
102
+ visit(m);
103
+ return ordered;
104
+ }
105
+ /** SessionStart: every module's announce (skipping null), in BOOT-SEQUENCE order
106
+ * (dependsOn topo-sort, array order as tie-breaker). */
63
107
  function collectAnnounces(env, registry = exports.REGISTRY) {
64
108
  const out = [];
65
- for (const m of registry) {
109
+ for (const m of bootOrder(registry)) {
66
110
  let a = null;
67
111
  try {
68
112
  a = m.announce(env);
@@ -1 +1 @@
1
- {"version":3,"file":"reminder-registry.js","sourceRoot":"","sources":["../../src/commands/reminder-registry.ts"],"names":[],"mappings":";AAAA;;;;kEAIkE;;;AAsClE,4CAaC;AAGD,4CAUC;AA7DD,mEAA4D;AAC5D,qDAAsD;AACtD,6DAAuD;AACvD,+DAAyD;AACzD,6DAA+D;AAC/D,mDAAqD;AACrD,iDAAkD;AAClD,2DAA6D;AAE7D;;;;;6EAK6E;AAChE,QAAA,QAAQ,GAAqB;IACxC,yCAAiB;IACjB,mCAAkB;IAClB,oCAAe;IACf,sCAAgB;IAChB,4CAAuB;IACvB,kCAAkB;IAClB,+BAAgB;IAChB,0CAAsB;CACvB,CAAC;AAQF;;mEAEmE;AACnE,SAAgB,gBAAgB,CAC9B,GAAgB,EAAE,WAA6B,gBAAQ;IAEvD,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAY,CAAC;QACjB,IAAI,CAAC;YAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QAC9C,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QACxC,IAAI,IAAI,GAAkB,IAAI,CAAC;QAC/B,IAAI,CAAC;YAAC,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QACtD,IAAI,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,gFAAgF;AAChF,SAAgB,gBAAgB,CAC9B,GAAgB,EAAE,WAA6B,gBAAQ;IAEvD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,GAAkB,IAAI,CAAC;QAC5B,IAAI,CAAC;YAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QAChD,IAAI,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"reminder-registry.js","sourceRoot":"","sources":["../../src/commands/reminder-registry.ts"],"names":[],"mappings":"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"}
@@ -40,6 +40,19 @@ export interface ReminderEnv {
40
40
  /** Precomputed assistant-doctrine context — the hook owns the doctrine-file read, so
41
41
  * this module half is a pass-through. Null for any non-assistant project. */
42
42
  assistantDoctrine?: string | null;
43
+ /** Deficiency-gated announce signal: the installed greprag is behind the latest
44
+ * published version. Set by the hook (daily-cached npm-registry check); null/undefined
45
+ * when current. Drives the version-upgrade announce — "new release, upgrade with X".
46
+ * docs/reminder-interrupt.md (a Deficiency-gated announce, not a new type). */
47
+ updateAvailable?: {
48
+ current: string;
49
+ latest: string;
50
+ } | null;
51
+ /** Names of the api-docs-tagged corpus stores (the hook lists `?tag=api-docs`).
52
+ * Drives the corpus announce: name the on-tap reference banks so an agent
53
+ * searches them before answering from training data. Empty/undefined → the
54
+ * corpus announce stays silent. adr: adr/corpus-tags.md */
55
+ corpusApiDocs?: string[];
43
56
  /** Envelope-only "you've got mail" front-desk notice — the hook owns the network +
44
57
  * per-machine dedup; the front-desk module routes it as its per-turn reminder. */
45
58
  frontDeskNotice?: string | null;
@@ -47,6 +60,14 @@ export interface ReminderEnv {
47
60
  * the search + the confidence gate + framing; the memory-reflex module routes the
48
61
  * framed string as its per-turn reminder. Null = nothing cleared the gate this turn. */
49
62
  memoryHit?: string | null;
63
+ /** The Bash command about to run (the `command` read surface for a Match trigger).
64
+ * Present only on the PreToolUse env; undefined at UserPromptSubmit. */
65
+ toolCommand?: string | null;
66
+ /** Same-repo peers live right now (the hook does the fresh watcher read off the
67
+ * hot path and passes the result; the collision module detects purely on it). */
68
+ collisionPeers?: {
69
+ short: string;
70
+ }[];
50
71
  }
51
72
  /** Slim open-checkpoint row (the SessionStart landmark announce, checkpoint module).
52
73
  * Lives here — not in checkpoint-reminder.ts — because ReminderEnv references it and a
@@ -67,6 +88,18 @@ export interface Detection {
67
88
  * unit-testable regression-lock. */
68
89
  export interface ReminderModule {
69
90
  id: string;
91
+ /** Which READ surface this module fires on (docs/reminder-interrupt.md — the landed
92
+ * map). `prompt` (default) modules run at UserPromptSubmit; `command` modules run at
93
+ * PreToolUse, reading `env.toolCommand`. The call site filters the registry by source
94
+ * so each hook event evaluates only its own modules. */
95
+ source?: 'prompt' | 'command';
96
+ /** Boot-sequence dependencies (docs/load-system.md §boot sequence): module ids whose
97
+ * announce MUST be emitted before this one's. A primer that references a concept an
98
+ * earlier primer establishes declares it here (e.g. the mechanic primer references chip
99
+ * vehicles → `dependsOn: ['chip-spawn-pointer']`; every pointer that says "greprag load"
100
+ * → `dependsOn: ['load-primer']`). collectAnnounces topologically sorts on this, so the
101
+ * boot order is a declared graph, not fragile array position. Omit = no dependency. */
102
+ dependsOn?: string[];
70
103
  /** Read the live deficiency. The gate: `silent` ⇒ the module is quiet this turn. */
71
104
  detect: (env: ReminderEnv) => Detection;
72
105
  /** SessionStart schema, loaded once (teach method + why). null = nothing to announce. */
@@ -0,0 +1,15 @@
1
+ /** version-reminder — the release-upgrade announce. A DEFICIENCY-gated announce
2
+ * (docs/reminder-interrupt.md): the Deficiency trigger ("a required state is missing")
3
+ * applied to the ANNOUNCE surface — the required state is "running the latest greprag,"
4
+ * the deficiency is "installed < latest published." When behind, the SessionStart announce
5
+ * tells the user a new release is out + how to upgrade; it auto-clears once they upgrade.
6
+ *
7
+ * This is what makes a release PROPAGATE — without it, users never learn to upgrade.
8
+ * NOT a new announce kind: it is a primer gated by Deficiency, exactly like setup-warning
9
+ * (which announces only when there's a drift gap). The hook does the I/O (the daily-cached
10
+ * npm-registry version check) and passes the verdict as env.updateAvailable; this module
11
+ * is PURE — announce-only (detect → silent, reminder → null). */
12
+ import { ReminderModule } from './reminder-types';
13
+ /** The upgrade announce — null unless the hook detected a newer published version. */
14
+ export declare function buildVersionAnnounce(current: string, latest: string): string;
15
+ export declare const versionUpgradeModule: ReminderModule;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /** version-reminder — the release-upgrade announce. A DEFICIENCY-gated announce
3
+ * (docs/reminder-interrupt.md): the Deficiency trigger ("a required state is missing")
4
+ * applied to the ANNOUNCE surface — the required state is "running the latest greprag,"
5
+ * the deficiency is "installed < latest published." When behind, the SessionStart announce
6
+ * tells the user a new release is out + how to upgrade; it auto-clears once they upgrade.
7
+ *
8
+ * This is what makes a release PROPAGATE — without it, users never learn to upgrade.
9
+ * NOT a new announce kind: it is a primer gated by Deficiency, exactly like setup-warning
10
+ * (which announces only when there's a drift gap). The hook does the I/O (the daily-cached
11
+ * npm-registry version check) and passes the verdict as env.updateAvailable; this module
12
+ * is PURE — announce-only (detect → silent, reminder → null). */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.versionUpgradeModule = void 0;
15
+ exports.buildVersionAnnounce = buildVersionAnnounce;
16
+ /** The upgrade announce — null unless the hook detected a newer published version. */
17
+ function buildVersionAnnounce(current, latest) {
18
+ return [
19
+ `[greprag — a new release is out: v${latest} (you are on v${current}).]`,
20
+ `Upgrade: \`npm i -g greprag@latest\`. New behavior + fixes land on your next session.`,
21
+ ].join('\n');
22
+ }
23
+ exports.versionUpgradeModule = {
24
+ id: 'version-upgrade',
25
+ detect: (_env) => ({ tier: 'silent' }), // announce-only
26
+ announce: (env) => {
27
+ const u = env.updateAvailable;
28
+ if (!u || !u.current || !u.latest)
29
+ return null;
30
+ return buildVersionAnnounce(u.current, u.latest);
31
+ },
32
+ reminder: () => null,
33
+ };
34
+ //# sourceMappingURL=version-reminder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-reminder.js","sourceRoot":"","sources":["../../src/commands/version-reminder.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;kEAUkE;;;AAKlE,oDAKC;AAND,sFAAsF;AACtF,SAAgB,oBAAoB,CAAC,OAAe,EAAE,MAAc;IAClE,OAAO;QACL,qCAAqC,MAAM,iBAAiB,OAAO,KAAK;QACxE,uFAAuF;KACxF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAEY,QAAA,oBAAoB,GAAmB;IAClD,EAAE,EAAE,iBAAiB;IACrB,MAAM,EAAE,CAAC,IAAiB,EAAa,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,gBAAgB;IAChF,QAAQ,EAAE,CAAC,GAAgB,EAAiB,EAAE;QAC5C,MAAM,CAAC,GAAG,GAAG,CAAC,eAAe,CAAC;QAC9B,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC/C,OAAO,oBAAoB,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC;IACD,QAAQ,EAAE,GAAkB,EAAE,CAAC,IAAI;CACpC,CAAC"}