@xn-intenton-z2a/agentic-lib 7.2.12 → 7.2.13
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/bin/agentic-lib.js +1 -0
- package/package.json +1 -1
- package/src/actions/agentic-step/tasks/transform.js +1 -1
- package/src/agents/agent-apply-fix.md +3 -3
- package/src/agents/agent-issue-resolution.md +14 -11
- package/src/scripts/build-web.cjs +52 -51
- package/src/seeds/zero-README.md +14 -12
- package/src/seeds/zero-index.html +4 -4
- package/src/seeds/zero-lib.js +4 -0
- package/src/seeds/zero-main.js +20 -7
- package/src/seeds/zero-package.json +2 -2
- package/src/seeds/zero-playwright.config.js +2 -2
- package/src/seeds/zero-web.test.js +8 -2
package/bin/agentic-lib.js
CHANGED
|
@@ -720,6 +720,7 @@ function initPurge(seedsDir, missionName, initTimestamp) {
|
|
|
720
720
|
"zero-main.js": "src/lib/main.js",
|
|
721
721
|
"zero-main.test.js": "tests/unit/main.test.js",
|
|
722
722
|
"zero-index.html": "src/web/index.html",
|
|
723
|
+
"zero-lib.js": "src/web/lib.js",
|
|
723
724
|
"zero-web.test.js": "tests/unit/web.test.js",
|
|
724
725
|
"zero-behaviour.test.js": "tests/behaviour/homepage.test.js",
|
|
725
726
|
"zero-playwright.config.js": "playwright.config.js",
|
package/package.json
CHANGED
|
@@ -120,7 +120,7 @@ export async function transform(context) {
|
|
|
120
120
|
`## Website Files (${webFiles.length})`,
|
|
121
121
|
"The website in `src/web/` uses the JS library.",
|
|
122
122
|
"When transforming source code, also update the website to use the library's new/changed features.",
|
|
123
|
-
"
|
|
123
|
+
"`src/web/lib.js` re-exports from `../lib/main.js` so the page imports the real library directly. Keep `main.js` browser-safe (guard Node APIs behind `typeof process` checks). NEVER duplicate library functions inline in the web page.",
|
|
124
124
|
...webFiles.map((f) => `### ${f.name}\n\`\`\`\n${f.content}\n\`\`\``),
|
|
125
125
|
"",
|
|
126
126
|
]
|
|
@@ -18,9 +18,9 @@ A fix is never just one file. These layers form a single unit — if you change
|
|
|
18
18
|
|
|
19
19
|
- **Library source** (`src/lib/main.js`) — the core implementation
|
|
20
20
|
- **Unit tests** (`tests/unit/`) — test every function at the API level with exact values and edge cases
|
|
21
|
-
- **Website** (`src/web/index.html` and
|
|
22
|
-
**NEVER duplicate library functions inline in the web page** —
|
|
23
|
-
|
|
21
|
+
- **Website** (`src/web/index.html` and `src/web/lib.js`) — `lib.js` re-exports from `../lib/main.js`, so the
|
|
22
|
+
page imports the **real library** directly. **NEVER duplicate library functions inline in the web page** —
|
|
23
|
+
add exports to `main.js` and they are automatically available via `lib.js`.
|
|
24
24
|
- **Website unit tests** (`tests/unit/web.test.js`) — verify HTML structure and library wiring
|
|
25
25
|
- **Behaviour tests** (`tests/behaviour/`) — Playwright tests that load the website in a real browser
|
|
26
26
|
and verify features work at a high navigational level (demo output visible, interactive elements work).
|
|
@@ -79,23 +79,26 @@ automatically (from `docs/` via `npm run build:web`).
|
|
|
79
79
|
|
|
80
80
|
### How the library connects to the website
|
|
81
81
|
|
|
82
|
-
- `src/lib/main.js` is
|
|
83
|
-
- `
|
|
84
|
-
- `src/web/index.html` imports
|
|
85
|
-
- The website
|
|
82
|
+
- `src/lib/main.js` is browser-safe — in Node it reads `package.json` via `createRequire`, in the browser via `fetch`
|
|
83
|
+
- `src/web/lib.js` re-exports from `../lib/main.js` — the page imports the **real library**
|
|
84
|
+
- `src/web/index.html` imports `./lib.js` via `<script type="module">` to access the library directly
|
|
85
|
+
- The website works at rest (no build step needed for development)
|
|
86
|
+
- `npm run build:web` generates `docs/lib.js` as a self-contained module for production (GitHub Pages)
|
|
86
87
|
|
|
87
88
|
### What to do with the website
|
|
88
89
|
|
|
89
|
-
- **Use the library**: Import
|
|
90
|
+
- **Use the library**: Import from `./lib.js` which re-exports from `../lib/main.js` — call library functions directly
|
|
90
91
|
- **Show real results**: Display actual output from library functions, not placeholder text
|
|
91
92
|
- When you add or change library functions, update the website to reflect them
|
|
92
93
|
- **Demonstrate features**: Each significant library feature should be visible and usable on the website.
|
|
93
94
|
Behaviour tests will verify these demonstrations work, so make them testable (use IDs, structured output).
|
|
95
|
+
- **Keep main.js browser-safe**: Do not add Node-only top-level code (e.g. bare `require`, `process.argv` checks)
|
|
96
|
+
without guarding them behind `typeof process !== "undefined"` checks
|
|
94
97
|
|
|
95
98
|
### CRITICAL: Never duplicate library code in the web page
|
|
96
99
|
|
|
97
|
-
**Do NOT copy or recreate library functions inline in `src/web/index.html`.** The web page
|
|
98
|
-
|
|
100
|
+
**Do NOT copy or recreate library functions inline in `src/web/index.html`.** The web page imports the
|
|
101
|
+
library directly via `src/web/lib.js` → `src/lib/main.js`. There is no reason to duplicate.
|
|
99
102
|
|
|
100
103
|
Why this matters:
|
|
101
104
|
- Unit tests test `src/lib/main.js` directly
|
|
@@ -104,11 +107,11 @@ Why this matters:
|
|
|
104
107
|
- The two copies can diverge silently, and tests pass even when the real library is broken
|
|
105
108
|
|
|
106
109
|
How to share code between library and web:
|
|
107
|
-
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
- `src/web/lib.js` re-exports everything from `../lib/main.js` — add exports to `main.js` and they are
|
|
111
|
+
automatically available to the web page
|
|
112
|
+
- If adding a new exported function to `main.js`, make sure it is browser-safe (no bare Node API calls)
|
|
110
113
|
- The behaviour test imports `getIdentity()` from `src/lib/main.js` and asserts the page displays the same
|
|
111
|
-
version — this coupling test proves the
|
|
114
|
+
version — this coupling test proves the import chain is wired up correctly
|
|
112
115
|
|
|
113
116
|
### Guidelines
|
|
114
117
|
|
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
//
|
|
7
7
|
// Builds the docs/ directory for web serving:
|
|
8
8
|
// 1. Creates docs/ and copies src/web/* into it
|
|
9
|
-
// 2. Generates docs/lib
|
|
10
|
-
//
|
|
9
|
+
// 2. Generates docs/lib.js — a self-contained browser module with:
|
|
10
|
+
// - Package identity (name, version, description) from package.json
|
|
11
|
+
// - Browser-safe exported functions extracted from src/lib/main.js
|
|
12
|
+
// This overwrites the src/web/lib.js re-export (which only works in dev).
|
|
11
13
|
//
|
|
12
14
|
// This file is part of the Example Suite for `agentic-lib` see: https://github.com/xn-intenton-z2a/agentic-lib
|
|
13
15
|
// This file is licensed under the MIT License. For details, see LICENSE-MIT
|
|
@@ -34,64 +36,63 @@ if (fs.existsSync(webDir)) {
|
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
// Step 2: Generate docs/lib
|
|
39
|
+
// Step 2: Generate docs/lib.js — self-contained browser module
|
|
40
|
+
// This overwrites the re-export copied from src/web/lib.js above,
|
|
41
|
+
// replacing it with a standalone module that works on GitHub Pages
|
|
42
|
+
// (where src/lib/main.js and package.json are not available).
|
|
38
43
|
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
|
|
39
|
-
const
|
|
40
|
-
|
|
44
|
+
const sections = [];
|
|
45
|
+
|
|
46
|
+
// Identity exports from package.json
|
|
47
|
+
sections.push(
|
|
48
|
+
`export const name = ${JSON.stringify(pkg.name)};`,
|
|
49
|
+
`export const version = ${JSON.stringify(pkg.version)};`,
|
|
50
|
+
`export const description = ${JSON.stringify(pkg.description)};`,
|
|
51
|
+
"",
|
|
52
|
+
"export function getIdentity() {",
|
|
53
|
+
" return { name, version, description };",
|
|
54
|
+
"}"
|
|
41
55
|
);
|
|
42
|
-
fs.writeFileSync(path.join(docsDir, "lib-meta.js"), metaLines.join("\n") + "\n");
|
|
43
|
-
console.log("Wrote docs/lib-meta.js");
|
|
44
56
|
|
|
45
|
-
//
|
|
46
|
-
// Parse the main module for `export function` and `export async function` declarations
|
|
47
|
-
// and re-emit them as a standalone browser-compatible module.
|
|
57
|
+
// Extract browser-safe exported functions from src/lib/main.js
|
|
48
58
|
const mainPath = path.resolve("src", "lib", "main.js");
|
|
49
59
|
if (fs.existsSync(mainPath)) {
|
|
50
60
|
const mainSrc = fs.readFileSync(mainPath, "utf8");
|
|
51
|
-
|
|
52
|
-
const exportRegex = /^export\s+(async\s+)?function\s+(\w+)/gm;
|
|
53
|
-
const exportNames = [];
|
|
54
|
-
let match;
|
|
55
|
-
while ((match = exportRegex.exec(mainSrc)) !== null) {
|
|
56
|
-
exportNames.push(match[2]);
|
|
57
|
-
}
|
|
61
|
+
const lines = mainSrc.split("\n");
|
|
58
62
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
63
|
+
// Skip identity-related exports and the main/CLI function — only extract
|
|
64
|
+
// mission-specific exported functions (e.g. hammingDistance, etc.)
|
|
65
|
+
const SKIP_FUNCTIONS = new Set(["getIdentity", "main"]);
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < lines.length; i++) {
|
|
68
|
+
const fnMatch = lines[i].match(/^export\s+(async\s+)?function\s+(\w+)/);
|
|
69
|
+
if (fnMatch && !SKIP_FUNCTIONS.has(fnMatch[2])) {
|
|
70
|
+
// Collect the full function body by tracking brace depth
|
|
71
|
+
const fnLines = [lines[i]];
|
|
72
|
+
let braceDepth = 0;
|
|
73
|
+
for (let j = i; j < lines.length; j++) {
|
|
74
|
+
for (const ch of lines[j]) {
|
|
75
|
+
if (ch === "{") braceDepth++;
|
|
76
|
+
if (ch === "}") braceDepth--;
|
|
77
|
+
}
|
|
78
|
+
if (j > i) fnLines.push(lines[j]);
|
|
79
|
+
if (braceDepth === 0 && j >= i) {
|
|
80
|
+
break;
|
|
77
81
|
}
|
|
78
|
-
functionBodies.push(fnLines.join("\n"));
|
|
79
82
|
}
|
|
83
|
+
sections.push("");
|
|
84
|
+
sections.push(fnLines.join("\n"));
|
|
80
85
|
}
|
|
81
|
-
|
|
82
|
-
const header = [
|
|
83
|
-
"// docs/lib-browser.js",
|
|
84
|
-
"// Generated browser-compatible module exposing named exports from src/lib/main.js.",
|
|
85
|
-
"// Auto-generated by build-web.cjs — do not edit manually.",
|
|
86
|
-
"",
|
|
87
|
-
].join("\n");
|
|
88
|
-
|
|
89
|
-
fs.writeFileSync(
|
|
90
|
-
path.join(docsDir, "lib-browser.js"),
|
|
91
|
-
header + functionBodies.join("\n\n") + "\n"
|
|
92
|
-
);
|
|
93
|
-
console.log(
|
|
94
|
-
`Wrote docs/lib-browser.js (${exportNames.length} exports: ${exportNames.join(", ")})`
|
|
95
|
-
);
|
|
96
86
|
}
|
|
97
87
|
}
|
|
88
|
+
|
|
89
|
+
const header = [
|
|
90
|
+
"// docs/lib.js",
|
|
91
|
+
"// Self-contained browser module generated by build-web.cjs.",
|
|
92
|
+
"// Identity from package.json; functions extracted from src/lib/main.js.",
|
|
93
|
+
"// Do not edit — regenerate with: npm run build:web",
|
|
94
|
+
"",
|
|
95
|
+
].join("\n");
|
|
96
|
+
|
|
97
|
+
fs.writeFileSync(path.join(docsDir, "lib.js"), header + sections.join("\n") + "\n");
|
|
98
|
+
console.log("Wrote docs/lib.js");
|
package/src/seeds/zero-README.md
CHANGED
|
@@ -49,33 +49,35 @@ The pipeline runs as GitHub Actions workflows. An LLM supervisor gathers reposit
|
|
|
49
49
|
## File Layout
|
|
50
50
|
|
|
51
51
|
```
|
|
52
|
-
src/lib/main.js ← library (
|
|
53
|
-
src/web/index.html ← web page (
|
|
52
|
+
src/lib/main.js ← library (browser-safe: identity + mission functions)
|
|
53
|
+
src/web/index.html ← web page (imports ./lib.js)
|
|
54
|
+
src/web/lib.js ← browser entry point (re-exports from ../lib/main.js)
|
|
54
55
|
tests/unit/main.test.js ← unit tests (import main.js directly, test API-level detail)
|
|
55
56
|
tests/unit/web.test.js ← web structure tests (read index.html as text, verify wiring)
|
|
56
|
-
tests/behaviour/ ← Playwright E2E (
|
|
57
|
+
tests/behaviour/ ← Playwright E2E (serve from project root, import main.js for coupling)
|
|
57
58
|
docs/ ← build output (generated by npm run build:web)
|
|
58
|
-
docs/lib
|
|
59
|
+
docs/lib.js ← generated: self-contained module for GitHub Pages
|
|
59
60
|
```
|
|
60
61
|
|
|
61
|
-
These files form a **coupled unit**.
|
|
62
|
+
These files form a **coupled unit**. The library works in both Node and the browser:
|
|
62
63
|
|
|
63
|
-
- `src/lib/main.js`
|
|
64
|
-
- `
|
|
65
|
-
- `src/web/index.html` imports
|
|
64
|
+
- `src/lib/main.js` is browser-safe — in Node it reads `package.json` via `createRequire`, in the browser via `fetch`
|
|
65
|
+
- `src/web/lib.js` re-exports from `../lib/main.js` — the page imports the **real library**, not a generated copy
|
|
66
|
+
- `src/web/index.html` imports `./lib.js` → displays library identity on the page
|
|
66
67
|
- The behaviour test imports `getIdentity()` from `main.js` AND reads `#lib-version` from the rendered page → asserts they match
|
|
68
|
+
- `npm run build:web` generates `docs/lib.js` as a self-contained module for production (GitHub Pages)
|
|
67
69
|
|
|
68
|
-
This coupling
|
|
70
|
+
This coupling proves the web page consumes the real library. Mission-specific functions should follow the same path — never duplicate library logic inline in the web page.
|
|
69
71
|
|
|
70
72
|
## Test Strategy
|
|
71
73
|
|
|
72
74
|
| Test layer | What it tests | How it binds |
|
|
73
75
|
|------------|--------------|--------------|
|
|
74
76
|
| **Unit tests** (`tests/unit/main.test.js`) | Library API: return values, error types, edge cases | Imports directly from `src/lib/main.js` |
|
|
75
|
-
| **Web structure tests** (`tests/unit/web.test.js`) | HTML structure: expected elements, `lib
|
|
76
|
-
| **Behaviour tests** (`tests/behaviour/`) | End-to-end: page renders,
|
|
77
|
+
| **Web structure tests** (`tests/unit/web.test.js`) | HTML structure: expected elements, `lib.js` re-export | Reads `src/web/index.html` and `src/web/lib.js` as text |
|
|
78
|
+
| **Behaviour tests** (`tests/behaviour/`) | End-to-end: page renders, displays real library values | Playwright serves from project root; coupling test imports `getIdentity()` from `main.js` and asserts the page displays the same version |
|
|
77
79
|
|
|
78
|
-
The **coupling test** in the behaviour test is the key invariant: it proves the web page displays values from the actual library, not hardcoded or duplicated values.
|
|
80
|
+
The **coupling test** in the behaviour test is the key invariant: it proves the web page displays values from the actual library, not hardcoded or duplicated values. The page imports `lib.js` which re-exports from `main.js` which reads `package.json` — the same chain the unit tests exercise.
|
|
79
81
|
|
|
80
82
|
## Configuration
|
|
81
83
|
|
|
@@ -33,16 +33,16 @@
|
|
|
33
33
|
<p>This website uses the library. See <a href="https://github.com/xn-intenton-z2a/repository0">the repository</a> for source code and mission details.</p>
|
|
34
34
|
<script type="module">
|
|
35
35
|
try {
|
|
36
|
-
const { name, version, description } = await import('./lib
|
|
36
|
+
const { name, version, description } = await import('./lib.js');
|
|
37
37
|
document.getElementById('lib-name').textContent = name;
|
|
38
38
|
document.getElementById('lib-version').textContent = version;
|
|
39
39
|
document.getElementById('lib-description').textContent = description || '(no description)';
|
|
40
40
|
document.getElementById('demo-output').textContent = JSON.stringify({ name, version, description }, null, 2);
|
|
41
41
|
document.title = name + ' v' + version;
|
|
42
42
|
} catch (e) {
|
|
43
|
-
document.getElementById('lib-version').textContent = '(
|
|
44
|
-
document.getElementById('lib-description').textContent =
|
|
45
|
-
document.getElementById('demo-output').textContent = '
|
|
43
|
+
document.getElementById('lib-version').textContent = '(error)';
|
|
44
|
+
document.getElementById('lib-description').textContent = e.message;
|
|
45
|
+
document.getElementById('demo-output').textContent = 'Failed to load library: ' + e.message;
|
|
46
46
|
}
|
|
47
47
|
</script>
|
|
48
48
|
</body>
|
package/src/seeds/zero-main.js
CHANGED
|
@@ -3,11 +3,21 @@
|
|
|
3
3
|
// Copyright (C) 2025-2026 Polycode Limited
|
|
4
4
|
// src/lib/main.js
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
import { fileURLToPath } from "url";
|
|
6
|
+
const isNode = typeof process !== "undefined" && !!process.versions?.node;
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
let pkg;
|
|
9
|
+
if (isNode) {
|
|
10
|
+
const { createRequire } = await import("module");
|
|
11
|
+
const requireFn = createRequire(import.meta.url);
|
|
12
|
+
pkg = requireFn("../../package.json");
|
|
13
|
+
} else {
|
|
14
|
+
try {
|
|
15
|
+
const resp = await fetch(new URL("../../package.json", import.meta.url));
|
|
16
|
+
pkg = await resp.json();
|
|
17
|
+
} catch {
|
|
18
|
+
pkg = { name: document.title, version: "0.0.0", description: "" };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
11
21
|
|
|
12
22
|
export const name = pkg.name;
|
|
13
23
|
export const version = pkg.version;
|
|
@@ -29,7 +39,10 @@ export function main(args) {
|
|
|
29
39
|
console.log(`${name}@${version}`);
|
|
30
40
|
}
|
|
31
41
|
|
|
32
|
-
if (
|
|
33
|
-
const
|
|
34
|
-
|
|
42
|
+
if (isNode) {
|
|
43
|
+
const { fileURLToPath } = await import("url");
|
|
44
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
45
|
+
const args = process.argv.slice(2);
|
|
46
|
+
main(args);
|
|
47
|
+
}
|
|
35
48
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"build:web": "node .github/agentic-lib/scripts/build-web.cjs",
|
|
10
10
|
"test": "vitest --run tests/unit/*.test.js",
|
|
11
11
|
"test:unit": "vitest --run --coverage tests/unit/*.test.js",
|
|
12
|
-
"test:behaviour": "
|
|
12
|
+
"test:behaviour": "npx playwright test --config playwright.config.js",
|
|
13
13
|
"start": "npm run build:web && npx serve docs",
|
|
14
14
|
"start:cli": "node src/lib/main.js"
|
|
15
15
|
},
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"author": "",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@xn-intenton-z2a/agentic-lib": "^7.2.
|
|
20
|
+
"@xn-intenton-z2a/agentic-lib": "^7.2.13"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@playwright/test": "^1.58.0",
|
|
@@ -7,10 +7,10 @@ export default defineConfig({
|
|
|
7
7
|
timeout: 30000,
|
|
8
8
|
retries: 2,
|
|
9
9
|
use: {
|
|
10
|
-
baseURL: "http://localhost:3000",
|
|
10
|
+
baseURL: "http://localhost:3000/src/web/",
|
|
11
11
|
},
|
|
12
12
|
webServer: {
|
|
13
|
-
command: "npx serve
|
|
13
|
+
command: "npx serve . -l 3000",
|
|
14
14
|
port: 3000,
|
|
15
15
|
reuseExistingServer: true,
|
|
16
16
|
},
|
|
@@ -15,9 +15,15 @@ describe("Website", () => {
|
|
|
15
15
|
expect(html).toContain("</html>");
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
test("index.html imports the library via lib
|
|
18
|
+
test("index.html imports the library via lib.js", () => {
|
|
19
19
|
const html = readFileSync("src/web/index.html", "utf8");
|
|
20
|
-
expect(html).toContain("lib
|
|
20
|
+
expect(html).toContain("lib.js");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("src/web/lib.js re-exports from the library", () => {
|
|
24
|
+
expect(existsSync("src/web/lib.js")).toBe(true);
|
|
25
|
+
const lib = readFileSync("src/web/lib.js", "utf8");
|
|
26
|
+
expect(lib).toContain("../lib/main.js");
|
|
21
27
|
});
|
|
22
28
|
|
|
23
29
|
test("index.html displays library identity elements", () => {
|