eklavya 1.27.0 → 1.27.1
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.
- package/README.md +48 -42
- package/dist/artifacts.js +2 -2
- package/dist/artifacts.js.map +1 -1
- package/dist/assets/artifact-template.html +2 -2
- package/dist/assets/dashboard.html +12 -9
- package/dist/assets/tokens.css +6 -4
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/agents/explainer.md +5 -3
- package/dist/plugin/cli/CLAUDE.md +60 -108
- package/dist/plugin/hooks/CLAUDE.md +118 -369
- package/dist/plugin/skills/CLAUDE.md +106 -298
- package/dist/user-skill/eklavya-artifacts/SKILL.md +23 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Eklavya
|
|
2
2
|
|
|
3
|
-
[Eklavya](https://github.com/ProjectAJ14/eklavya)
|
|
4
|
-
|
|
3
|
+
[Eklavya](https://github.com/ProjectAJ14/eklavya) teaches the concepts behind
|
|
4
|
+
agent-written code and keeps local project memory. This package includes the
|
|
5
|
+
Claude Code plugin, installer, CLI and MCP server.
|
|
5
6
|
|
|
6
|
-
## Install
|
|
7
|
+
## Install in Claude Code
|
|
8
|
+
|
|
9
|
+
With Node 22 or newer:
|
|
7
10
|
|
|
8
11
|
```bash
|
|
9
12
|
npx eklavya install
|
|
10
13
|
```
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
is how you upgrade; `npx eklavya uninstall` removes it and keeps your history unless you pass
|
|
16
|
-
`--purge`.
|
|
15
|
+
Follow the settings prompts, then restart Claude Code. The installer registers
|
|
16
|
+
the plugin, installs the managed runtime and chat/artifact skills, and prepares
|
|
17
|
+
local storage. `/eklavya:setup` lets you revisit settings.
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
Read the [installation guide](https://eklavya-run.web.app/docs/installing/) for
|
|
20
|
+
verification and [updates and removal](https://eklavya-run.web.app/docs/updates/)
|
|
21
|
+
for maintenance. Uninstall preserves learner data unless you explicitly use
|
|
22
|
+
`--purge`.
|
|
20
23
|
|
|
21
|
-
##
|
|
24
|
+
## Standalone MCP connection
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
editor-agnostic.
|
|
26
|
+
An MCP client can connect directly:
|
|
25
27
|
|
|
26
28
|
```json
|
|
27
29
|
{
|
|
@@ -31,41 +33,45 @@ editor-agnostic.
|
|
|
31
33
|
}
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
This exposes tools. Automatic capture, checkpoints and session instructions
|
|
37
|
+
depend on host integration; an MCP connection alone does not provide Claude
|
|
38
|
+
Code's learning loop.
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
## Available tools
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
| Tool | Purpose |
|
|
42
|
+
| Purpose | Tools |
|
|
43
43
|
|---|---|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
| `get_concept_graph` | a domain in prerequisite order |
|
|
51
|
-
| `get_config` / `set_config` | global and per-repo settings |
|
|
44
|
+
| Learner state and concepts | `get_learner_profile`, `log_session_concepts`, `upsert_concepts`, `get_concept_graph` |
|
|
45
|
+
| Questions and assessment | `get_session_quiz_plan`, `record_attempt`, `get_gate_status` |
|
|
46
|
+
| Settings | `get_config`, `set_config` |
|
|
47
|
+
| Find and read memory | `memory_search`, `memory_get`, `memory_timeline`, `memory_file_history`, `memory_status` |
|
|
48
|
+
| Maintain memory | `memory_write`, `memory_correct`, `memory_delete`, `memory_collections` |
|
|
49
|
+
| Inspect code | `code_outline`, `code_find_symbol` |
|
|
52
50
|
|
|
53
|
-
|
|
51
|
+
Search first, choose relevant entries, then use `memory_get` for their full
|
|
52
|
+
content. Session-aware learning and configuration tools resolve the current session
|
|
53
|
+
when `session_id` is omitted. In `memory_timeline`, it instead filters results
|
|
54
|
+
to one session; omission shows the project timeline. Other tools may not accept
|
|
55
|
+
that argument.
|
|
54
56
|
|
|
55
|
-
## CLI
|
|
57
|
+
## CLI and data
|
|
56
58
|
|
|
57
59
|
```bash
|
|
58
|
-
eklavya
|
|
59
|
-
eklavya
|
|
60
|
-
eklavya
|
|
61
|
-
eklavya
|
|
62
|
-
eklavya
|
|
63
|
-
eklavya config set focus concept # what it teaches
|
|
64
|
-
eklavya config set focus learn --topic caching
|
|
65
|
-
eklavya export-rules --out rules.md # the tutor pedagogy as Markdown
|
|
66
|
-
eklavya dashboard [--port <n>] [--no-open] # your learning history, served locally and opened
|
|
67
|
-
# in your browser (--no-open just prints the URL)
|
|
68
|
-
eklavya db-path
|
|
60
|
+
npx eklavya doctor
|
|
61
|
+
npx eklavya memory status
|
|
62
|
+
npx eklavya config get
|
|
63
|
+
npx eklavya dashboard
|
|
64
|
+
npx eklavya db-path
|
|
69
65
|
```
|
|
70
66
|
|
|
67
|
+
The [CLI reference](https://eklavya-run.web.app/docs/cli/) lists all commands and
|
|
68
|
+
flags. [Configuration](https://eklavya-run.web.app/docs/configuration/) lists
|
|
69
|
+
defaults and scopes. The [memory guide](https://eklavya-run.web.app/docs/memory/)
|
|
70
|
+
covers retrieval, processing, providers, privacy and sync.
|
|
71
|
+
|
|
72
|
+
State is local under `~/.eklavya/`, including `knowledge.db` (SQLite, WAL).
|
|
73
|
+
`EKLAVYA_HOME` and `EKLAVYA_DB` override those paths. Questions and memory have
|
|
74
|
+
independent switches. External processing is optional and explicitly configured;
|
|
75
|
+
see [your data](https://eklavya-run.web.app/docs/your-data/).
|
|
76
|
+
|
|
71
77
|
MIT.
|
package/dist/artifacts.js
CHANGED
|
@@ -64,8 +64,8 @@ function inlineTokens() {
|
|
|
64
64
|
return css.replace(/@import\s+url\([^)]*\)[^;]*;\s*/gi, '');
|
|
65
65
|
}
|
|
66
66
|
catch {
|
|
67
|
-
// A build without the tokens still
|
|
68
|
-
//
|
|
67
|
+
// A build without the tokens still writes the page; it renders unstyled
|
|
68
|
+
// until the tokens are restored, rather than failing the command.
|
|
69
69
|
return '';
|
|
70
70
|
}
|
|
71
71
|
}
|
package/dist/artifacts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE/D,4EAA4E;AAC5E,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC;AAiB7B,kGAAkG;AAClG,MAAM,UAAU,eAAe,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACzD,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,QAAQ;QAAE,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,KAAa;IACjC,MAAM,CAAC,GAAG,KAAK;SACZ,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtB,OAAO,CAAC,IAAI,UAAU,CAAC;AACzB,CAAC;AAED,MAAM,OAAO,GAAG,CAAC,CAAS,EAAE,EAAE,CAC5B,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;AAE9G,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,6FAA6F;AAC7F,SAAS,YAAY;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7D,OAAO,GAAG,CAAC,OAAO,CAAC,mCAAmC,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
/*{{TOKENS}}*/
|
|
21
21
|
</style>
|
|
22
22
|
<style>
|
|
23
|
-
:root{ --
|
|
23
|
+
:root{ --maxw:880px; }
|
|
24
24
|
|
|
25
25
|
*{box-sizing:border-box}
|
|
26
26
|
body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.65 var(--font-body)}
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
border:1px solid var(--line-2);border-radius:0;background:var(--panel);color:var(--ink);
|
|
81
81
|
font:500 12px var(--font-mono);letter-spacing:.06em;cursor:pointer}
|
|
82
82
|
.actions button:hover{border-color:var(--spot);color:var(--spot)}
|
|
83
|
-
.actions button:focus-visible{outline:none;box-shadow:
|
|
83
|
+
.actions button:focus-visible{outline:none;box-shadow:var(--ring)}
|
|
84
84
|
|
|
85
85
|
@media screen{
|
|
86
86
|
body{background-image:linear-gradient(var(--grid) 1px,transparent 1px),
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
the viewport, so it never opens off-screen on a phone or a short window. */
|
|
98
98
|
.picker { position:fixed; z-index:40; min-width:220px; max-width:calc(100vw - 16px);
|
|
99
99
|
background:var(--panel); border:1px solid var(--line-2); padding:var(--space-1) 0;
|
|
100
|
-
box-shadow:
|
|
100
|
+
box-shadow:var(--shadow-lg); overflow-y:auto; }
|
|
101
101
|
.picker[hidden] { display:none; }
|
|
102
102
|
.picker__label { font-family:var(--font-mono); font-size:10px; letter-spacing:var(--tracking-caps);
|
|
103
103
|
text-transform:uppercase; color:var(--faint); padding:var(--space-2) var(--space-4) var(--space-1); margin:0; }
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
background:none; border:0; color:var(--dim); font:inherit; font-size:14px;
|
|
106
106
|
padding:var(--space-2) var(--space-4); cursor:pointer; }
|
|
107
107
|
.picker button:hover, .picker button:focus-visible { background:var(--mass); color:var(--ink); box-shadow:none; outline:none; }
|
|
108
|
-
.picker button:focus-visible { box-shadow:inset 2px 0 0 var(--spot); }
|
|
108
|
+
.picker button:focus-visible { box-shadow:inset 2px 0 0 var(--spot); } /* inset: the picker scrolls, so an outset ring would clip */
|
|
109
109
|
.picker button[aria-checked="true"] { color:var(--ink); }
|
|
110
110
|
.picker button span { flex:1; }
|
|
111
111
|
.picker .check { width:15px; height:15px; color:var(--spot); visibility:hidden; }
|
|
@@ -119,6 +119,8 @@
|
|
|
119
119
|
transition:color var(--duration-fast) var(--ease), background var(--duration-fast) var(--ease); }
|
|
120
120
|
nav.side__nav a:hover { color:var(--ink); background:var(--mass); }
|
|
121
121
|
nav.side__nav a[aria-current="page"] { color:var(--ink); border-left-color:var(--spot); background:var(--mass); }
|
|
122
|
+
/* --faint misses 4.5:1 on --mass in ink */
|
|
123
|
+
nav.side__nav a[aria-current="page"] i, nav.side__nav a:hover i { color:var(--dim); }
|
|
122
124
|
nav.side__nav a svg { width:17px; height:17px; flex:none; color:var(--faint); }
|
|
123
125
|
nav.side__nav a[aria-current="page"] svg { color:var(--spot); }
|
|
124
126
|
nav.side__nav a i { margin-left:auto; font-style:normal; font-family:var(--font-mono);
|
|
@@ -266,10 +268,10 @@
|
|
|
266
268
|
.meter.mute > i { background:var(--faint-2); }
|
|
267
269
|
|
|
268
270
|
.pill { display:inline-block; font-family:var(--font-mono); font-size:11px; padding:2px 8px;
|
|
269
|
-
border-radius:
|
|
271
|
+
border-radius:0; background:var(--mass); color:var(--dim); white-space:nowrap; }
|
|
270
272
|
.pill.ok { background:var(--spot-soft); color:var(--spot); }
|
|
271
273
|
.pill.due { color:var(--warning); }
|
|
272
|
-
.pill.new { color:var(--
|
|
274
|
+
.pill.new { color:var(--dim); }
|
|
273
275
|
|
|
274
276
|
.grade { font-family:var(--font-mono); font-size:11.5px; padding:2px 8px; white-space:nowrap;
|
|
275
277
|
background:var(--mass); color:var(--dim); }
|
|
@@ -286,7 +288,7 @@
|
|
|
286
288
|
.seg > span { display:block; height:100%; }
|
|
287
289
|
.seg__key { display:flex; gap:var(--space-5); flex-wrap:wrap; margin-top:var(--space-3);
|
|
288
290
|
font-size:12.5px; color:var(--dim); }
|
|
289
|
-
.seg__key b { display:inline-block; width:9px; height:9px; margin-right:var(--space-2); }
|
|
291
|
+
.seg__key b { display:inline-block; width:9px; height:9px; margin-right:var(--space-2); border:1px solid var(--line-2); }
|
|
290
292
|
|
|
291
293
|
/* ---------- charts ---------- */
|
|
292
294
|
.legend { display:flex; gap:var(--space-5); font-size:12.5px; color:var(--dim);
|
|
@@ -298,6 +300,7 @@
|
|
|
298
300
|
.axis { font-family:var(--font-mono); font-size:10px; fill:var(--faint); }
|
|
299
301
|
.hit { fill:transparent; cursor:pointer; }
|
|
300
302
|
.hit:hover + .col, .hit:focus-visible + .col { opacity:.72; }
|
|
303
|
+
.hit:focus-visible { outline:2px solid var(--spot); outline-offset:-2px; }
|
|
301
304
|
.tip { position:absolute; pointer-events:none; opacity:0; transform:translate(-50%,-100%);
|
|
302
305
|
background:var(--bg); border:1px solid var(--line-2); color:var(--ink);
|
|
303
306
|
padding:var(--space-3); font-size:var(--text-xs); line-height:1.6; white-space:nowrap;
|
|
@@ -393,7 +396,7 @@
|
|
|
393
396
|
background:none; border:1px solid var(--line-2); color:var(--ink); width:34px; height:34px; cursor:pointer; }
|
|
394
397
|
.side__close svg { width:16px; height:16px; }
|
|
395
398
|
.side__brand { padding-right:64px; }
|
|
396
|
-
.scrim { position:fixed; inset:0; z-index:25; background:
|
|
399
|
+
.scrim { position:fixed; inset:0; z-index:25; background:color-mix(in srgb, var(--bg) 70%, transparent); }
|
|
397
400
|
.scrim.is-open { display:block; }
|
|
398
401
|
body.drawer-open { overflow:hidden; }
|
|
399
402
|
main { padding:var(--space-6) var(--space-5) var(--space-16); }
|
|
@@ -1119,7 +1122,7 @@ function viewLearningDashboard() {
|
|
|
1119
1122
|
${card('Where you stand', 'The catalogue is a library, not a to-do list — untouched concepts are not debt.',
|
|
1120
1123
|
segbar([
|
|
1121
1124
|
{ label:'Mastered', n:mastered.length, color:'var(--spot)' },
|
|
1122
|
-
{ label:'Learning', n:seen.length - mastered.length, color:'var(--
|
|
1125
|
+
{ label:'Learning', n:seen.length - mastered.length, color:'color-mix(in srgb, var(--spot) 45%, var(--mass))' },
|
|
1123
1126
|
{ label:'Not asked', n:Math.max(0, scoped.length - seen.length), color:'var(--mass)' },
|
|
1124
1127
|
]) + `<p style="margin:var(--space-4) 0 0;color:var(--faint);font-size:13.5px">
|
|
1125
1128
|
A concept is mastered at score 0.7 with two or more passes. Score decays about
|
|
@@ -1699,7 +1702,7 @@ function viewDomain(name) {
|
|
|
1699
1702
|
</div>`,
|
|
1700
1703
|
card(null, null, segbar([
|
|
1701
1704
|
{ label:'Mastered', n:seen.filter((c) => c.mastered).length, color:'var(--spot)' },
|
|
1702
|
-
{ label:'Learning', n:seen.filter((c) => !c.mastered).length, color:'var(--
|
|
1705
|
+
{ label:'Learning', n:seen.filter((c) => !c.mastered).length, color:'color-mix(in srgb, var(--spot) 45%, var(--mass))' },
|
|
1703
1706
|
{ label:'Not asked', n:all.length - seen.length, color:'var(--mass)' },
|
|
1704
1707
|
])),
|
|
1705
1708
|
card(null, null, table([{t:'Concept'},{t:'Tier'},{t:'Score'},{t:'Asked',n:1},{t:'State'},{t:'From your code'}], rows)
|
|
@@ -2497,7 +2500,7 @@ function renderNav(wf, active) {
|
|
|
2497
2500
|
const id = `grp-${wf}-${g.id}`;
|
|
2498
2501
|
return `<div class="nav__group">
|
|
2499
2502
|
<button type="button" class="nav__toggle" id="tog-${wf}-${g.id}" data-group="${g.id}" aria-expanded="${open}" aria-controls="${id}">
|
|
2500
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>${esc(g.label)}
|
|
2503
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>${esc(g.label)}
|
|
2501
2504
|
</button>
|
|
2502
2505
|
<div class="nav__items" id="${id}" role="group" aria-label="${esc(g.label)}"${open ? '' : ' hidden'}>${g.items.map(item).join('')}</div>
|
|
2503
2506
|
</div>`;
|
package/dist/assets/tokens.css
CHANGED
|
@@ -40,10 +40,9 @@
|
|
|
40
40
|
--vd-900: #052E2B;
|
|
41
41
|
|
|
42
42
|
/* ---------- SEMANTIC (real errors and warnings only) ----------
|
|
43
|
-
Kept off the accent hue so state never reads as branding.
|
|
44
|
-
redefined per ground below: an orange that carries on ink is
|
|
45
|
-
cream, which fails as text and as a chart fill alike. */
|
|
46
|
-
--error: #E5484D;
|
|
43
|
+
Kept off the accent hue so state never reads as branding. --warning and
|
|
44
|
+
--error are redefined per ground below: an orange that carries on ink is
|
|
45
|
+
2.3:1 on cream, which fails as text and as a chart fill alike. */
|
|
47
46
|
--info: #4A9EFF;
|
|
48
47
|
|
|
49
48
|
/* ---------- TYPE FAMILIES ----------
|
|
@@ -144,6 +143,7 @@
|
|
|
144
143
|
--glow-low: rgba(25,150,136,.10);
|
|
145
144
|
--shot-op: .28; /* the arrow scene, as ambient art */
|
|
146
145
|
--warning: #E8920C;
|
|
146
|
+
--error: #FF6166; /* 4.82:1 on its own 12% tint over --panel */
|
|
147
147
|
--code-bg: var(--mass); /* the well behind a code block */
|
|
148
148
|
--shadow-lg: 0 12px 28px rgba(0,0,0,.45);
|
|
149
149
|
--ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--spot);
|
|
@@ -173,6 +173,7 @@
|
|
|
173
173
|
--glow-low: rgba(14,110,102,.05);
|
|
174
174
|
--shot-op: .5;
|
|
175
175
|
--warning: #7A4B00; /* 5.21:1 on --mass */
|
|
176
|
+
--error: #A8201A; /* 4.70:1 on its own 12% tint over --panel */
|
|
176
177
|
/* A syntax theme's dimmest token (comments) lands at 3.9:1 on --mass. The
|
|
177
178
|
well is lightened rather than the theme repainted, which lifts every
|
|
178
179
|
token at once; the frame's border is what still reads it as a block. */
|
|
@@ -197,4 +198,5 @@
|
|
|
197
198
|
--term-spot: var(--vd-300);
|
|
198
199
|
--term-cmd: #8ECF7A;
|
|
199
200
|
--term-str: #E6C060;
|
|
201
|
+
--term-err: #E5484D;
|
|
200
202
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eklavya",
|
|
3
3
|
"displayName": "Eklavya",
|
|
4
|
-
"version": "1.27.
|
|
4
|
+
"version": "1.27.1",
|
|
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"
|
|
@@ -47,9 +47,11 @@ In this order, each under its own `<h2>`:
|
|
|
47
47
|
- **The rule that transfers.** When this applies in a different codebase, and
|
|
48
48
|
the one gotcha to watch for.
|
|
49
49
|
|
|
50
|
-
Plain English, short sentences, no jargon without a gloss.
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
Plain English, short sentences, no jargon without a gloss. Any CSS you add
|
|
51
|
+
follows the design rules in the `eklavya-artifacts` skill: role tokens only
|
|
52
|
+
(`--ink --dim --faint --line --spot …`, never a raw hex or `--vd-*` step), one
|
|
53
|
+
verdigris accent, square corners, hairlines instead of shadows, the three font
|
|
54
|
+
variables, readable on both ink and paper, no emoji. One self-contained file.
|
|
53
55
|
|
|
54
56
|
Never reveal or restate the answer to a *different* question, and never grade
|
|
55
57
|
anything: the session already recorded the answer.
|
|
@@ -1,110 +1,62 @@
|
|
|
1
1
|
# Working in `cli/`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
`sh`
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
the
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- the config does not ask for enforcement — `quiz.enforced` false or absent with
|
|
64
|
-
no `mode: enforced` behind it, or `quiz.enabled` false — in the project file,
|
|
65
|
-
or in the global one when the project does not say;
|
|
66
|
-
- the database file does not exist;
|
|
67
|
-
- the `sqlite3` query errors, or returns no gate row for this repo.
|
|
68
|
-
|
|
69
|
-
Exit 1 happens on exactly one condition: a gate row for this repo whose `passed`
|
|
70
|
-
is not `1`. Adding a new failure mode means adding a new `exit 0` path.
|
|
71
|
-
|
|
72
|
-
## It reads the database directly
|
|
73
|
-
|
|
74
|
-
There is no server in a git hook, so the script talks to `knowledge.db` in raw
|
|
75
|
-
SQL and duplicates things it cannot import. Keep it in step with:
|
|
76
|
-
|
|
77
|
-
- the `gates` table shape — it selects `passed, required, answered` and picks the
|
|
78
|
-
repo's most recent row by `updated_at`. `syncGate` in `mcp/src/store.ts` is the
|
|
79
|
-
only writer; a renamed or added column lands here in the same commit.
|
|
80
|
-
- `DEFAULT_CONFIG.quiz` in `mcp/src/config.ts` — the script defaults a config
|
|
81
|
-
with neither `quiz` nor `mode` to unenforced.
|
|
82
|
-
- `projectSlug` in `mcp/src/paths.ts` — the script rebuilds it with
|
|
83
|
-
`tr '/\\:' '-'`, and `test/gate.test.ts` runs both parsers over one set of
|
|
84
|
-
configs so the two cannot drift apart silently.
|
|
85
|
-
- the `mode` → `quiz` alias in `normalizeLegacyKeys`, and the rule that
|
|
86
|
-
`quiz.enabled: false` forces `enforced` off. Both are duplicated here in jq,
|
|
87
|
-
spelled out with `if`/`elif` rather than `//`: jq's `//` is an alternative
|
|
88
|
-
operator, so `.quiz.enforced // (.mode == "enforced")` reads an explicit
|
|
89
|
-
`false` as unset and falls back to a stale `mode` in the same file — a gate
|
|
90
|
-
that keeps holding commits after somebody switched it off.
|
|
91
|
-
`test/gate.test.ts` runs both parsers over the same five configs.
|
|
92
|
-
|
|
93
|
-
The pass/fail arithmetic itself (`PASSING_GRADE`, `pass_threshold`,
|
|
94
|
-
`ceil(required * pass_threshold)`) is **not** duplicated here — the script trusts
|
|
95
|
-
the persisted `passed` column. Keep it that way: a change to the gate's rule
|
|
96
|
-
belongs in `syncGate` alone. What is duplicated is the lookup key, and it differs
|
|
97
|
-
from the in-session hook on purpose: `mcp/src/hooks/pre-tool-gate.ts` looks the
|
|
98
|
-
gate up by `session_id`, this script by `repo`, because a terminal commit has no
|
|
99
|
-
session.
|
|
100
|
-
|
|
101
|
-
## Tests
|
|
102
|
-
|
|
103
|
-
`mcp/test/gate.test.ts` runs the real script and the real installer against a
|
|
104
|
-
temp repo, and ends with an actual `git commit`. From `mcp/`:
|
|
105
|
-
|
|
106
|
-
```sh
|
|
107
|
-
npm test -- gate
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
`pretest` builds `dist/`, which `pre-tool-gate.js` in the same file needs.
|
|
3
|
+
This directory contains the POSIX `eklavya-gate` script. The `eklavya` binary
|
|
4
|
+
(`config`, `doctor`, `install`, `dashboard`, etc.) lives in `mcp/src/cli.ts`.
|
|
5
|
+
Read the root `CLAUDE.md` for the repository contract.
|
|
6
|
+
|
|
7
|
+
## Installation and scope
|
|
8
|
+
|
|
9
|
+
The terminal gate requires both a per-repository installation and project
|
|
10
|
+
`quiz.enforced: true`. `eklavya install` does not install a git hook.
|
|
11
|
+
|
|
12
|
+
`scripts/install-git-hook.sh` writes into the common Git directory so linked
|
|
13
|
+
worktrees use the same hook. It preserves an existing hook as `pre-commit.local`
|
|
14
|
+
and runs that first; `--uninstall` restores it. With `core.hooksPath` configured,
|
|
15
|
+
it prints the integration line and exits 2 without installing anything.
|
|
16
|
+
|
|
17
|
+
The installed wrapper tries the managed runtime, then the original installation
|
|
18
|
+
path, and invokes the script with `sh`. Missing both paths warns and allows the
|
|
19
|
+
commit. Preserve this fallback: updates can move plugin directories.
|
|
20
|
+
`eklavya uninstall` warns about the hook and prints removal instructions; it
|
|
21
|
+
does not remove the hook itself.
|
|
22
|
+
|
|
23
|
+
Project config lives in `~/.eklavya/projects/<slug>/config.json`; worktrees fold
|
|
24
|
+
to their main checkout. The script reads the old `<repo>/.eklavya.json` only as
|
|
25
|
+
a fallback and never migrates it. Global enforcement alone does not activate
|
|
26
|
+
this gate, but a global `quiz.enabled: false` releases it unless overridden by
|
|
27
|
+
the project. Keep legacy `mode` compatibility and explicit `false` values.
|
|
28
|
+
|
|
29
|
+
## Fail-open contract
|
|
30
|
+
|
|
31
|
+
Use POSIX `sh`; the installed hook runs through `/bin/sh`. Missing repository,
|
|
32
|
+
config, `jq`, `sqlite3`, database or gate row allows the commit. Database query
|
|
33
|
+
errors also allow it. Missing dependencies warn on stderr.
|
|
34
|
+
|
|
35
|
+
Exit 1 only when a gate row exists for this repository and `passed` is not `1`.
|
|
36
|
+
Do not add an operational error that prevents a commit.
|
|
37
|
+
|
|
38
|
+
## Keep duplicated logic aligned
|
|
39
|
+
|
|
40
|
+
| Script responsibility | Source and verification |
|
|
41
|
+
|---|---|
|
|
42
|
+
| Config merge and legacy `mode` alias | `mcp/src/config.ts`; shared fixtures in `mcp/test/gate.test.ts` |
|
|
43
|
+
| Project slug and worktree folding | `mcp/src/paths.ts`; physical paths must also handle symlinks |
|
|
44
|
+
| Latest repository gate lookup | `gates` schema and `syncGate` in `mcp/src/store.ts` |
|
|
45
|
+
| In-session commit detection | `mcp/src/hooks/pre-tool-gate.ts` and `commit-lib.ts` |
|
|
46
|
+
|
|
47
|
+
The script trusts persisted `passed`; it must not duplicate passing-grade or
|
|
48
|
+
threshold arithmetic. It looks up the latest gate by repository, whereas the
|
|
49
|
+
in-session hook uses a session ID. In jq, use explicit `if`/`elif` for booleans:
|
|
50
|
+
`//` treats `false` as absent and can re-enable a disabled legacy gate.
|
|
51
|
+
|
|
52
|
+
## Documentation and verification
|
|
53
|
+
|
|
54
|
+
In the same PR, update the manual `commit-gate.mdx` for installer, prerequisite,
|
|
55
|
+
scope, bypass or failure behavior changes. Check `configuration.mdx`,
|
|
56
|
+
`skills/setup/SKILL.md` and the commit-gate acceptance check in `CONTRIBUTING.md`
|
|
57
|
+
when their claims change. Every claim about terminal enforcement must include
|
|
58
|
+
both installation and project enforcement.
|
|
59
|
+
|
|
60
|
+
From `mcp/`, run `npm test -- gate`. It builds the runtime and exercises the real
|
|
61
|
+
script and installer in temporary repositories, including an actual commit.
|
|
62
|
+
Build `web/` after documentation changes; report any live acceptance test not run.
|