@draig/lexis-two 1.0.0 → 1.0.3

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 (90) hide show
  1. package/README.md +3 -3
  2. package/package.json +7 -2
  3. package/.claude-plugin/marketplace.json +0 -29
  4. package/.claude-plugin/plugin.json +0 -9
  5. package/.codex-plugin/plugin.json +0 -31
  6. package/.env.example +0 -8
  7. package/.github/FUNDING.yml +0 -1
  8. package/.github/copilot-instructions.md +0 -47
  9. package/.github/plugin/marketplace.json +0 -20
  10. package/.github/plugin/plugin.json +0 -16
  11. package/.github/workflows/deploy-site.yml +0 -53
  12. package/.github/workflows/test.yml +0 -29
  13. package/AUDIT.md +0 -74
  14. package/SPECXIS.md +0 -576
  15. package/benchmarks/README.md +0 -114
  16. package/benchmarks/arms/baseline.js +0 -2
  17. package/benchmarks/arms/caveman-SKILL.md +0 -67
  18. package/benchmarks/arms/caveman.js +0 -8
  19. package/benchmarks/arms/lexis-two.js +0 -10
  20. package/benchmarks/arms/ponytail.js +0 -6
  21. package/benchmarks/behavior.js +0 -58
  22. package/benchmarks/behavior.yaml +0 -40
  23. package/benchmarks/benchmark-local.py +0 -156
  24. package/benchmarks/benchmark-opencode-go.js +0 -294
  25. package/benchmarks/correctness.js +0 -294
  26. package/benchmarks/lib/aggregate-opencode-go.js +0 -103
  27. package/benchmarks/lib/load-env.js +0 -31
  28. package/benchmarks/lib/opencode-go-client.js +0 -151
  29. package/benchmarks/loc.js +0 -13
  30. package/benchmarks/opencode-go-models.json +0 -31
  31. package/benchmarks/promptfooconfig.yaml +0 -41
  32. package/benchmarks/prompts.json +0 -15
  33. package/benchmarks/render-opencode-go-report.js +0 -28
  34. package/benchmarks/results/2026-06-15-llama3.2-local.md +0 -76
  35. package/benchmarks/results/2026-06-16-opencode-go.md +0 -56
  36. package/benchmarks/results/opencode-go-2026-06-16-report.html +0 -226
  37. package/benchmarks/results/opencode-go-2026-06-16.json +0 -1339
  38. package/docs/assets/lexis-two-nobg.png +0 -0
  39. package/docs/assets/logo.png +0 -0
  40. package/docs/assets/logo.svg +0 -4
  41. package/docs/portability.md +0 -147
  42. package/docs/site.md +0 -52
  43. package/gemini-extension.json +0 -7
  44. package/pi-extension/index.js +0 -161
  45. package/pi-extension/package.json +0 -8
  46. package/pi-extension/test/extension.test.js +0 -89
  47. package/pi-extension/test/helpers.test.js +0 -35
  48. package/scripts/check-rule-copies.js +0 -82
  49. package/site/astro.config.mjs +0 -18
  50. package/site/package-lock.json +0 -4913
  51. package/site/package.json +0 -14
  52. package/site/public/CNAME +0 -1
  53. package/site/public/assets/lexis-two-nobg.png +0 -0
  54. package/site/public/assets/logo.png +0 -0
  55. package/site/public/assets/logo.svg +0 -4
  56. package/site/public/robots.txt +0 -4
  57. package/site/src/components/Adapt.astro +0 -33
  58. package/site/src/components/Benchmarks.astro +0 -232
  59. package/site/src/components/Commands.astro +0 -33
  60. package/site/src/components/Ecosystem.astro +0 -30
  61. package/site/src/components/Example.astro +0 -77
  62. package/site/src/components/Footer.astro +0 -28
  63. package/site/src/components/Header.astro +0 -87
  64. package/site/src/components/Hero.astro +0 -58
  65. package/site/src/components/Home.astro +0 -46
  66. package/site/src/components/Hosts.astro +0 -62
  67. package/site/src/components/Install.astro +0 -143
  68. package/site/src/components/LanguageSwitcher.astro +0 -82
  69. package/site/src/components/Philosophy.astro +0 -23
  70. package/site/src/components/Stacks.astro +0 -33
  71. package/site/src/components/Suggested.astro +0 -39
  72. package/site/src/data/opencode-go-benchmark.json +0 -230
  73. package/site/src/i18n/en.ts +0 -155
  74. package/site/src/i18n/es.ts +0 -158
  75. package/site/src/i18n/index.ts +0 -14
  76. package/site/src/layouts/Layout.astro +0 -114
  77. package/site/src/pages/benchmarks.astro +0 -4
  78. package/site/src/pages/es/benchmarks.astro +0 -4
  79. package/site/src/pages/es/index.astro +0 -10
  80. package/site/src/pages/index.astro +0 -10
  81. package/site/src/styles/global.css +0 -780
  82. package/site/tsconfig.json +0 -3
  83. package/tests/behavior.test.js +0 -80
  84. package/tests/commands.test.js +0 -40
  85. package/tests/copilot-plugin.test.js +0 -33
  86. package/tests/correctness.test.js +0 -191
  87. package/tests/gemini-extension.test.js +0 -78
  88. package/tests/hooks-windows.test.js +0 -48
  89. package/tests/hooks.test.js +0 -177
  90. package/tests/opencode-plugin.test.js +0 -64
Binary file
Binary file
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 48" role="img" aria-label="Lexis-Two">
2
- <rect x="0" y="8" width="220" height="32" rx="4" fill="#141816" stroke="#7cba8a" stroke-width="1.5"/>
3
- <text x="110" y="30" fill="#7cba8a" font-family="ui-monospace, monospace" font-size="14" font-weight="600" text-anchor="middle" letter-spacing="0.12em">LEXIS-TWO</text>
4
- </svg>
@@ -1,147 +0,0 @@
1
- # Agent Portability
2
-
3
- Lexis-Two is an agent-portable ecosystem. The `skills/` folder holds the core behavior.
4
- Host-specific files are thin adapters that point to those skills.
5
-
6
- **Site (live target):** [lexis-two.excelso.xyz](https://lexis-two.excelso.xyz) — built from `site/` and deployed via GitHub Actions. See [site.md](./site.md) for hosting.
7
-
8
- ## Naming
9
-
10
- | Name | What it is |
11
- | ---- | ---------- |
12
- | `lexis` | Base prefix — `// lexis:` comments, shared philosophy |
13
- | `lexis-two` | This repo — public portable rules, skills, commands, adapters |
14
- | `lexis-one` | Private agent configuration (not published) |
15
- | `lexis-zero` | Future orchestrator-style agent (not shipped yet) |
16
-
17
- Slash commands and skill folders use the `lexis-two-*` prefix. Plugin manifests use `"name": "lexis-two"`.
18
-
19
- ## Supported Hosts
20
-
21
- | Host | Files | Level |
22
- | ---- | ----- | ----- |
23
- | OpenCode | `.opencode/plugins/lexis-two.mjs`, `.opencode/command/`, `hooks/`, `skills/` | Full — plugin + mode switches + commands |
24
- | Claude Code | `.claude-plugin/`, `hooks/hooks.json`, `commands/`, `skills/` | **Coming soon** (v0.3) — files in repo, not verified |
25
- | GitHub Copilot (IDE plugin) | `.github/plugin/plugin.json`, `hooks/copilot-hooks.json`, `commands/`, `skills/` | **Coming soon** (v0.3) — files in repo, not verified |
26
- | Gemini CLI | `gemini-extension.json`, `AGENTS.md`, `commands/`, `skills/` | Full — extension manifest + commands |
27
- | pi | `pi-extension/`, `skills/` (via `package.json` `"pi"`) | Full — extension + commands |
28
- | Codex | `.codex-plugin/plugin.json`, `hooks/hooks.json`, `AGENTS.md` | Full — plugin + hooks |
29
- | Cursor | `.cursor/rules/lexis-two.mdc` | Rules — always-on project rule |
30
- | Windsurf | `.windsurf/rules/lexis-two.md` | Rules — project rule |
31
- | Cline | `.clinerules/lexis-two.md` | Rules — project rule |
32
- | GitHub Copilot (repo) | `.github/copilot-instructions.md` | Rules — repository instruction |
33
- | GitHub Copilot CLI | `AGENTS.md` or `~/.copilot/copilot-instructions.md` | Rules — no mode switches |
34
- | Kiro | `.kiro/steering/lexis-two.md` | Rules — steering rule |
35
- | VS Code + Codex | `AGENTS.md` or `~/.codex/AGENTS.md` | Rules — instruction tier |
36
- | Antigravity | `AGENTS.md` or `.agents/rules/` | Rules — instruction tier |
37
- | Generic agents | `AGENTS.md` or `skills/*/SKILL.md` | Rules — copy and load |
38
-
39
- ### Adapter rule
40
-
41
- Keep adapters thin. When a host supports skills or hooks, point it at the
42
- existing `skills/` and `hooks/` files. When a host only supports project
43
- instructions, keep its rule text aligned with `AGENTS.md`.
44
-
45
- Run `node scripts/check-rule-copies.js` after editing `AGENTS.md` to verify
46
- instruction-tier copies (Cursor, Windsurf, Cline, Kiro) have not drifted.
47
-
48
- ## Slash Commands
49
-
50
- Available on hosts that ship `commands/` and/or `.opencode/command/` today: OpenCode, Gemini CLI, pi. Claude Code and Copilot plugin: v0.3.
51
-
52
- | Command | Skill / behavior |
53
- | ------- | ---------------- |
54
- | `/lexis-two` | Mode switch — `lite`, `full` (default), `ultra`, `off` |
55
- | `/lexis-two-review` | `skills/lexis-two-review/` — diff review for over-engineering |
56
- | `/lexis-two-audit` | `skills/lexis-two-audit/` — full repo audit |
57
- | `/lexis-two-debt` | `skills/lexis-two-debt/` — harvest `// lexis:` comments |
58
- | `/lexis-two-plan` | `skills/lexis-two-plan/` — plan before coding |
59
- | `/lexis-two-security` | `skills/lexis-two-security/` — security audit (Node/TS stack default) |
60
- | `/lexis-two-help` | Quick reference card |
61
-
62
- Gemini CLI: `commands/lexis-two*.toml`. OpenCode: `.opencode/command/lexis-two*.md`.
63
-
64
- ## Portable Skills
65
-
66
- | Skill | What it does |
67
- | ----- | ------------ |
68
- | `skills/lexis-two/` | Core ruleset + intensity levels |
69
- | `skills/lexis-two-review/` | Diff review for over-engineering |
70
- | `skills/lexis-two-audit/` | Full repo audit |
71
- | `skills/lexis-two-debt/` | Harvest `// lexis:` comments into debt ledger |
72
- | `skills/lexis-two-plan/` | Feature planning before coding |
73
- | `skills/lexis-two-security/` | Security audit (default: Node.js / Next.js / MongoDB) |
74
-
75
- Adapt skill shell commands for other stacks — see README **Adapting Lexis-Two to Any Stack**.
76
-
77
- ## Project Install
78
-
79
- ```bash
80
- git clone https://github.com/nitdraig/lexis-two.git ~/lexis-two
81
- ```
82
-
83
- ### OpenCode
84
-
85
- Add to `opencode.json` in the project (or `~/.config/opencode/opencode.json` globally):
86
-
87
- ```jsonc
88
- {
89
- "plugin": ["~/lexis-two/.opencode/plugins/lexis-two.mjs"],
90
- "instructions": ["~/lexis-two/AGENTS.md"]
91
- }
92
- ```
93
-
94
- ### Cursor
95
-
96
- ```bash
97
- cp ~/lexis-two/.cursor/rules/lexis-two.mdc .cursor/rules/lexis-two.mdc
98
- ```
99
-
100
- ### Windsurf / Cline / Kiro
101
-
102
- Copy the matching rule file into your project:
103
-
104
- ```bash
105
- cp ~/lexis-two/.windsurf/rules/lexis-two.md .windsurf/rules/
106
- cp ~/lexis-two/.clinerules/lexis-two.md .clinerules/
107
- cp ~/lexis-two/.kiro/steering/lexis-two.md .kiro/steering/
108
- ```
109
-
110
- ### Gemini CLI
111
-
112
- Run from the cloned repo root (manifest auto-discovers `commands/` and `AGENTS.md`):
113
-
114
- ```bash
115
- cd ~/lexis-two
116
- # Follow Gemini CLI extension install for gemini-extension.json
117
- ```
118
-
119
- ### pi
120
-
121
- Install as a pi package from the repo root (`package.json` declares `"pi"` extensions and skills).
122
-
123
- ## Global Install (rules-only hosts)
124
-
125
- ```bash
126
- # Cursor (global)
127
- cp ~/lexis-two/.cursor/rules/lexis-two.mdc ~/.cursor/rules/lexis-two.mdc
128
-
129
- # GitHub Copilot CLI (global)
130
- cp ~/lexis-two/AGENTS.md ~/.copilot/copilot-instructions.md
131
-
132
- # VS Code + Codex (global)
133
- cp ~/lexis-two/AGENTS.md ~/.codex/AGENTS.md
134
-
135
- # OpenCode (global) — add to ~/.config/opencode/opencode.json:
136
- # { "plugin": ["~/lexis-two/.opencode/plugins/lexis-two.mjs"] }
137
- ```
138
-
139
- ## Config
140
-
141
- Default mode resolution (hooks + pi + OpenCode plugin):
142
-
143
- 1. `LEXIS_TWO_DEFAULT_MODE` env var (`off` \| `lite` \| `full` \| `ultra`)
144
- 2. Config file: `~/.config/lexis-two/config.json` (Windows: `%APPDATA%\lexis-two\config.json`) with `{ "defaultMode": "full" }`
145
- 3. Fallback: `full`
146
-
147
- Active mode flag (Claude Code): `~/.claude/.lexis-two-active`. OpenCode: `~/.config/opencode/.lexis-two-active`.
package/docs/site.md DELETED
@@ -1,52 +0,0 @@
1
- # Site — lexis-two.excelso.xyz
2
-
3
- Astro static site in `site/`. Deployed to GitHub Pages via `.github/workflows/deploy-site.yml`.
4
-
5
- **Primary goal:** showcase the project and drive clones/stars.
6
- **Secondary goal:** publish benchmark charts at `/benchmarks/`.
7
-
8
- ## Local dev
9
-
10
- ```bash
11
- npm run site:dev
12
- # → http://localhost:4321
13
-
14
- # After a benchmark run:
15
- npm run benchmark:report # syncs JSON → site/src/data/
16
- npm run site:build
17
- ```
18
-
19
- ## Hosting
20
-
21
- GitHub Pages + custom domain `lexis-two.excelso.xyz`.
22
-
23
- | Piece | Location |
24
- | ----- | -------- |
25
- | Astro app | `site/` |
26
- | Build output | `site/dist/` |
27
- | CNAME | `site/public/CNAME` |
28
- | CI deploy | `.github/workflows/deploy-site.yml` (push to `main` under `site/**`) |
29
-
30
- DNS: CNAME `lexis-two` → `<user>.github.io`.
31
-
32
- ## Content map
33
-
34
- | Section | Source |
35
- | ------- | ------ |
36
- | Hero + benchmarks CTA | `site/src/components/Home.astro` + i18n |
37
- | Philosophy ladder | `site/src/i18n/*.ts` |
38
- | Hosts / commands / install | i18n dictionaries |
39
- | Benchmark charts | `site/src/pages/benchmarks.astro` + `site/src/data/opencode-go-benchmark.json` |
40
- | Portability docs | `docs/portability.md` on GitHub (linked, not duplicated) |
41
-
42
- ## Checklist
43
-
44
- - [x] Astro site in `site/`
45
- - [x] `site/public/CNAME` → `lexis-two.excelso.xyz`
46
- - [x] Benchmark page at `/benchmarks/`
47
- - [ ] GitHub Pages enabled (Settings → Pages → deploy from Actions / gh-pages branch)
48
- - [ ] DNS CNAME live; HTTPS green
49
-
50
- ## Legacy
51
-
52
- `docs/index.html` and `docs/styles.css` were removed — use `site/` instead. `docs/portability.md` stays in repo for GitHub linking.
@@ -1,7 +0,0 @@
1
- {
2
- "name": "lexis-two",
3
- "version": "1.0.0",
4
- "description": "The simple way to obtain the best code. Portable rules, skills, and slash commands for AI agents with lowest tokens usage.",
5
- "contextFileName": "AGENTS.md",
6
- "commands": "commands/"
7
- }
@@ -1,161 +0,0 @@
1
- import { createRequire } from "node:module";
2
-
3
- const require = createRequire(import.meta.url);
4
- const {
5
- DEFAULT_MODE,
6
- getDefaultMode,
7
- normalizeMode,
8
- normalizeConfigMode,
9
- normalizePersistedMode,
10
- writeDefaultMode,
11
- } = require("../hooks/lexis-two-config.js");
12
- const { getLexisInstructions, filterSkillBodyForMode } = require("../hooks/lexis-two-instructions.js");
13
-
14
- export { filterSkillBodyForMode };
15
- export const readDefaultMode = getDefaultMode;
16
-
17
- export function resolveSessionMode(entries, fallbackMode = DEFAULT_MODE) {
18
- const fallback = normalizePersistedMode(fallbackMode) || DEFAULT_MODE;
19
- if (!Array.isArray(entries)) return fallback;
20
-
21
- for (let i = entries.length - 1; i >= 0; i -= 1) {
22
- const entry = entries[i];
23
- if (entry?.type !== "custom" || entry?.customType !== "lexis-two-mode") continue;
24
-
25
- const mode = normalizePersistedMode(entry?.data?.mode);
26
- if (mode) return mode;
27
- }
28
-
29
- return fallback;
30
- }
31
-
32
- export function parseLexisCommand(text, defaultMode = DEFAULT_MODE) {
33
- const fallback = normalizePersistedMode(defaultMode) || DEFAULT_MODE;
34
- const normalizedText = String(text || "").trim().toLowerCase();
35
-
36
- if (!normalizedText) {
37
- return { type: "set-mode", mode: fallback === "off" ? "full" : fallback };
38
- }
39
-
40
- const [primary, secondary] = normalizedText.split(/\s+/);
41
-
42
- if (primary === "status") return { type: "status" };
43
-
44
- if (primary === "default") {
45
- const mode = normalizeConfigMode(secondary);
46
- return mode ? { type: "set-default", mode } : { type: "invalid", reason: "invalid-default-mode" };
47
- }
48
-
49
- const mode = normalizeMode(primary);
50
- return mode ? { type: "set-mode", mode } : { type: "invalid", reason: "invalid-mode", mode: primary };
51
- }
52
-
53
- export { writeDefaultMode };
54
-
55
- export default function lexisExtension(pi) {
56
- let currentMode = DEFAULT_MODE;
57
- let configuredDefaultMode = getDefaultMode();
58
-
59
- const setMode = (mode, ctx) => {
60
- const normalized = normalizePersistedMode(mode);
61
- if (!normalized) return;
62
-
63
- currentMode = normalized;
64
- pi.appendEntry("lexis-two-mode", { mode: normalized });
65
- ctx?.ui?.notify?.(`Lexis-Two mode set to ${normalized}.`, "info");
66
- };
67
-
68
- const sendAlias = (skillName, args, ctx) => {
69
- const normalized = String(args || "").trim();
70
- const message = normalized ? `${skillName} ${normalized}` : skillName;
71
-
72
- if (ctx?.isIdle?.() === false) {
73
- pi.sendUserMessage(message, { deliverAs: "followUp" });
74
- ctx?.ui?.notify?.(`${skillName} queued as follow-up.`, "info");
75
- return;
76
- }
77
-
78
- pi.sendUserMessage(message);
79
- };
80
-
81
- pi.registerCommand("lexis-two", {
82
- description: "Set or report Lexis-Two mode",
83
- handler: async (args, ctx) => {
84
- const parsed = parseLexisCommand(args, configuredDefaultMode);
85
-
86
- if (parsed.type === "status") {
87
- ctx?.ui?.notify?.(`Lexis-Two: current ${currentMode} • default ${configuredDefaultMode}`, "info");
88
- return;
89
- }
90
-
91
- if (parsed.type === "set-default") {
92
- const written = writeDefaultMode(parsed.mode);
93
- if (written) {
94
- configuredDefaultMode = getDefaultMode();
95
- const message = configuredDefaultMode === written
96
- ? `Default Lexis-Two mode set to ${written}.`
97
- : `Saved default ${written}, but env override keeps default at ${configuredDefaultMode}.`;
98
- ctx?.ui?.notify?.(message, "info");
99
- }
100
- return;
101
- }
102
-
103
- if (parsed.type === "set-mode") {
104
- setMode(parsed.mode, ctx);
105
- return;
106
- }
107
-
108
- ctx?.ui?.notify?.("Unknown or unsupported /lexis-two mode.", "warning");
109
- },
110
- });
111
-
112
- pi.registerCommand("lexis-two-review", {
113
- description: "Run /skill:lexis-two-review",
114
- handler: (_args, ctx) => sendAlias("/skill:lexis-two-review", "", ctx),
115
- });
116
-
117
- pi.registerCommand("lexis-two-audit", {
118
- description: "Run /skill:lexis-two-audit",
119
- handler: (_args, ctx) => sendAlias("/skill:lexis-two-audit", "", ctx),
120
- });
121
-
122
- pi.registerCommand("lexis-two-debt", {
123
- description: "Run /skill:lexis-two-debt",
124
- handler: (_args, ctx) => sendAlias("/skill:lexis-two-debt", "", ctx),
125
- });
126
-
127
- pi.registerCommand("lexis-two-plan", {
128
- description: "Run /skill:lexis-two-plan",
129
- handler: (_args, ctx) => sendAlias("/skill:lexis-two-plan", "", ctx),
130
- });
131
-
132
- pi.registerCommand("lexis-two-security", {
133
- description: "Run /skill:lexis-two-security",
134
- handler: (_args, ctx) => sendAlias("/skill:lexis-two-security", "", ctx),
135
- });
136
-
137
- pi.registerCommand("lexis-two-help", {
138
- description: "Run /skill:lexis-two-help",
139
- handler: (_args, ctx) => sendAlias("/skill:lexis-two-help", "", ctx),
140
- });
141
-
142
- pi.on("input", async (event) => {
143
- if (event?.source === "extension") return;
144
-
145
- const text = String(event?.text || "");
146
- if (currentMode !== "off" && /\b(stop lexis|normal mode)\b/i.test(text)) {
147
- setMode("off");
148
- }
149
- });
150
-
151
- pi.on("session_start", async (_event, ctx) => {
152
- const entries = ctx?.sessionManager?.getBranch?.() || ctx?.sessionManager?.getEntries?.() || [];
153
- configuredDefaultMode = getDefaultMode();
154
- currentMode = resolveSessionMode(entries, configuredDefaultMode);
155
- });
156
-
157
- pi.on("before_agent_start", async (event) => {
158
- if (!currentMode || currentMode === "off") return;
159
- return { systemPrompt: `${event.systemPrompt}\n\n${getLexisInstructions(currentMode)}` };
160
- });
161
- }
@@ -1,8 +0,0 @@
1
- {
2
- "name": "lexis-two-pi-extension-dev",
3
- "private": true,
4
- "type": "module",
5
- "scripts": {
6
- "test": "node --test ./test/*.test.js"
7
- }
8
- }
@@ -1,89 +0,0 @@
1
- import test from "node:test";
2
- import assert from "node:assert/strict";
3
- import lexisExtension from "../index.js";
4
-
5
- class MockPi {
6
- constructor() {
7
- this.commands = {};
8
- this.listeners = {};
9
- this.entries = [];
10
- this.userMessages = [];
11
- }
12
-
13
- registerCommand(name, config) {
14
- this.commands[name] = config;
15
- }
16
-
17
- on(event, handler) {
18
- this.listeners[event] = handler;
19
- }
20
-
21
- appendEntry(type, data) {
22
- this.entries.push({ type, data });
23
- }
24
-
25
- sendUserMessage(text, options) {
26
- this.userMessages.push({ text, options });
27
- }
28
- }
29
-
30
- test("lexisExtension registers commands and listeners", () => {
31
- const pi = new MockPi();
32
- lexisExtension(pi);
33
-
34
- assert.ok(pi.commands["lexis-two"]);
35
- assert.ok(pi.commands["lexis-two-review"]);
36
- assert.ok(pi.commands["lexis-two-audit"]);
37
- assert.ok(pi.commands["lexis-two-debt"]);
38
- assert.ok(pi.commands["lexis-two-plan"]);
39
- assert.ok(pi.commands["lexis-two-security"]);
40
- assert.ok(pi.commands["lexis-two-help"]);
41
-
42
- assert.ok(pi.listeners["input"]);
43
- assert.ok(pi.listeners["session_start"]);
44
- assert.ok(pi.listeners["before_agent_start"]);
45
- });
46
-
47
- test("lexisExtension command handlers trigger correctly", async () => {
48
- const pi = new MockPi();
49
- lexisExtension(pi);
50
-
51
- let notified = null;
52
- const ctx = {
53
- ui: {
54
- notify: (msg, type) => {
55
- notified = { msg, type };
56
- },
57
- },
58
- };
59
-
60
- await pi.commands["lexis-two"].handler("lite", ctx);
61
- assert.equal(pi.entries[0].type, "lexis-two-mode");
62
- assert.equal(pi.entries[0].data.mode, "lite");
63
- assert.equal(notified.msg, "Lexis-Two mode set to lite.");
64
-
65
- pi.commands["lexis-two-review"].handler("", ctx);
66
- assert.equal(pi.userMessages[0].text, "/skill:lexis-two-review");
67
- });
68
-
69
- test("lexisExtension input listener detects deactivation", async () => {
70
- const pi = new MockPi();
71
- lexisExtension(pi);
72
-
73
- let notified = null;
74
- const ctx = {
75
- ui: {
76
- notify: (msg, type) => {
77
- notified = { msg, type };
78
- },
79
- },
80
- };
81
-
82
- // Set mode to full first
83
- await pi.commands["lexis-two"].handler("full", ctx);
84
- assert.equal(pi.entries[0].data.mode, "full");
85
-
86
- // Send input "stop lexis"
87
- await pi.listeners["input"]({ text: "Please stop lexis now" });
88
- assert.equal(pi.entries[1].data.mode, "off");
89
- });
@@ -1,35 +0,0 @@
1
- import test from "node:test";
2
- import assert from "node:assert/strict";
3
- import { resolveSessionMode, parseLexisCommand } from "../index.js";
4
-
5
- test("resolveSessionMode resolves mode from branch entries", () => {
6
- const entries = [
7
- { type: "user-message", text: "hello" },
8
- { type: "custom", customType: "lexis-two-mode", data: { mode: "lite" } },
9
- { type: "assistant-message", text: "world" },
10
- ];
11
- assert.equal(resolveSessionMode(entries, "full"), "lite");
12
- });
13
-
14
- test("resolveSessionMode falls back to default mode if no entries", () => {
15
- assert.equal(resolveSessionMode([], "lite"), "lite");
16
- });
17
-
18
- test("parseLexisCommand parses empty command as default toggle", () => {
19
- assert.deepEqual(parseLexisCommand("", "full"), { type: "set-mode", mode: "full" });
20
- assert.deepEqual(parseLexisCommand(" ", "off"), { type: "set-mode", mode: "full" });
21
- });
22
-
23
- test("parseLexisCommand parses status command", () => {
24
- assert.deepEqual(parseLexisCommand("status"), { type: "status" });
25
- });
26
-
27
- test("parseLexisCommand parses default command", () => {
28
- assert.deepEqual(parseLexisCommand("default lite"), { type: "set-default", mode: "lite" });
29
- assert.deepEqual(parseLexisCommand("default invalid"), { type: "invalid", reason: "invalid-default-mode" });
30
- });
31
-
32
- test("parseLexisCommand parses mode command", () => {
33
- assert.deepEqual(parseLexisCommand("ultra"), { type: "set-mode", mode: "ultra" });
34
- assert.deepEqual(parseLexisCommand("invalid"), { type: "invalid", reason: "invalid-mode", mode: "invalid" });
35
- });
@@ -1,82 +0,0 @@
1
- #!/usr/bin/env node
2
- // lexis-two — rule copy integrity check
3
- //
4
- // To avoid runtime overhead, instruction-tier hosts (Windsurf, Cline, Kiro,
5
- // Cursor) load static copies of the rules. This script acts as a build/CI guard
6
- // to ensure those copies never drift from the canonical source (AGENTS.md).
7
- //
8
- // It asserts that:
9
- // 1. Every rule copy file exists.
10
- // 2. Every copy is completely identical to AGENTS.md (ignoring host-specific frontmatter).
11
- // 3. The canonical AGENTS.md itself contains the load-bearing Lexis-Two rules.
12
-
13
- const fs = require('fs');
14
- const path = require('path');
15
-
16
- const root = path.join(__dirname, '..');
17
-
18
- // Canonical source of truth
19
- const SOURCE_FILE = 'AGENTS.md';
20
-
21
- // Static copies to validate
22
- const COPIES = [
23
- '.windsurf/rules/lexis-two.md',
24
- '.clinerules/lexis-two.md',
25
- '.kiro/steering/lexis-two.md',
26
- '.cursor/rules/lexis-two.mdc',
27
- ];
28
-
29
- // Load-bearing phrases that MUST exist in the source of truth. If these are
30
- // missing, the source file has been gutted, and the copies are validating
31
- // against an empty shell.
32
- const INVARIANTS = [
33
- 'lazy senior',
34
- 'Input validation at trust boundaries',
35
- 'YAGNI',
36
- ];
37
-
38
- function read(relPath) {
39
- try {
40
- return fs.readFileSync(path.join(root, relPath), 'utf8');
41
- } catch (e) {
42
- console.error(`Error: failed to read ${relPath}`);
43
- process.exit(1);
44
- }
45
- }
46
-
47
- // 1. Validate canonical source
48
- const source = read(SOURCE_FILE);
49
- for (const phrase of INVARIANTS) {
50
- if (!source.includes(phrase)) {
51
- console.error(`Error: canonical source (${SOURCE_FILE}) is missing load-bearing rule: "${phrase}"`);
52
- process.exit(1);
53
- }
54
- }
55
-
56
- // Helper to strip frontmatter (metadata blocks between '---' at start of file)
57
- function stripFrontmatter(content) {
58
- return content.replace(/^---[\s\S]*?---\s*/, '');
59
- }
60
-
61
- // 2. Validate copies
62
- let failed = false;
63
- const canonicalBody = stripFrontmatter(source).trim();
64
-
65
- for (const copyPath of COPIES) {
66
- const copyContent = read(copyPath);
67
- const copyBody = stripFrontmatter(copyContent).trim();
68
-
69
- if (copyBody !== canonicalBody) {
70
- console.error(`Drift detected: ${copyPath} does not match ${SOURCE_FILE}`);
71
- failed = true;
72
- }
73
- }
74
-
75
- if (failed) {
76
- console.error('\nIntegrity check FAILED. Rule copies have drifted from AGENTS.md.');
77
- console.error('To fix, copy AGENTS.md content into the drifted files, preserving their frontmatter if any.');
78
- process.exit(1);
79
- }
80
-
81
- console.log('Rule copy integrity check PASSED.');
82
- process.exit(0);
@@ -1,18 +0,0 @@
1
- import { defineConfig } from "astro/config";
2
- import sitemap from "@astrojs/sitemap";
3
-
4
- export default defineConfig({
5
- site: "https://lexis-two.excelso.xyz",
6
- output: "static",
7
- i18n: {
8
- defaultLocale: "en",
9
- locales: ["en", "es"],
10
- routing: {
11
- prefixDefaultLocale: false,
12
- },
13
- },
14
- build: {
15
- format: "directory",
16
- },
17
- integrations: [sitemap()],
18
- });