@gramatr/client 0.6.18 → 0.6.20

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.
@@ -20,7 +20,7 @@
20
20
  * - Token savings metadata
21
21
  */
22
22
 
23
- import { readFileSync } from 'fs';
23
+ import { readFileSync, appendFileSync } from 'fs';
24
24
  import { getGitContext } from './lib/gmtr-hook-utils.ts';
25
25
  import {
26
26
  persistClassificationResult,
@@ -29,6 +29,12 @@ import {
29
29
  } from '../core/routing.ts';
30
30
  import type { RouteResponse } from '../core/types.ts';
31
31
 
32
+ // ── Turn Tracking (Issue #594) ──
33
+ // Module-level counter incremented per prompt in this process.
34
+ // Reset on process restart (acceptable — session-end flushes).
35
+ let turnCounter = 0;
36
+ const TURNS_JSONL_PATH = '/tmp/gramatr-turns.jsonl';
37
+
32
38
  // ── Types ──
33
39
 
34
40
  interface HookInput {
@@ -337,6 +343,10 @@ function formatIntelligence(data: RouteResponse): string {
337
343
  lines.push('The ISC prefix is REQUIRED — it signals to the user that GMTR intelligence is driving the criteria.');
338
344
  lines.push('This is a HARD GATE — do NOT proceed to any work until TaskCreate calls are complete.');
339
345
 
346
+ // ── grā identity — server-generated content marker ──
347
+ lines.push('');
348
+ lines.push('When presenting gramatr intelligence (ISC scaffolds, search results, agent recommendations, summaries), prefix with **grā:** in bold. This distinguishes server-pre-computed content from your own reasoning. Example: "**grā:** ISC scaffold suggests 6 criteria for this migration task."');
349
+
340
350
  // ── Effort-level-scaled format ──
341
351
  if (effort === 'instant') {
342
352
  lines.push('');
@@ -614,6 +624,23 @@ async function main() {
614
624
 
615
625
  persistLastClassification(prompt, session_id, result, downstreamModel);
616
626
 
627
+ // Accumulate turn data for batch flush at session end (Issue #594)
628
+ try {
629
+ const cl = result?.classification || {};
630
+ const es = result?.execution_summary || {};
631
+ const turnData = {
632
+ turn_number: turnCounter++,
633
+ timestamp: new Date().toISOString(),
634
+ prompt: prompt.substring(0, 500),
635
+ effort_level: cl.effort_level || null,
636
+ intent_type: cl.intent_type || null,
637
+ confidence: cl.confidence || null,
638
+ memory_tier: cl.memory_tier || null,
639
+ classifier_model: es.classifier_model || null,
640
+ };
641
+ appendFileSync(TURNS_JSONL_PATH, JSON.stringify(turnData) + '\n');
642
+ } catch { /* never block the hook */ }
643
+
617
644
  // If no result — DO NOT silently pass through. Tell the user what's broken.
618
645
  if (!result || !result.classification) {
619
646
  if (lastFailure) {
@@ -11,7 +11,7 @@
11
11
  * ZERO external CLI dependencies — no jq, sed, curl, awk.
12
12
  */
13
13
 
14
- import { writeFileSync } from 'fs';
14
+ import { writeFileSync, readFileSync, existsSync, unlinkSync } from 'fs';
15
15
  import { join } from 'path';
16
16
  import {
17
17
  readHookInput,
@@ -129,6 +129,32 @@ async function main(): Promise<void> {
129
129
  log('');
130
130
  log('Saving session state to gramatr...');
131
131
 
132
+ // ── Flush accumulated turns to server (Issue #594) ──
133
+ try {
134
+ const turnsFile = '/tmp/gramatr-turns.jsonl';
135
+ if (existsSync(turnsFile)) {
136
+ const lines = readFileSync(turnsFile, 'utf8').trim().split('\n').filter(Boolean);
137
+ const turns = lines.map(line => JSON.parse(line));
138
+ if (turns.length > 0) {
139
+ log(` Flushing ${turns.length} turns to gramatr...`);
140
+ const interactionId = config?.current_session?.interaction_id || '';
141
+ const flushResult = await callMcpToolRaw('gramatr_batch_save_turns', {
142
+ session_id: sessionEntityId || sessionId,
143
+ project_id: projectId,
144
+ turns,
145
+ });
146
+ if (flushResult && flushResult.includes('"turns_saved"')) {
147
+ log(` Turns flushed successfully`);
148
+ } else {
149
+ log(' Turn flush uncertain (server may be unavailable)');
150
+ }
151
+ }
152
+ unlinkSync(turnsFile);
153
+ }
154
+ } catch {
155
+ log(' Turn flush failed (non-critical)');
156
+ }
157
+
132
158
  // Session lifecycle only — gramatr_session_end records git summary on the session entity.
133
159
  // Handoffs are saved by the AGENT in the LEARN phase via gramatr_save_handoff (HARD GATE).
134
160
  // The hook does NOT save handoffs — it lacks conversation context.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gramatr/client",
3
- "version": "0.6.18",
3
+ "version": "0.6.20",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },