eklavya 1.9.4 → 1.11.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.
@@ -287,13 +287,15 @@ A pinned level (`pinned: true`) means someone set the band deliberately — an o
287
287
  Every plan item carries `ask_header`: one bracketed line naming the settings that asked the question.
288
288
 
289
289
  ```
290
- [ambient · concept · easy · tier 2 mechanism · q 1/3]
290
+ [mode: ambient · focus: concept · level: easy · tier: 2 mechanism · question: 1 of 3]
291
291
 
292
292
  Why is httpOnly set on the refresh cookie here but not on the access token?
293
293
  ```
294
294
 
295
- Mode, focus, level, what the tier is asking for, and — when the plan holds more
296
- than one — which question of how many this is.
295
+ Every part names its dial: mode, focus, level, what the tier is asking for, and
296
+ — when the plan holds more than one — which question of how many this is. The
297
+ labels are the point. Four bare values only read as a settings line to someone
298
+ who already knows there are four dials and what order they come in.
297
299
 
298
300
  **Print it as the first line of the `question` you pass to `AskUserQuestion`**, then a blank line, then the stem, exactly as given. It is the only thing on screen that explains why a question is pitched where it is — without it, a `concept`-focus question reads as vague and an `easy` question reads as shallow.
299
301
 
package/dist/cli.js CHANGED
@@ -11,7 +11,7 @@ import { openDb } from './db.js';
11
11
  import { dbPath, eklavyaHome } from './paths.js';
12
12
  import { loadConfig, writeConfigFile, REPO_CONFIG_FILE, DEFAULT_CONFIG } from './config.js';
13
13
  import { levelStanding } from './store.js';
14
- import { startDashboard } from './dashboard.js';
14
+ import { startDashboard, openInBrowser } from './dashboard.js';
15
15
  import { install, uninstall } from './install.js';
16
16
  const moduleDir = path.dirname(fileURLToPath(import.meta.url));
17
17
  const USAGE = `eklavya — local learning state for agent-assisted development
@@ -27,7 +27,8 @@ Usage:
27
27
  cadence interleaved|end,
28
28
  difficulty auto|easy|medium|hard
29
29
  add --topic <topic> when setting focus to "learn"
30
- eklavya dashboard [--port <n>] Serve the learning dashboard on localhost
30
+ eklavya dashboard [--port <n>] Serve the learning dashboard and open it in your browser
31
+ (--no-open serves it and just prints the URL)
31
32
  eklavya doctor Check that everything is wired up
32
33
  eklavya db-path Print the database location
33
34
 
@@ -175,8 +176,16 @@ function dashboardCommand(argv) {
175
176
  process.stderr.write('eklavya dashboard: --port needs a number\n');
176
177
  process.exit(1);
177
178
  }
179
+ // Opens by default. A dashboard you have to copy out of a terminal is a
180
+ // dashboard you open once; `--no-open` is for a headless box, or for an agent
181
+ // that only wants the URL to hand back.
182
+ const open = !argv.includes('--no-open');
178
183
  startDashboard(openDb(), { port }).then(({ url }) => {
179
184
  process.stdout.write(`Eklavya dashboard on ${url}\nReading ${dbPath()} — press Ctrl+C to stop.\n`);
185
+ if (open) {
186
+ process.stdout.write('Opening it in your browser…\n');
187
+ openInBrowser(url);
188
+ }
180
189
  }, (err) => {
181
190
  process.stderr.write(`eklavya dashboard: ${err.message}\n`);
182
191
  process.exit(1);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/dashboard.js CHANGED
@@ -3,19 +3,30 @@
3
3
  *
4
4
  * The terminal report has to fit in twenty lines, so it answers "what now?".
5
5
  * This answers "am I getting better?", which needs history, per-project
6
- * comparison and the full concept list — none of which fit in a paragraph.
6
+ * comparison, per-concept history and the full concept list — none of which fit
7
+ * in a paragraph.
7
8
  *
8
9
  * Deliberately a static page plus one JSON endpoint: no framework, no build
9
10
  * step, same rule the landing page follows. It binds to loopback only, which
10
11
  * is the whole security model — the data never leaves the machine, and that
11
12
  * is a promise the landing page makes on Eklavya's behalf.
13
+ *
14
+ * The endpoint ships mostly *flat rows* — every attempt, every logged context,
15
+ * one row per day — and lets the page derive the views. One aggregate query per
16
+ * card is a coupling to the layout: the sessions view, the streak, the per-day
17
+ * heatmap and the per-concept history are four readings of the same attempt
18
+ * rows, and adding a fifth view should not mean adding a fifth query. The whole
19
+ * payload for a heavy year of use is a few hundred kilobytes over loopback.
12
20
  */
13
21
  import http from 'node:http';
14
22
  import fs from 'node:fs';
23
+ import { spawn } from 'node:child_process';
15
24
  import path from 'node:path';
16
25
  import { fileURLToPath } from 'node:url';
17
- import { decayedScore, isDue, isKnown } from './srs.js';
18
- import { GLOBAL_PROJECT } from './store.js';
26
+ import { decayedScore, isDue, isKnown, MS_PER_DAY } from './srs.js';
27
+ import { GLOBAL_PROJECT, levelStanding, PASSING_GRADE } from './store.js';
28
+ import { loadConfig, DEFAULT_CONFIG } from './config.js';
29
+ import { dbPath } from './paths.js';
19
30
  const moduleDir = path.dirname(fileURLToPath(import.meta.url));
20
31
  /**
21
32
  * High, unassigned, and deliberately boring to collide with.
@@ -28,41 +39,80 @@ const moduleDir = path.dirname(fileURLToPath(import.meta.url));
28
39
  * is as good a reason as any to remember it.)
29
40
  */
30
41
  const DEFAULT_PORT = 41729;
31
- /** Enough history to see a trend, short enough to stay one screen wide. */
32
- const TIMELINE_DAYS = 30;
42
+ /**
43
+ * How much history the per-day rows cover. A year, because the calendar heatmap
44
+ * shows half of one and the streak has to be able to run off the top of it —
45
+ * a thirty-day window would cap the longest streak at thirty.
46
+ */
47
+ const TIMELINE_DAYS = 365;
48
+ /**
49
+ * Cap on the attempt rows shipped for drill-down. Counts and per-day totals are
50
+ * aggregated in SQL over the whole table, so the cap can only ever shorten a
51
+ * history list, never make a number wrong.
52
+ */
53
+ const ATTEMPT_LIMIT = 2000;
54
+ /**
55
+ * Two timestamp shapes live in this database and both have to parse.
56
+ * `attempts.ts` defaults to SQLite's `2026-09-05 21:04:00` — UTC, no zone
57
+ * marker, which `Date.parse` would read as local time — while `next_review` is
58
+ * a JS ISO string that already carries its `Z`. Appending one unconditionally
59
+ * produced `...ZZ`, which parses to NaN, and every overdue count came out zero.
60
+ */
61
+ const parseTs = (s) => Date.parse(/([zZ]|[+-]\d\d:?\d\d)$/.test(s) ? s : s.replace(' ', 'T') + 'Z');
62
+ const days = (from, now) => {
63
+ if (from === null)
64
+ return null;
65
+ const t = parseTs(from);
66
+ return Number.isFinite(t) ? Math.floor((now.getTime() - t) / MS_PER_DAY) : null;
67
+ };
68
+ function readConfig() {
69
+ // A dashboard must open even if the config file is half-written or owned by
70
+ // another user; the defaults describe the same product.
71
+ try {
72
+ return loadConfig().config;
73
+ }
74
+ catch {
75
+ return DEFAULT_CONFIG;
76
+ }
77
+ }
33
78
  export function dashboardState(db) {
34
79
  const now = new Date();
35
- // One row per calendar day, split three ways. `grade >= 3` is the same pass
36
- // line the level ladder uses, so the chart and the promotion agree.
37
- const timeline = db
80
+ const config = readConfig();
81
+ // One row per calendar day per project, split three ways. `grade >= 3` is the
82
+ // same pass line the level ladder uses, so the chart and the promotion agree.
83
+ const daily = db
38
84
  .prepare(`SELECT date(ts) AS day,
39
85
  NULLIF(trim(COALESCE(repo, '')), '') AS repo,
40
- sum(CASE WHEN grade >= 3 THEN 1 ELSE 0 END) AS passed,
41
- sum(CASE WHEN grade < 3 AND (outcome IS NULL OR outcome = 'answered') THEN 1 ELSE 0 END) AS missed,
86
+ sum(CASE WHEN grade >= ? THEN 1 ELSE 0 END) AS passed,
87
+ sum(CASE WHEN grade < ? AND (outcome IS NULL OR outcome = 'answered') THEN 1 ELSE 0 END) AS missed,
42
88
  sum(CASE WHEN outcome IN ('declined','dont_know') THEN 1 ELSE 0 END) AS skipped
43
89
  FROM attempts
44
90
  WHERE ts >= date('now', ?)
45
91
  GROUP BY day, repo
46
92
  ORDER BY day`)
47
- .all(`-${TIMELINE_DAYS} days`);
93
+ .all(PASSING_GRADE, PASSING_GRADE, `-${TIMELINE_DAYS} days`);
48
94
  // A null repo is the pre-migration-003 bucket. It is kept, not dropped:
49
95
  // hiding those rows would silently shrink every total on the page.
50
96
  const projects = db
51
97
  .prepare(`SELECT NULLIF(trim(COALESCE(a.repo, '')), '') AS repo,
52
98
  count(*) AS answers,
53
- sum(CASE WHEN a.grade >= 3 THEN 1 ELSE 0 END) AS passed,
99
+ sum(CASE WHEN a.grade >= ? THEN 1 ELSE 0 END) AS passed,
54
100
  sum(CASE WHEN a.outcome IN ('declined','dont_know') THEN 1 ELSE 0 END) AS skipped,
55
101
  count(DISTINCT a.concept_id) AS concepts,
102
+ min(a.ts) AS first_active,
56
103
  max(a.ts) AS last_active
57
104
  FROM attempts a
58
105
  GROUP BY repo
59
106
  ORDER BY last_active DESC`)
60
- .all();
61
- const levels = new Map(db.prepare('SELECT repo, level, promoted_at FROM project_levels').all().map((r) => [r.repo, r]));
107
+ .all(PASSING_GRADE);
62
108
  const conceptRows = db
63
- .prepare(`SELECT c.slug, c.name, c.domain, c.tier,
64
- m.score, m.reps, m.next_review, m.last_seen,
109
+ .prepare(`SELECT c.id, c.slug, c.name, c.domain, c.description, c.tier, c.source,
110
+ m.score, m.ease, m.interval_d, m.reps, m.next_review, m.last_seen,
65
111
  (SELECT count(*) FROM attempts a WHERE a.concept_id = c.id) AS attempts,
112
+ (SELECT count(*) FROM attempts a WHERE a.concept_id = c.id AND a.grade >= ${PASSING_GRADE}) AS passed,
113
+ (SELECT count(*) FROM attempts a WHERE a.concept_id = c.id
114
+ AND a.outcome IN ('declined','dont_know')) AS skipped,
115
+ (SELECT min(a.ts) FROM attempts a WHERE a.concept_id = c.id) AS first_asked,
66
116
  (SELECT a.grade FROM attempts a WHERE a.concept_id = c.id ORDER BY a.id DESC LIMIT 1) AS last_grade,
67
117
  (SELECT sc.context FROM session_concepts sc
68
118
  WHERE sc.concept_id = c.id AND sc.context IS NOT NULL
@@ -71,95 +121,211 @@ export function dashboardState(db) {
71
121
  WHERE a.concept_id = c.id AND a.repo IS NOT NULL AND trim(a.repo) <> ''
72
122
  ORDER BY a.id DESC LIMIT 1) AS last_repo
73
123
  FROM concepts c
74
- LEFT JOIN mastery m ON m.concept_id = c.id`)
124
+ LEFT JOIN mastery m ON m.concept_id = c.id
125
+ ORDER BY c.domain, c.tier, c.name`)
75
126
  .all();
76
- const domains = new Map();
77
- const concepts = [];
78
- for (const row of conceptRows) {
79
- const bucket = domains.get(row.domain) ?? { domain: row.domain, mastered: 0, learning: 0, unseen: 0 };
80
- domains.set(row.domain, bucket);
81
- if (row.attempts === 0) {
82
- bucket.unseen += 1;
127
+ const byId = new Map(conceptRows.map((r) => [r.id, r.slug]));
128
+ // Edges travel as slugs so the page can link one concept card to another
129
+ // without carrying the id space around with it.
130
+ const edgeRows = db
131
+ .prepare('SELECT from_concept, to_concept, relation FROM edges')
132
+ .all();
133
+ const prereqs = new Map();
134
+ const unlocks = new Map();
135
+ const related = new Map();
136
+ const push = (m, k, v) => m.set(k, [...(m.get(k) ?? []), v]);
137
+ for (const e of edgeRows) {
138
+ const from = byId.get(e.from_concept);
139
+ const to = byId.get(e.to_concept);
140
+ if (!from || !to)
83
141
  continue;
142
+ if (e.relation === 'prerequisite_of') {
143
+ push(prereqs, to, from);
144
+ push(unlocks, from, to);
84
145
  }
146
+ else {
147
+ push(related, from, to);
148
+ push(related, to, from);
149
+ }
150
+ }
151
+ const domains = new Map();
152
+ const concepts = conceptRows.map((row) => {
153
+ const bucket = domains.get(row.domain) ?? {
154
+ domain: row.domain,
155
+ catalogue: 0,
156
+ touched: 0,
157
+ mastered: 0,
158
+ learning: 0,
159
+ unseen: 0,
160
+ };
161
+ domains.set(row.domain, bucket);
162
+ bucket.catalogue += 1;
85
163
  // Read-time decay only, exactly as the profile computes it — two surfaces
86
164
  // disagreeing about the same score is worse than either being wrong.
87
165
  const score = decayedScore(row.score ?? 0, row.next_review, now);
88
- const mastered = isKnown({ score, reps: row.reps ?? 0 });
89
- if (mastered)
90
- bucket.mastered += 1;
91
- else
92
- bucket.learning += 1;
93
- concepts.push({
166
+ const seen = row.attempts > 0;
167
+ const mastered = seen && isKnown({ score, reps: row.reps ?? 0 });
168
+ if (!seen)
169
+ bucket.unseen += 1;
170
+ else {
171
+ bucket.touched += 1;
172
+ if (mastered)
173
+ bucket.mastered += 1;
174
+ else
175
+ bucket.learning += 1;
176
+ }
177
+ const due = seen && isDue(row.next_review, now);
178
+ return {
94
179
  slug: row.slug,
95
180
  name: row.name,
96
181
  domain: row.domain,
182
+ description: row.description,
97
183
  tier: row.tier,
98
- score: Number(score.toFixed(2)),
184
+ source: row.source,
185
+ seen,
186
+ score: Number(score.toFixed(4)),
187
+ // The stored score, so a decayed concept can say how much of its score is
188
+ // rust rather than failure.
189
+ stored_score: Number((row.score ?? 0).toFixed(4)),
190
+ ease: row.ease ?? null,
191
+ interval_d: row.interval_d ?? 0,
99
192
  reps: row.reps ?? 0,
100
193
  attempts: row.attempts,
194
+ passed: row.passed,
195
+ skipped: row.skipped,
101
196
  last_grade: row.last_grade,
102
197
  mastered,
103
- due: isDue(row.next_review, now),
198
+ due,
199
+ overdue_days: due ? days(row.next_review, now) : null,
104
200
  next_review: row.next_review,
105
201
  last_seen: row.last_seen,
202
+ first_asked: row.first_asked,
106
203
  context: row.last_context,
107
204
  repo: row.last_repo,
108
- });
109
- }
110
- concepts.sort((a, b) => a.score - b.score);
111
- const skipped = db
112
- .prepare(`SELECT c.slug AS slug, c.name AS name, c.domain AS domain,
113
- a.outcome AS outcome, a.repo AS repo, a.ts AS ts, a.question AS question
205
+ prereqs: prereqs.get(row.slug) ?? [],
206
+ unlocks: unlocks.get(row.slug) ?? [],
207
+ related: related.get(row.slug) ?? [],
208
+ };
209
+ });
210
+ // Every graded response, newest first, with its question and the tutor's
211
+ // explanation. This is what makes a concept page a record of what you were
212
+ // actually asked rather than a score.
213
+ const attempts = db
214
+ .prepare(`SELECT a.id, c.slug, c.name, c.domain, a.session_id, a.question, a.answer, a.feedback,
215
+ a.grade, a.difficulty AS tier, a.outcome, a.format, a.options, a.ts,
216
+ NULLIF(trim(COALESCE(a.repo, '')), '') AS repo, a.level
114
217
  FROM attempts a JOIN concepts c ON c.id = a.concept_id
115
- WHERE a.outcome IN ('declined','dont_know')
116
- ORDER BY a.ts DESC`)
117
- .all();
118
- const recent = db
119
- .prepare(`SELECT c.slug AS slug, c.domain AS domain, sc.context AS context, sc.ts AS ts, g.repo AS repo
218
+ ORDER BY a.id DESC
219
+ LIMIT ?`)
220
+ .all(ATTEMPT_LIMIT);
221
+ // The context lines, which are what a concept means to *this* learner: the
222
+ // code that taught it. Grouped by session on the page.
223
+ const logged = db
224
+ .prepare(`SELECT sc.session_id, c.slug, c.name, c.domain, sc.context, sc.ts, sc.origin,
225
+ NULLIF(trim(COALESCE(g.repo, '')), '') AS repo
120
226
  FROM session_concepts sc
121
227
  JOIN concepts c ON c.id = sc.concept_id
122
228
  LEFT JOIN gates g ON g.session_id = sc.session_id
123
- WHERE sc.context IS NOT NULL AND trim(sc.context) <> ''
124
- ORDER BY sc.ts DESC
125
- LIMIT 40`)
229
+ ORDER BY sc.ts DESC`)
126
230
  .all();
127
- const totals = timeline.reduce((acc, d) => ({
128
- passed: acc.passed + d.passed,
129
- missed: acc.missed + d.missed,
130
- skipped: acc.skipped + d.skipped,
131
- }), { passed: 0, missed: 0, skipped: 0 });
132
231
  const allTime = db
133
232
  .prepare(`SELECT count(*) AS answers,
134
- sum(CASE WHEN grade >= 3 THEN 1 ELSE 0 END) AS passed,
135
- sum(CASE WHEN outcome IN ('declined','dont_know') THEN 1 ELSE 0 END) AS skipped
233
+ sum(CASE WHEN grade >= ? THEN 1 ELSE 0 END) AS passed,
234
+ sum(CASE WHEN grade < ? AND (outcome IS NULL OR outcome = 'answered') THEN 1 ELSE 0 END) AS missed,
235
+ sum(CASE WHEN outcome IN ('declined','dont_know') THEN 1 ELSE 0 END) AS skipped,
236
+ count(DISTINCT date(ts)) AS active_days,
237
+ min(ts) AS first_answer
136
238
  FROM attempts`)
137
- .get();
239
+ .get(PASSING_GRADE, PASSING_GRADE);
240
+ const sessionCount = db.prepare('SELECT count(DISTINCT session_id) AS n FROM session_concepts').get().n;
138
241
  return {
139
242
  generated_at: now.toISOString(),
243
+ db_path: dbPath(),
140
244
  timeline_days: TIMELINE_DAYS,
245
+ attempts_shown: attempts.length,
246
+ attempts_total: allTime.answers,
247
+ config: {
248
+ mode: config.mode,
249
+ focus: config.focus,
250
+ focus_topic: config.focus_topic,
251
+ cadence: config.cadence,
252
+ difficulty: config.difficulty,
253
+ pass_threshold: config.pass_threshold,
254
+ level_up_after: config.level_up_after,
255
+ level_up_accuracy: config.level_up_accuracy,
256
+ max_questions_per_task: config.max_questions_per_task,
257
+ },
141
258
  totals: {
142
259
  answers: allTime.answers,
143
260
  passed: allTime.passed ?? 0,
261
+ missed: allTime.missed ?? 0,
144
262
  skipped: allTime.skipped ?? 0,
145
263
  mastered: concepts.filter((c) => c.mastered).length,
146
264
  due: concepts.filter((c) => c.due).length,
147
- touched: concepts.length,
265
+ touched: concepts.filter((c) => c.seen).length,
148
266
  catalogue: conceptRows.length,
149
- window: totals,
267
+ sessions: sessionCount,
268
+ active_days: allTime.active_days,
269
+ first_answer: allTime.first_answer,
150
270
  },
151
- timeline,
152
- projects: projects.map((p) => ({
153
- ...p,
154
- level: levels.get(p.repo ?? GLOBAL_PROJECT)?.level ?? 'easy',
155
- promoted_at: levels.get(p.repo ?? GLOBAL_PROJECT)?.promoted_at ?? null,
156
- })),
157
- domains: [...domains.values()].sort((a, b) => b.mastered + b.learning - (a.mastered + a.learning)),
271
+ daily,
272
+ projects: projects.map((p) => {
273
+ // The promotion runway, said out loud rather than hinted at — the same
274
+ // numbers `/eklavya:progress` prints, so the two never disagree.
275
+ const standing = levelStanding(db, config, p.repo);
276
+ return {
277
+ ...p,
278
+ key: p.repo ?? GLOBAL_PROJECT,
279
+ level: standing.level,
280
+ pinned: standing.pinned,
281
+ promoted_at: standing.entered_at,
282
+ next_level: standing.next,
283
+ level_counts: standing.counts,
284
+ level_accuracy: standing.accuracy,
285
+ level_needed: standing.needed,
286
+ level_unmet: standing.unmet,
287
+ };
288
+ }),
289
+ domains: [...domains.values()].sort((a, b) => b.touched - a.touched || b.catalogue - a.catalogue),
158
290
  concepts,
159
- skipped,
160
- recent,
291
+ attempts,
292
+ logged,
161
293
  };
162
294
  }
295
+ /**
296
+ * The platform's URL opener, as a command and its arguments.
297
+ *
298
+ * The empty string before the URL on Windows is load-bearing: `start <url>`
299
+ * reads its first quoted argument as the new window's *title*, so a URL passed
300
+ * alone can be swallowed as one. `start "" <url>` is the documented shape.
301
+ */
302
+ export function browserCommand(url, platform = process.platform) {
303
+ if (platform === 'darwin')
304
+ return ['open', [url]];
305
+ if (platform === 'win32')
306
+ return ['cmd', ['/c', 'start', '', url]];
307
+ return ['xdg-open', [url]];
308
+ }
309
+ /**
310
+ * Hands the URL to whatever the OS considers the browser.
311
+ *
312
+ * Best effort, and deliberately silent when it fails: a container, a bare SSH
313
+ * session or a machine with no desktop has no browser to hand it to, and the
314
+ * URL is on stdout for those. Detached and unref'd so the opener's lifetime is
315
+ * not tied to this process — `xdg-open` can outlive the launch by seconds, and
316
+ * a child still attached would hold the terminal after Ctrl+C.
317
+ */
318
+ export function openInBrowser(url) {
319
+ try {
320
+ const [cmd, args] = browserCommand(url);
321
+ const child = spawn(cmd, args, { stdio: 'ignore', detached: true });
322
+ child.on('error', () => { });
323
+ child.unref();
324
+ }
325
+ catch {
326
+ // Nothing to do: the URL is printed either way.
327
+ }
328
+ }
163
329
  function send(res, status, type, body) {
164
330
  res.writeHead(status, {
165
331
  'content-type': type,
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eklavya",
3
3
  "displayName": "Eklavya",
4
- "version": "1.9.4",
4
+ "version": "1.11.0",
5
5
  "description": "Learn while your agent works. Turns coding-agent generation time into adaptive, Socratic learning grounded in the code being written.",
6
6
  "author": {
7
7
  "name": "Ajay Kumar"
@@ -43,7 +43,8 @@ Finish with **one** concrete next step: `/eklavya:quiz` when anything is due,
43
43
  mostly unseen.
44
44
 
45
45
  Then one line pointing at `eklavya dashboard` — the same data as a local page,
46
- with the history and the full concept list this report deliberately truncates.
46
+ with the history, the per-session record and every question ever asked on a
47
+ concept, all of which this report deliberately truncates.
47
48
  Mention it once, at the end; it is the deeper view, not a replacement for
48
49
  answering the question they just asked.
49
50
 
@@ -287,13 +287,15 @@ A pinned level (`pinned: true`) means someone set the band deliberately — an o
287
287
  Every plan item carries `ask_header`: one bracketed line naming the settings that asked the question.
288
288
 
289
289
  ```
290
- [ambient · concept · easy · tier 2 mechanism · q 1/3]
290
+ [mode: ambient · focus: concept · level: easy · tier: 2 mechanism · question: 1 of 3]
291
291
 
292
292
  Why is httpOnly set on the refresh cookie here but not on the access token?
293
293
  ```
294
294
 
295
- Mode, focus, level, what the tier is asking for, and — when the plan holds more
296
- than one — which question of how many this is.
295
+ Every part names its dial: mode, focus, level, what the tier is asking for, and
296
+ — when the plan holds more than one — which question of how many this is. The
297
+ labels are the point. Four bare values only read as a settings line to someone
298
+ who already knows there are four dials and what order they come in.
297
299
 
298
300
  **Print it as the first line of the `question` you pass to `AskUserQuestion`**, then a blank line, then the stem, exactly as given. It is the only thing on screen that explains why a question is pitched where it is — without it, a `concept`-focus question reads as vague and an `easy` question reads as shallow.
299
301
 
@@ -103,8 +103,9 @@ eklavya db-path # where the learning history lives
103
103
  ## The dashboard
104
104
 
105
105
  ```bash
106
- eklavya dashboard # http://127.0.0.1:41729
106
+ eklavya dashboard # opens http://127.0.0.1:41729 in their browser
107
107
  eklavya dashboard --port 8080
108
+ eklavya dashboard --no-open # serve it, print the URL, open nothing
108
109
  ```
109
110
 
110
111
  It binds to loopback only and reads the local database — that is the whole
@@ -112,6 +113,22 @@ security model, and it is worth saying when someone asks where their data
112
113
  goes. The process runs until interrupted, so start it in the background and
113
114
  hand back the URL rather than blocking the session on it.
114
115
 
116
+ It opens the browser itself, so do not tell them to click the URL. Use
117
+ `--no-open` when they only asked *where* the dashboard is, or when the session
118
+ is on a machine with no desktop.
119
+
120
+ Six sections, each deep-linkable — hand back the one that answers what was
121
+ actually asked rather than the bare root:
122
+
123
+ | Ask | Link |
124
+ |---|---|
125
+ | how am I doing, streaks, activity | `/#/overview` |
126
+ | what am I learning, search a concept | `/#/concepts` (or `/#/concepts/due`, `/mastered`, `/unseen`), `/#/concept/<slug>` for one |
127
+ | what is due, what is scheduled, what I skipped | `/#/review`, `/#/review/upcoming`, `/#/review/skipped` |
128
+ | what did that session teach me | `/#/sessions` |
129
+ | how hard is this repo allowed to get | `/#/projects` |
130
+ | where are the gaps | `/#/domains` |
131
+
115
132
  ## When the plugin is loaded, point at the commands
116
133
 
117
134
  These do more than this skill should reimplement. Name the one that fits and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eklavya",
3
- "version": "1.9.4",
3
+ "version": "1.11.0",
4
4
  "description": "Learn while your agent works — local knowledge graph, spaced repetition, and quiz gating for agent-assisted development.",
5
5
  "license": "MIT",
6
6
  "repository": {