diff --git a/PUBLISHING.md b/PUBLISHING.md index 898f169..5c17df4 100644 --- a/PUBLISHING.md +++ b/PUBLISHING.md @@ -59,6 +59,6 @@ testing; it is not a user install path (see README). ## Current release posture -`VERSION` is `0.2.0`, the first stable release on npm (`0.2.0-dev` was the initial prerelease). +`VERSION` is `0.3.0`, which adds the Knowledge module; `0.2.0` was the first stable release on npm. Fresh Claude/Codex/Copilot discovery checks are still to be recorded. Linux is the tested platform. The project is MIT; `THIRD_PARTY_NOTICES.md` retains the notices for the skills attributed to Matt Pocock. diff --git a/README.md b/README.md index 6207e34..0c761cf 100644 --- a/README.md +++ b/README.md @@ -206,7 +206,7 @@ bash agent-workflow-kit/module.sh update --target /path/to/my-project ## Project status -**Version `0.2.0`, published on npm as [`ants-kit`](https://www.npmjs.com/package/ants-kit).** +**Version `0.3.0`, published on npm as [`ants-kit`](https://www.npmjs.com/package/ants-kit).** Local tests, GitHub CI and publication archive checks pass; Linux is the tested platform. Checks in fresh Claude Code, Codex, and Copilot sessions are still to be recorded. diff --git a/VERSION b/VERSION index 0ea3a94..0d91a54 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 +0.3.0 diff --git a/package.json b/package.json index 42ae62b..8b14ad5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ants-kit", - "version": "0.2.0", + "version": "0.3.0", "description": "Modular task, memory and quality workflow for Claude Code, Codex and Copilot, installed into a single project directory.", "license": "MIT", "author": "Pierre Dillard", diff --git a/templates/project/.workflow/runtime/catalog.mjs b/templates/project/.workflow/runtime/catalog.mjs index 7406ca6..ce20dc6 100644 --- a/templates/project/.workflow/runtime/catalog.mjs +++ b/templates/project/.workflow/runtime/catalog.mjs @@ -108,14 +108,15 @@ export function resolveModules(catalog, selected, installed = []) { const ordered = []; const visiting = new Set(); const visited = new Set(); - function visit(moduleId, requiredVersion = '*') { + function visit(moduleId, requiredVersion = '*', requiredBy = null) { const manifest = known.get(moduleId) ?? catalog.get(moduleId)?.manifest; - if (!manifest) throw new Error(`Missing module dependency: ${moduleId}`); + if (!manifest && requiredBy) throw new Error(`Missing module dependency: ${moduleId} (required by ${requiredBy})`); + if (!manifest) throw new Error(`Unknown module: ${moduleId} (not in the installed modules or available catalogs)`); if (!satisfiesVersion(manifest.version, requiredVersion)) throw new Error(`Incompatible version: ${moduleId} requires ${requiredVersion}, found ${manifest.version}`); if (visiting.has(moduleId)) throw new Error(`Module dependency cycle: ${moduleId}`); if (visited.has(moduleId)) return; visiting.add(moduleId); - for (const [dependency, version] of Object.entries(manifest.requires ?? {}).sort()) visit(dependency, version); + for (const [dependency, version] of Object.entries(manifest.requires ?? {}).sort()) visit(dependency, version, moduleId); visiting.delete(moduleId); visited.add(moduleId); ordered.push(manifest); diff --git a/tests/modules.test.mjs b/tests/modules.test.mjs index 3749d8c..e7e2291 100644 --- a/tests/modules.test.mjs +++ b/tests/modules.test.mjs @@ -23,7 +23,8 @@ function command(executable, args, expectedSuccess = true, environment = {}) { function fixture(context, configuration = '') { const root = mkdtempSync(join(tmpdir(), 'workflow-module-test-')); - context.after(() => rmSync(root, { recursive: true, force: true })); + // Retries absorb a Git process still writing in a fixture repository when cleanup starts. + context.after(() => rmSync(root, { recursive: true, force: true, maxRetries: 5 })); const project = join(root, 'project with spaces'); const user = join(root, 'user with spaces'); mkdirSync(project); mkdirSync(user); @@ -287,7 +288,7 @@ test('module dependencies accept compatible versions of the same major and refus }); for (const [label, overrides, expected] of [ - ['missing dependency', { requires: { missing: '*' } }, /Missing module dependency/], + ['missing dependency', { requires: { missing: '*' } }, /Missing module dependency: missing \(required by /], ['incompatible dependency', { requires: { memory: '99.0.0' } }, /Incompatible version/], ['incompatible dependency major', { requires: { memory: '^99.0.0' } }, /Incompatible version/], ['unsupported dependency range', { requires: { memory: '~1.1.0' } }, /Invalid dependency/], @@ -360,7 +361,7 @@ test('mid-add failure restores files, inventory, shared rules, directories and u test('unknown selection and invalid configuration leave first install untouched', context => { const setup = fixture(context); const before = snapshot(setup.project); - assert.match(install(setup, ['--modules', 'unknown'], false), /Missing module dependency/); + assert.match(install(setup, ['--modules', 'unknown'], false), /Unknown module: unknown \(not in the installed modules or available catalogs\)/); assert.match(install(setup, ['--profile', 'unknown'], false), /Unknown profile/); assert.deepEqual(snapshot(setup.project), before); }); @@ -458,7 +459,7 @@ function updateFixture(context, extra = [], configuration = '') { command('git', ['-C', source, 'init', '-q']); command('git', ['-C', source, 'add', '.']); command('git', ['-C', source, '-c', 'user.name=Workflow fixture', '-c', 'user.email=fixture@example.invalid', - '-c', 'commit.gpgsign=false', 'commit', '-qm', 'Fixture baseline']); + '-c', 'commit.gpgsign=false', '-c', 'gc.auto=0', '-c', 'maintenance.auto=false', 'commit', '-qm', 'Fixture baseline']); const workflow = join(source, 'core/skills/project-workflow/SKILL.md'); writeFileSync(workflow, '---\nname: project-workflow\ndescription: Previous fixture router.\n---\n\nPrevious fixture route.\n'); command('bash', [join(source, 'install.sh'), '--target', setup.project, '--user-root', setup.user,