eklavya 1.27.0 → 1.28.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.
- 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 +196 -57
- 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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eklavya",
|
|
3
3
|
"displayName": "Eklavya",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.28.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"
|
|
@@ -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.
|