@teurons/vds 0.0.1 → 0.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.
- package/README.md +52 -0
- package/dist/vds.js +56 -6
- package/dist/vds_mapper.wasm +0 -0
- package/package.json +2 -14
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# @teurons/vds
|
|
2
|
+
|
|
3
|
+
The `vds` command. It starts, checks and indexes a VDS workspace on your machine.
|
|
4
|
+
|
|
5
|
+
VDS keeps a product's spec as files: capabilities that hold rules written in EARS,
|
|
6
|
+
scenarios in Gherkin, and flows that point at those rules in order.
|
|
7
|
+
This package is an early alpha.
|
|
8
|
+
|
|
9
|
+
## Set it up with your AI agent
|
|
10
|
+
|
|
11
|
+
Copy this prompt into Claude Code, Codex or any coding agent, run from the root of your project:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
Set up VDS in this project.
|
|
15
|
+
|
|
16
|
+
1. Run `npx -y @teurons/vds init vds-workspace`. It creates the
|
|
17
|
+
capabilities, flows and scenarios folders, a VDS.md guide and a .vds.json.
|
|
18
|
+
If it says a workspace already exists, stop and tell me what it found.
|
|
19
|
+
2. Add `"vds": "vds"` to package.json scripts and @teurons/vds to
|
|
20
|
+
devDependencies if this project uses npm, pnpm or yarn. Otherwise skip this.
|
|
21
|
+
3. Read vds-workspace/VDS.md and follow it from now on whenever you work on
|
|
22
|
+
the spec.
|
|
23
|
+
4. Add a short section to this project's AGENTS.md (or CLAUDE.md if that is
|
|
24
|
+
what exists) saying: the product spec lives in vds-workspace; read
|
|
25
|
+
vds-workspace/VDS.md before changing it; run `vds index vds-workspace`
|
|
26
|
+
first and `vds check vds-workspace` before finishing.
|
|
27
|
+
5. Run `npx @teurons/vds check vds-workspace` and confirm it prints valid.
|
|
28
|
+
6. Tell me what you created and changed, file by file.
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Commands
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
npx @teurons/vds init [folder] # start a workspace (never overwrites one)
|
|
35
|
+
npx @teurons/vds check [folder] # print every problem; exit 1 if any
|
|
36
|
+
npx @teurons/vds index [folder] # print the index: every flow and rule, one line each
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`folder` defaults to the current folder.
|
|
40
|
+
|
|
41
|
+
## A workspace
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
vds-workspace/
|
|
45
|
+
VDS.md how agents and people work on this spec
|
|
46
|
+
.vds.json local settings, such as the studio port
|
|
47
|
+
capabilities/<CODE>.yaml rules, each one EARS statement with an id like ONB-01
|
|
48
|
+
flows/<id>.yaml versioned flows whose steps point at rule ids
|
|
49
|
+
scenarios/<RULE-ID>.feature Gherkin scenarios, one file per rule
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Needs Node 20 or later.
|
package/dist/vds.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/bin.js
|
|
4
4
|
import { readdirSync, readFileSync as readFileSync2 } from "node:fs";
|
|
5
|
-
import { join, resolve } from "node:path";
|
|
5
|
+
import { join as join2, resolve } from "node:path";
|
|
6
6
|
|
|
7
7
|
// ../../specs/js/load.js
|
|
8
8
|
import { readFileSync } from "node:fs";
|
|
@@ -93,22 +93,72 @@ function loadMapper() {
|
|
|
93
93
|
return instantiate(mapperModule());
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
// src/
|
|
96
|
+
// src/init.js
|
|
97
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
98
|
+
import { createServer } from "node:net";
|
|
99
|
+
import { join } from "node:path";
|
|
97
100
|
var FOLDERS = ["capabilities", "flows", "scenarios"];
|
|
101
|
+
var FIRST_PORT = 4600;
|
|
102
|
+
var GUIDE = `# Working in this VDS workspace
|
|
103
|
+
|
|
104
|
+
This folder holds the product's requirements, flows and scenarios as plain files.
|
|
105
|
+
Read and write them with the vds command.
|
|
106
|
+
|
|
107
|
+
## Layout
|
|
108
|
+
|
|
109
|
+
- capabilities/<CODE>.yaml: one capability and its requirements (ids like ONB-01).
|
|
110
|
+
- flows/<id>.yaml: a journey made of states; each state points at requirement ids.
|
|
111
|
+
- scenarios/<REQ-ID>.feature: Given, When, Then scenarios for one requirement.
|
|
112
|
+
|
|
113
|
+
## How to work
|
|
114
|
+
|
|
115
|
+
1. Run \`vds index\` first. It prints one line per flow and requirement, so you know what exists.
|
|
116
|
+
2. Open one file at a time. Read only the file you are changing.
|
|
117
|
+
3. Write requirements in EARS: "When <trigger>, the system SHALL <response>." The system is always the subject.
|
|
118
|
+
4. Point flows at requirement ids. A state lists the ids it needs under \`requirements:\`.
|
|
119
|
+
5. Run \`vds check\` before you finish. It prints "valid" when nothing is wrong; fix every problem it lists.
|
|
120
|
+
`;
|
|
121
|
+
async function freePort() {
|
|
122
|
+
for (let port = FIRST_PORT; ; port++) {
|
|
123
|
+
const free = await new Promise((resolve2) => {
|
|
124
|
+
const server = createServer();
|
|
125
|
+
server.once("error", () => resolve2(false));
|
|
126
|
+
server.listen(port, () => server.close(() => resolve2(true)));
|
|
127
|
+
});
|
|
128
|
+
if (free) return port;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async function init(root) {
|
|
132
|
+
const found = [...FOLDERS, "VDS.md"].filter((name) => existsSync(join(root, name)));
|
|
133
|
+
if (found.length > 0) {
|
|
134
|
+
console.error(`nothing changed; this folder already has: ${found.join(", ")}`);
|
|
135
|
+
return 1;
|
|
136
|
+
}
|
|
137
|
+
const port = await freePort();
|
|
138
|
+
for (const dir of FOLDERS) mkdirSync(join(root, dir), { recursive: true });
|
|
139
|
+
writeFileSync(join(root, "VDS.md"), GUIDE);
|
|
140
|
+
writeFileSync(join(root, ".vds.json"), `${JSON.stringify({ port })}
|
|
141
|
+
`);
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/bin.js
|
|
146
|
+
var FOLDERS2 = ["capabilities", "flows", "scenarios"];
|
|
98
147
|
function readWorkspace(root) {
|
|
99
148
|
const files = {};
|
|
100
|
-
for (const dir of
|
|
149
|
+
for (const dir of FOLDERS2) {
|
|
101
150
|
let names = [];
|
|
102
151
|
try {
|
|
103
|
-
names = readdirSync(
|
|
152
|
+
names = readdirSync(join2(root, dir));
|
|
104
153
|
} catch {
|
|
105
154
|
continue;
|
|
106
155
|
}
|
|
107
|
-
for (const name of names) files[`${dir}/${name}`] = readFileSync2(
|
|
156
|
+
for (const name of names) files[`${dir}/${name}`] = readFileSync2(join2(root, dir, name), "utf8");
|
|
108
157
|
}
|
|
109
158
|
return files;
|
|
110
159
|
}
|
|
111
160
|
async function main([command, folder = "."]) {
|
|
161
|
+
if (command === "init") return init(resolve(folder));
|
|
112
162
|
const mapper = await loadMapper();
|
|
113
163
|
const files = readWorkspace(resolve(folder));
|
|
114
164
|
if (command === "check") {
|
|
@@ -126,7 +176,7 @@ async function main([command, folder = "."]) {
|
|
|
126
176
|
process.stdout.write(mapper.v2Index(files));
|
|
127
177
|
return 0;
|
|
128
178
|
}
|
|
129
|
-
console.error("usage: vds check [folder] | vds index [folder]");
|
|
179
|
+
console.error("usage: vds init [folder] | vds check [folder] | vds index [folder]");
|
|
130
180
|
return 2;
|
|
131
181
|
}
|
|
132
182
|
process.exitCode = await main(process.argv.slice(2));
|
package/dist/vds_mapper.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teurons/vds",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "The vds command: check, index and run a VDS workspace on your machine.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,25 +12,13 @@
|
|
|
12
12
|
"engines": {
|
|
13
13
|
"node": ">=20"
|
|
14
14
|
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "node build.mjs",
|
|
17
|
-
"test": "vitest run",
|
|
18
|
-
"prepack": "node build.mjs",
|
|
19
|
-
"release": "node release.mjs"
|
|
20
|
-
},
|
|
21
15
|
"dependencies": {},
|
|
22
|
-
"devDependencies": {
|
|
23
|
-
"@vds/mapper": "workspace:*",
|
|
24
|
-
"esbuild": "0.28.1",
|
|
25
|
-
"vitest": "5.0.1"
|
|
26
|
-
},
|
|
27
16
|
"license": "UNLICENSED",
|
|
28
17
|
"repository": {
|
|
29
18
|
"type": "git",
|
|
30
19
|
"url": "git+https://github.com/teurons/vds.git"
|
|
31
20
|
},
|
|
32
21
|
"publishConfig": {
|
|
33
|
-
"access": "public"
|
|
34
|
-
"tag": "next"
|
|
22
|
+
"access": "public"
|
|
35
23
|
}
|
|
36
24
|
}
|