@draig/lexis-two 1.0.6 → 1.0.8
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/.opencode/command/lexis.md +17 -0
- package/.opencode/command/specxis.md +18 -0
- package/.opencode/plugins/lexis-two-tui.mjs +5 -4
- package/.opencode/plugins/lexis-two.mjs +8 -1
- package/README.md +41 -19
- package/commands/lexis-two-audit.toml +3 -0
- package/commands/lexis-two-debt.toml +3 -0
- package/commands/lexis-two-help.toml +3 -0
- package/commands/lexis-two-plan.toml +3 -0
- package/commands/lexis-two-review.toml +3 -0
- package/commands/lexis-two-security.toml +3 -0
- package/commands/lexis-two.toml +3 -0
- package/commands/lexis.toml +3 -0
- package/commands/specxis.toml +3 -0
- package/package.json +6 -2
- package/scripts/check-rule-copies.js +82 -0
- package/scripts/opencode-wrapper-postinstall.mjs +50 -0
- package/scripts/specxis-debt.js +121 -0
- package/scripts/specxis-init.js +45 -0
- package/skills/specxis/SKILL.md +46 -0
- package/templates/specxis/proposal.md +21 -0
- package/templates/specxis/review.md +17 -0
- package/templates/specxis/spec.md +24 -0
- package/templates/specxis/tasks.md +16 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Manage Lexis senior dev mode, intensity levels, and quality/security tools"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Manage Lexis senior dev mode, intensity levels, and quality/security tools.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
- `/lexis` or `/lexis status`: Show current mode and status.
|
|
9
|
+
- `/lexis lite` / `/lexis full` / `/lexis ultra` / `/lexis off`: Switch the intensity level of the ruleset.
|
|
10
|
+
- `/lexis plan` (or `/lexis p`): Plan a feature using the lazy hierarchy before coding.
|
|
11
|
+
- `/lexis review` (or `/lexis r`): Review current changes for over-engineering.
|
|
12
|
+
- `/lexis audit` (or `/lexis a`): Audit the entire repository for over-engineering.
|
|
13
|
+
- `/lexis debt` (or `/lexis d`): Harvest all `// lexis:` comments into a tracked ledger.
|
|
14
|
+
- `/lexis security` (or `/lexis s`): Run a focused security audit on the stack.
|
|
15
|
+
- `/lexis help` (or `/lexis h`): Show the quick reference card.
|
|
16
|
+
|
|
17
|
+
Respond in Spanish.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Manage the Specxis Spec-Driven Development lifecycle (new, plan, implement, review, close, debt, status)"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Manage the Specxis Spec-Driven Development lifecycle.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
- `/specxis` or `/specxis status`: Show active specs, tasks progress, and debt.
|
|
9
|
+
- `/specxis new <slug>`: Create a new spec folder and proposal.md.
|
|
10
|
+
- `/specxis plan <slug>`: Generate spec.md and tasks.md from proposal.md.
|
|
11
|
+
- `/specxis implement <slug>`: Implement the next unchecked task.
|
|
12
|
+
- `/specxis review <slug>`: Review the implementation against spec.md and AGENTS.md.
|
|
13
|
+
- `/specxis close <slug>`: Archive the completed spec and sync its debt.
|
|
14
|
+
- `/specxis debt`: Sync all `// lexis:` comments from the codebase to `.specxis/debt.md`.
|
|
15
|
+
|
|
16
|
+
If `.specxis/` does not exist, suggest running `node node_modules/@draig/lexis-two/scripts/specxis-init.js` (or local script path if in development).
|
|
17
|
+
|
|
18
|
+
Respond in Spanish.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// lexis-two — OpenCode TUI plugin (no-op)
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
// and prevent installation/runtime load failures in the TUI interface.
|
|
3
|
+
// Satisfies OpenCode's TUI target loader. No TUI UI is needed for lexis-two.
|
|
5
4
|
|
|
6
|
-
export default
|
|
7
|
-
|
|
5
|
+
export default {
|
|
6
|
+
async tui() {
|
|
7
|
+
return {};
|
|
8
|
+
},
|
|
8
9
|
};
|
|
@@ -55,7 +55,7 @@ function writeMode(mode) {
|
|
|
55
55
|
fs.writeFileSync(statePath, mode);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
function createServerHooks({ client } = {}) {
|
|
59
59
|
const log = (level, message) => {
|
|
60
60
|
try {
|
|
61
61
|
client &&
|
|
@@ -83,4 +83,11 @@ export default async ({ client } = {}) => {
|
|
|
83
83
|
log("info", "lexis-two " + mode);
|
|
84
84
|
},
|
|
85
85
|
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// OpenCode v1 plugin shape: default export is { server(), tui() }.
|
|
89
|
+
export default {
|
|
90
|
+
async server(input) {
|
|
91
|
+
return createServerHooks(input);
|
|
92
|
+
},
|
|
86
93
|
};
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<picture>
|
|
3
3
|
<!-- <source media="(prefers-color-scheme: dark)" srcset="assets/logo-dark.png"> -->
|
|
4
|
-
<img src="assets/logo.png" width="220" alt="Lexis-two">
|
|
4
|
+
<img src="https://github.com/nitdraig/lexis-two/assets/logo.png" width="220" alt="Lexis-two">
|
|
5
5
|
</picture>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
@@ -89,7 +89,8 @@ To enable the slash commands globally in any project:
|
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
91
|
mkdir -p ~/.config/opencode/commands
|
|
92
|
-
cp .opencode/command/lexis
|
|
92
|
+
cp .opencode/command/lexis*.md ~/.config/opencode/commands/
|
|
93
|
+
cp .opencode/command/specxis*.md ~/.config/opencode/commands/
|
|
93
94
|
```
|
|
94
95
|
|
|
95
96
|
### OpenCode (Local development / manual)
|
|
@@ -129,15 +130,36 @@ More hosts (Windsurf, Gemini CLI, pi, Copilot): see [docs/portability.md](./docs
|
|
|
129
130
|
|
|
130
131
|
## Commands
|
|
131
132
|
|
|
132
|
-
Once installed, these slash commands are available in OpenCode:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
|
138
|
-
|
|
|
139
|
-
| `/lexis
|
|
140
|
-
| `/lexis
|
|
133
|
+
Once installed, these unifed slash commands are available in OpenCode, Gemini CLI, and pi:
|
|
134
|
+
|
|
135
|
+
### 1. `/lexis` — Core Lexis Commands
|
|
136
|
+
Manage Lexis senior dev mode, intensity levels, and quality/security tools under a single unifed command.
|
|
137
|
+
|
|
138
|
+
| Subcommand | Shortcut | What it does |
|
|
139
|
+
| ---------- | -------- | ------------ |
|
|
140
|
+
| `/lexis status` | `/lexis` | Shows current mode (lite/full/ultra/off) and default configuration. |
|
|
141
|
+
| `/lexis lite` / `full` / `ultra` / `off` | - | Switches the intensity level of the ruleset. |
|
|
142
|
+
| `/lexis plan` | `/lexis p` | Plans a feature using the minimalist decision hierarchy before coding. |
|
|
143
|
+
| `/lexis review` | `/lexis r` | Reviews recent changes against `AGENTS.md` rules for over-engineering. |
|
|
144
|
+
| `/lexis audit` | `/lexis a` | Full codebase audit — over-engineering, deps, structure. |
|
|
145
|
+
| `/lexis debt` | `/lexis d` | Surfaces all `// lexis:` comments as a prioritized debt list. |
|
|
146
|
+
| `/lexis security` | `/lexis s` | Security audit focused on your stack (Node.js, MongoDB, Next.js). |
|
|
147
|
+
| `/lexis help` | `/lexis h` | Shows the quick reference card. |
|
|
148
|
+
|
|
149
|
+
*(Note: The old individual commands like `/lexis-two-review` are fully supported for backward compatibility but will display a deprecation warning guiding you to use `/lexis` instead.)*
|
|
150
|
+
|
|
151
|
+
### 2. `/specxis` — Spec-Driven Development (v0.5)
|
|
152
|
+
Manage the complete Specxis SDD lifecycle for complex features.
|
|
153
|
+
|
|
154
|
+
| Subcommand | What it does |
|
|
155
|
+
| ---------- | ------------ |
|
|
156
|
+
| `/specxis` or `/specxis status` | Shows active specs, tasks progress, and debt. |
|
|
157
|
+
| `/specxis new <slug>` | Creates a new spec folder and `proposal.md` applying the lazy check. |
|
|
158
|
+
| `/specxis plan <slug>` | Generates `spec.md` and `tasks.md` from `proposal.md`. |
|
|
159
|
+
| `/specxis implement <slug>` | Implements the next unchecked task in the active spec. |
|
|
160
|
+
| `/specxis review <slug>` | Reviews the implementation against `spec.md` and `AGENTS.md`. |
|
|
161
|
+
| `/specxis close <slug>` | Archives the completed spec and syncs its debt to `.specxis/debt.md`. |
|
|
162
|
+
| `/specxis debt` | Sincroniza todos los comentarios `// lexis:` del código de forma portable. |
|
|
141
163
|
|
|
142
164
|
---
|
|
143
165
|
|
|
@@ -166,7 +188,7 @@ Lexis marks intentional simplifications with inline comments:
|
|
|
166
188
|
// lexis: tech debt — revisit when auth module is stable
|
|
167
189
|
```
|
|
168
190
|
|
|
169
|
-
Run `/lexis
|
|
191
|
+
Run `/lexis debt` (or `/lexis d`) to collect and prioritize all tagged items across the codebase.
|
|
170
192
|
|
|
171
193
|
---
|
|
172
194
|
|
|
@@ -250,17 +272,17 @@ The public orchestrator — a generalized pattern extracted from the private Lex
|
|
|
250
272
|
|
|
251
273
|
---
|
|
252
274
|
|
|
253
|
-
### v0.5 — Specxis (Spec-Driven Development)
|
|
275
|
+
### v0.5 — Specxis (Spec-Driven Development) ✅
|
|
254
276
|
|
|
255
277
|
Lightweight SDD layer for complex features — inspired by OpenSpec and Spec Kit,
|
|
256
278
|
built for the Lexis philosophy.
|
|
257
279
|
|
|
258
|
-
- [
|
|
259
|
-
- [
|
|
260
|
-
- [
|
|
261
|
-
- [
|
|
262
|
-
- [
|
|
263
|
-
- [
|
|
280
|
+
- [x] `.specxis/` folder convention documented
|
|
281
|
+
- [x] Commands: specxis-new, specxis-plan, specxis-implement, specxis-review, specxis-close, specxis-debt
|
|
282
|
+
- [x] Skills: specxis, specxis-plan, specxis-review, specxis-close
|
|
283
|
+
- [x] `scripts/specxis-init.js` — creates .specxis/ structure in any project
|
|
284
|
+
- [x] `templates/specxis/` — proposal, spec, and tasks templates
|
|
285
|
+
- [x] `docs/specxis.md` — when to use SDD vs direct implementation
|
|
264
286
|
- [ ] Integration guide for Lexis-One private config
|
|
265
287
|
|
|
266
288
|
---
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
name = "lexis-two-help"
|
|
2
|
+
description = "Quick reference for lexis-two levels, skills, and commands"
|
|
3
|
+
prompt = "Show the lexis-two quick reference. One shot, change nothing: do not switch mode, write flag files, or persist anything. Levels: /lexis-two lite, /lexis-two (full, default), /lexis-two ultra. Commands: /lexis-two-review, /lexis-two-audit, /lexis-two-debt, /lexis-two-plan, /lexis-two-security, /lexis-two-help."
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
name = "lexis-two"
|
|
2
|
+
description = "Switch lexis-two intensity level (lite/full/ultra/off)"
|
|
3
|
+
prompt = "Switch to lexis-two {{args}} mode. If no level specified, use full. Lazy senior dev mode, before any code: does it need to exist at all (YAGNI)? Does the standard library do it? A native platform feature? Can it be one line? Build the minimum that works. No unrequested abstractions, no avoidable dependencies, no boilerplate. Mark intentional simplifications with a lexis: comment."
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
name = "lexis"
|
|
2
|
+
description = "Manage Lexis senior dev mode, intensity levels, and quality/security tools"
|
|
3
|
+
prompt = "Manage Lexis senior dev mode. Handle the requested subcommand: plan (p), review (r), audit (a), debt (d), security (s), help (h), status, or intensity level (lite/full/ultra/off)."
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@draig/lexis-two",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "The simple way to obtain the best code. Portable rules, skills, and slash commands for AI agents with lowest tokens usage.",
|
|
5
5
|
"main": "./.opencode/plugins/lexis-two.mjs",
|
|
6
6
|
"exports": {
|
|
@@ -16,8 +16,11 @@
|
|
|
16
16
|
".opencode/plugins/lexis-two.mjs",
|
|
17
17
|
".opencode/plugins/lexis-two-tui.mjs",
|
|
18
18
|
".opencode/command/",
|
|
19
|
+
"commands/",
|
|
19
20
|
"hooks/",
|
|
20
|
-
"skills/"
|
|
21
|
+
"skills/",
|
|
22
|
+
"templates/",
|
|
23
|
+
"scripts/"
|
|
21
24
|
],
|
|
22
25
|
"keywords": [
|
|
23
26
|
"pi-package",
|
|
@@ -27,6 +30,7 @@
|
|
|
27
30
|
],
|
|
28
31
|
"license": "MIT",
|
|
29
32
|
"scripts": {
|
|
33
|
+
"postinstall": "node scripts/opencode-wrapper-postinstall.mjs",
|
|
30
34
|
"test": "node --test tests/*.test.js && npm test --prefix pi-extension",
|
|
31
35
|
"benchmark:opencode-go": "node benchmarks/benchmark-opencode-go.js --repeat 3 --write-md",
|
|
32
36
|
"benchmark:report": "node benchmarks/render-opencode-go-report.js",
|
|
@@ -0,0 +1,82 @@
|
|
|
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);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Patch OpenCode's npm cache wrapper package.json after install.
|
|
3
|
+
//
|
|
4
|
+
// OpenCode installs scoped plugins into ~/.cache/opencode/packages/@scope/pkg@latest/
|
|
5
|
+
// with a wrapper package.json that only lists dependencies. At runtime the loader
|
|
6
|
+
// reads that wrapper (not node_modules/@scope/pkg/package.json), so exports/main
|
|
7
|
+
// are missing and the plugin fails with "runtime load failed".
|
|
8
|
+
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
|
|
13
|
+
const pkgRoot = path.dirname(path.join(fileURLToPath(import.meta.url), ".."));
|
|
14
|
+
const pkgJsonPath = path.join(pkgRoot, "package.json");
|
|
15
|
+
|
|
16
|
+
function isOpenCodeWrapperDir(dir) {
|
|
17
|
+
const normalized = dir.replace(/\\/g, "/");
|
|
18
|
+
return normalized.includes("/packages/") && normalized.endsWith("@latest");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function patchWrapperPackageJson(wrapperDir, packageName) {
|
|
22
|
+
const wrapperPkgPath = path.join(wrapperDir, "package.json");
|
|
23
|
+
if (!fs.existsSync(wrapperPkgPath)) return false;
|
|
24
|
+
|
|
25
|
+
const wrapper = JSON.parse(fs.readFileSync(wrapperPkgPath, "utf8"));
|
|
26
|
+
const pluginBase = `./node_modules/${packageName}/.opencode/plugins`;
|
|
27
|
+
const next = {
|
|
28
|
+
...wrapper,
|
|
29
|
+
main: `${pluginBase}/lexis-two.mjs`,
|
|
30
|
+
exports: {
|
|
31
|
+
".": `${pluginBase}/lexis-two.mjs`,
|
|
32
|
+
"./server": `${pluginBase}/lexis-two.mjs`,
|
|
33
|
+
"./tui": `${pluginBase}/lexis-two-tui.mjs`,
|
|
34
|
+
},
|
|
35
|
+
"oc-plugin": ["server", "tui"],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
fs.writeFileSync(wrapperPkgPath, `${JSON.stringify(next, null, 2)}\n`);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
|
|
44
|
+
const wrapperDir = path.resolve(pkgRoot, "../..");
|
|
45
|
+
if (!isOpenCodeWrapperDir(wrapperDir)) process.exit(0);
|
|
46
|
+
patchWrapperPackageJson(wrapperDir, pkg.name);
|
|
47
|
+
} catch {
|
|
48
|
+
// lexis: postinstall is best-effort — normal npm installs must not fail
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// scripts/specxis-debt.js
|
|
2
|
+
// Portable Node.js script to scan the codebase for "// lexis:" comments
|
|
3
|
+
// and sync them with .specxis/debt.md.
|
|
4
|
+
// Works on Windows, macOS, and Linux.
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
const DEBT_FILE = '.specxis/debt.md';
|
|
10
|
+
|
|
11
|
+
// Recursive directory scan
|
|
12
|
+
function scanDir(dir, fileList = []) {
|
|
13
|
+
if (!fs.existsSync(dir)) return fileList;
|
|
14
|
+
const files = fs.readdirSync(dir);
|
|
15
|
+
for (const file of files) {
|
|
16
|
+
const filePath = path.join(dir, file);
|
|
17
|
+
const stat = fs.statSync(filePath);
|
|
18
|
+
if (stat.isDirectory()) {
|
|
19
|
+
// Skip common ignore folders
|
|
20
|
+
if (['node_modules', '.git', '.specxis', '.astro', 'dist', 'build', '.cache'].includes(file)) continue;
|
|
21
|
+
scanDir(filePath, fileList);
|
|
22
|
+
} else {
|
|
23
|
+
// Only scan relevant code files
|
|
24
|
+
if (['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(path.extname(file))) {
|
|
25
|
+
fileList.push(filePath);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return fileList;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function findLexisComments() {
|
|
33
|
+
const files = scanDir('.');
|
|
34
|
+
const comments = [];
|
|
35
|
+
const regex = /\/\/\s*lexis:\s*(.*)/gi;
|
|
36
|
+
|
|
37
|
+
for (const file of files) {
|
|
38
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
39
|
+
const lines = content.split(/\r?\n/);
|
|
40
|
+
lines.forEach((line, index) => {
|
|
41
|
+
let match;
|
|
42
|
+
// Reset regex lastIndex
|
|
43
|
+
regex.lastIndex = 0;
|
|
44
|
+
while ((match = regex.exec(line)) !== null) {
|
|
45
|
+
comments.push({
|
|
46
|
+
file: file.replace(/\\/g, '/'), // normalize to forward slashes
|
|
47
|
+
line: index + 1,
|
|
48
|
+
comment: match[1].trim()
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return comments;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function syncDebt() {
|
|
57
|
+
if (!fs.existsSync(DEBT_FILE)) {
|
|
58
|
+
console.error(`Error: ${DEBT_FILE} does not exist. Run specxis-init first.`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const found = findLexisComments();
|
|
63
|
+
console.log(`Found ${found.length} '// lexis:' comments in codebase.`);
|
|
64
|
+
|
|
65
|
+
let debtContent = fs.readFileSync(DEBT_FILE, 'utf8');
|
|
66
|
+
|
|
67
|
+
// We want to reconstruct or append to .specxis/debt.md.
|
|
68
|
+
// Let's create a prioritized ledger as described in SPECXIS.md.
|
|
69
|
+
// Categories:
|
|
70
|
+
// - Immediate: shortcuts causing pain or blocking features
|
|
71
|
+
// - Next sprint: shortcuts with a known ceiling approaching
|
|
72
|
+
// - Backlog: fine for now, revisit at scale
|
|
73
|
+
// - Permanent: intentional, no action needed
|
|
74
|
+
|
|
75
|
+
const immediate = [];
|
|
76
|
+
const nextSprint = [];
|
|
77
|
+
const backlog = [];
|
|
78
|
+
const permanent = [];
|
|
79
|
+
|
|
80
|
+
found.forEach(item => {
|
|
81
|
+
const text = item.comment.toLowerCase();
|
|
82
|
+
const entry = `- [ ] **${item.file}:${item.line}**: ${item.comment}`;
|
|
83
|
+
|
|
84
|
+
if (text.includes('immediate') || text.includes('critical') || text.includes('pain') || text.includes('block')) {
|
|
85
|
+
immediate.push(entry);
|
|
86
|
+
} else if (text.includes('sprint') || text.includes('soon') || text.includes('ceiling')) {
|
|
87
|
+
nextSprint.push(entry);
|
|
88
|
+
} else if (text.includes('permanent') || text.includes('intentional') || text.includes('no action')) {
|
|
89
|
+
permanent.push(`- **${item.file}:${item.line}**: ${item.comment} (Permanent)`);
|
|
90
|
+
} else {
|
|
91
|
+
backlog.push(entry);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const header = `# Specxis Debt Ledger
|
|
96
|
+
|
|
97
|
+
Consolidated // lexis: comments across all features.
|
|
98
|
+
Updated automatically by /specxis-debt and /specxis-close.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Prioritized Ledger
|
|
103
|
+
|
|
104
|
+
### Immediate (shortcuts causing pain or blocking features)
|
|
105
|
+
${immediate.length > 0 ? immediate.join('\n') : '*No immediate debt found.*'}
|
|
106
|
+
|
|
107
|
+
### Next Sprint (shortcuts with a known ceiling approaching)
|
|
108
|
+
${nextSprint.length > 0 ? nextSprint.join('\n') : '*No next sprint debt found.*'}
|
|
109
|
+
|
|
110
|
+
### Backlog (fine for now, revisit at scale)
|
|
111
|
+
${backlog.length > 0 ? backlog.join('\n') : '*No backlog debt found.*'}
|
|
112
|
+
|
|
113
|
+
### Permanent (intentional, no action needed)
|
|
114
|
+
${permanent.length > 0 ? permanent.join('\n') : '*No permanent debt found.*'}
|
|
115
|
+
`;
|
|
116
|
+
|
|
117
|
+
fs.writeFileSync(DEBT_FILE, header);
|
|
118
|
+
console.log(`Updated ${DEBT_FILE} with prioritized ledger.`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
syncDebt();
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// scripts/specxis-init.js
|
|
2
|
+
// Initializes .specxis/ folder structure in the current project.
|
|
3
|
+
// Run with: node scripts/specxis-init.js
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const dirs = [
|
|
9
|
+
'.specxis/active',
|
|
10
|
+
'.specxis/archive',
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const debtTemplate = `# Specxis Debt Ledger
|
|
14
|
+
|
|
15
|
+
Consolidated // lexis: comments across all features.
|
|
16
|
+
Updated automatically by /specxis-debt and /specxis-close.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<!-- Entries added by specxis-close and specxis-debt commands -->
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
for (const dir of dirs) {
|
|
24
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
25
|
+
console.log(`created ${dir}/`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const debtPath = '.specxis/debt.md';
|
|
29
|
+
if (!fs.existsSync(debtPath)) {
|
|
30
|
+
fs.writeFileSync(debtPath, debtTemplate);
|
|
31
|
+
console.log(`created ${debtPath}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Add .specxis/archive to .gitignore if not already there
|
|
35
|
+
// (active specs stay in git; archive is optional)
|
|
36
|
+
const gitignorePath = '.gitignore';
|
|
37
|
+
if (fs.existsSync(gitignorePath)) {
|
|
38
|
+
const content = fs.readFileSync(gitignorePath, 'utf8');
|
|
39
|
+
if (!content.includes('.specxis/archive')) {
|
|
40
|
+
fs.appendFileSync(gitignorePath, '\n# Specxis archived specs (optional)\n# .specxis/archive\n');
|
|
41
|
+
console.log('added .specxis/archive comment to .gitignore');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log('\nSpecxis initialized. Run /specxis-new to create your first spec.');
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specxis
|
|
3
|
+
description: Manage the Specxis Spec-Driven Development lifecycle (new, plan, implement, review, close, debt, status)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are the Specxis orchestrator. Handle the requested subcommand or action:
|
|
7
|
+
|
|
8
|
+
### 1. STATUS (default: `/specxis` or `/specxis status`)
|
|
9
|
+
- List folders in `.specxis/active/`. For each, show: slug, status (draft/agreed/implementing/done), task progress (X/Y), and if review.md exists.
|
|
10
|
+
- List count of archived specs in `.specxis/archive/`.
|
|
11
|
+
- Show open items in `.specxis/debt.md` by priority.
|
|
12
|
+
|
|
13
|
+
### 2. NEW (`/specxis new <slug>`)
|
|
14
|
+
- Ask for slug if not provided (kebab-case, e.g. "user-auth").
|
|
15
|
+
- Create `.specxis/active/[slug]/proposal.md` from the template in `node_modules/@draig/lexis-two/templates/specxis/proposal.md` (or local path).
|
|
16
|
+
- Apply the lazy check: ask "Does this need to exist? What's the minimum?". Fill what you know, leave unknowns blank.
|
|
17
|
+
|
|
18
|
+
### 3. PLAN (`/specxis plan <slug>`)
|
|
19
|
+
- Read `.specxis/active/[slug]/proposal.md`.
|
|
20
|
+
- Apply the lazy hierarchy to every requirement.
|
|
21
|
+
- Create `.specxis/active/[slug]/spec.md` (MUST/SHOULD/MAY) and `.specxis/active/[slug]/tasks.md` (max 10 tasks, one per file/function).
|
|
22
|
+
- Ask for approval before starting implementation.
|
|
23
|
+
|
|
24
|
+
### 4. IMPLEMENT (`/specxis implement <slug>`)
|
|
25
|
+
- Read `.specxis/active/[slug]/tasks.md`. Find the first unchecked task (`- [ ]`).
|
|
26
|
+
- Implement it following spec.md MUST requirements and AGENTS.md rules.
|
|
27
|
+
- Mark as done (`- [x]`), add `// lexis:` comments for deviations, and update "Lexis Tags Added" in tasks.md.
|
|
28
|
+
- Implement only one task per run. Stop and report.
|
|
29
|
+
|
|
30
|
+
### 5. REVIEW (`/specxis review <slug>`)
|
|
31
|
+
- Read `.specxis/active/[slug]/spec.md` and run `git diff HEAD`.
|
|
32
|
+
- Evaluate spec compliance, SHOULD compliance, AGENTS.md rules, and tests.
|
|
33
|
+
- Write findings to `.specxis/active/[slug]/review.md` (Severity: Critical/High/Medium/Low, Location, Issue, Fix).
|
|
34
|
+
|
|
35
|
+
### 6. CLOSE (`/specxis close <slug>`)
|
|
36
|
+
- Verify all tasks are checked and no Critical/High findings are open.
|
|
37
|
+
- Move `.specxis/active/[slug]/` to `.specxis/archive/[slug]/`.
|
|
38
|
+
- Collect all `// lexis:` comments added during this feature and append them to `.specxis/debt.md`.
|
|
39
|
+
|
|
40
|
+
### 7. DEBT (`/specxis debt`)
|
|
41
|
+
- Run `node node_modules/@draig/lexis-two/scripts/specxis-debt.js` (or local path) to scan the codebase and update `.specxis/debt.md` with a prioritized ledger.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
If `.specxis/` does not exist, suggest running `node node_modules/@draig/lexis-two/scripts/specxis-init.js` first.
|
|
46
|
+
Respond in Spanish. All code, comments, JSDoc in English.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Proposal: [feature-slug]
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
One sentence — what does this feature do for the user?
|
|
5
|
+
|
|
6
|
+
## Lazy Check
|
|
7
|
+
Answer before writing any code:
|
|
8
|
+
- Does this need to exist? Could the requirement be met another way?
|
|
9
|
+
- Does stdlib, the framework, or an installed dep already cover it?
|
|
10
|
+
- What is the absolute minimum that satisfies the requirement?
|
|
11
|
+
|
|
12
|
+
## Context
|
|
13
|
+
- Affected domain / feature folder:
|
|
14
|
+
- Related existing files:
|
|
15
|
+
- Dependencies already installed that are relevant:
|
|
16
|
+
|
|
17
|
+
## Out of Scope (YAGNI)
|
|
18
|
+
Explicitly list what this proposal does NOT include.
|
|
19
|
+
|
|
20
|
+
## Open Questions
|
|
21
|
+
Anything that needs clarification before planning.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Review: [feature-slug]
|
|
2
|
+
|
|
3
|
+
> Generated by /specxis-review on close.
|
|
4
|
+
|
|
5
|
+
## Summary
|
|
6
|
+
One sentence on overall quality.
|
|
7
|
+
|
|
8
|
+
## Spec Compliance
|
|
9
|
+
Did the implementation follow spec.md?
|
|
10
|
+
- MUST requirements met: yes / no / partial
|
|
11
|
+
- Deviations: list with // lexis: references
|
|
12
|
+
|
|
13
|
+
## Debt Registered
|
|
14
|
+
// lexis: comments added during this feature — moved to .specxis/debt.md.
|
|
15
|
+
|
|
16
|
+
## Next Steps
|
|
17
|
+
Recommended follow-up actions in priority order.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Spec: [feature-slug]
|
|
2
|
+
|
|
3
|
+
> Status: draft | agreed | implementing | done
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
### MUST (non-negotiable)
|
|
8
|
+
- [ ]
|
|
9
|
+
|
|
10
|
+
### SHOULD (strong preference, can deviate with // lexis: comment)
|
|
11
|
+
- [ ]
|
|
12
|
+
|
|
13
|
+
### MAY (optional, implement only if trivial)
|
|
14
|
+
- [ ]
|
|
15
|
+
|
|
16
|
+
## Constraints
|
|
17
|
+
- Performance:
|
|
18
|
+
- Security:
|
|
19
|
+
- Accessibility:
|
|
20
|
+
- TypeScript: strict — no any, as, or ! without // lexis: explanation
|
|
21
|
+
|
|
22
|
+
## Acceptance Criteria
|
|
23
|
+
How do we know this is done?
|
|
24
|
+
- [ ]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Tasks: [feature-slug]
|
|
2
|
+
|
|
3
|
+
> Generated by /specxis-plan. Each task maps to one file or one function.
|
|
4
|
+
> Do not start implementing until tasks are agreed.
|
|
5
|
+
|
|
6
|
+
## Tasks
|
|
7
|
+
|
|
8
|
+
- [ ] task-001:
|
|
9
|
+
- [ ] task-002:
|
|
10
|
+
- [ ] task-003:
|
|
11
|
+
|
|
12
|
+
## Implementation Notes
|
|
13
|
+
Decisions made during planning that affect implementation.
|
|
14
|
+
|
|
15
|
+
## Lexis Tags Added
|
|
16
|
+
// lexis: comments added during implementation (updated as work progresses).
|