Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ jobs:
timeout-minutes: 10

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
persist-credentials: false
# Full history: the migration test installs the last 0.1 revision.
fetch-depth: 0

- uses: actions/setup-node@v4
- uses: actions/setup-node@v5
with:
node-version: 20

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ jobs:
timeout-minutes: 10

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
persist-credentials: false
# Full history: the migration test installs the last 0.1 revision.
fetch-depth: 0

- uses: actions/setup-node@v4
- uses: actions/setup-node@v5
with:
node-version: 24
registry-url: https://registry.npmjs.org
Expand Down
8 changes: 5 additions & 3 deletions PUBLISHING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ planning backlog, which is not part of the package.
## Excluded local material

- `tasks/`: personal planning, historical evidence and project references.
- `global-skills/`, legacy template skills/scripts/agents, `components.tsv` and the legacy reporting
configurator: retained locally as historical snapshots only; the current installer does not read them.
- Legacy template scripts/agents, `components.tsv` and the legacy reporting configurator: retained
locally as historical snapshots only; the current installer does not read them. Skills have a
single editable source in `core/skills/` and `modules/*/skills/`.

The exclusions are declared in `.gitignore`, so `git add .` stages the intended source package
without deleting the local snapshots.
Expand Down Expand Up @@ -53,7 +54,8 @@ Change `name` in `package.json` and the commands in README/docs together if the
automatically) so that `npx ants-kit@latest` keeps resolving to the last
stable release; `npx ants-kit@next` resolves to the latest prerelease.

`npx github:PierreDillard/agent-workflow-kit` installs from the default branch with the same CLI.
Maintainer note: `npx github:PierreDillard/agent-workflow-kit` runs the unreleased default branch for
testing; it is not a user install path (see README).

## Current release posture

Expand Down
2 changes: 1 addition & 1 deletion core/skills/branch-router/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: branch-router
description: Resolve the current Git branch, its task workspace, merge direction and configured branch policy before any versioned change or merge.
description: Resolve the current Git branch, its task workspace, merge direction and configured branch policy before any versioned change or merge. Use before any versioned change, branch creation or merge, and whenever work touches shared files or the default branch.
---

# Branch Router
Expand Down
2 changes: 1 addition & 1 deletion core/skills/workflow-doctor/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: workflow-doctor
description: Run the installed workflow's read-only health check after installation or workflow changes.
description: Run the installed workflow's read-only health check after installation or workflow changes. Use after installing or updating the kit, after editing any skill, on a new clone or machine, or when the user says "doctor" or "check the workflow".
---

# Workflow Doctor
Expand Down
10 changes: 6 additions & 4 deletions docs/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ of eight official modules and never automatically activates external discoveries
"id": "project-notes",
"version": "1.0.0",
"description": "A small notebook",
"requires": { "memory": "1.0.0" },
"requires": { "memory": "1.1.0" },
"config": { "title": "Project notes" },
"skills": [{ "name": "project-notes", "source": "skills/project-notes" }],
"files": [{ "source": "templates/notes.md", "target": "{{TASKS_DIR}}/notes/README.md", "editable": true }],
Expand All @@ -47,7 +47,7 @@ writing any destination. One component/file has one owner; destination collision
| `files` | `source` file/directory, `target`, optional boolean `editable` (default false) |
| `rules` | Unique `id`, Markdown `source`, `point`, optional `when` array of module IDs |
| `hooks` | Unique `id`, module-owned managed `path`, `runner` (`bash` or `node`), `args`, `point`, optional `when` |
| `checks` | Owned `path`, `type` (`file`, `json`, `timezone`), optional positive `maxBytes` |
| `checks` | Owned `path` or `pattern` (`*` within one path segment), `type` (`file`, `json`, `timezone`, `links`), optional positive `maxBytes`, optional `level` (`fail` by default, or `warn`; a `pattern` or `links` check requires `warn`) |
| `config` | String defaults; override on first activation with `--set module.key=value` |

Collections other than identity fields may be omitted. A source path is relative to its module.
Expand Down Expand Up @@ -80,8 +80,10 @@ Dependencies run before dependents; unrelated modules use sorted IDs; contributi
retain manifest order. Reporting's handoff fragment is a built-in example of conditional composition.

The doctor checks dependencies, managed hashes/modes, mirrored skills and declarative checks.
`file` checks presence, `json` additionally parses JSON, and `timezone` also validates its `timezone`
field. It checks no external services and makes no claim about the agent following instructions.
`file` checks presence, `json` additionally parses JSON, `timezone` also validates its `timezone`
field, and `links` requires every relative Markdown link to name an existing file. A `warn` check is
reported by the doctor without failing it, and installation, add and update skip it. It checks no
external services and makes no claim about the agent following instructions.

## Preservation and lifecycle

Expand Down
2 changes: 1 addition & 1 deletion examples/modules/project-notes/module.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"id": "project-notes",
"version": "1.0.0",
"description": "Keep a small project notebook without enabling weekly reporting",
"requires": { "memory": "1.0.0" },
"requires": { "memory": "1.1.0" },
"config": { "title": "Project notes" },
"skills": [{ "name": "project-notes", "source": "skills/project-notes" }],
"files": [{ "source": "templates/notes.md", "target": "{{TASKS_DIR}}/notes/README.md", "editable": true }],
Expand Down
22 changes: 20 additions & 2 deletions modules/bugs/module.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"id": "bugs",
"version": "1.0.0",
"version": "1.1.0",
"description": "Bugs workflow capabilities",
"requires": {},
"skills": [
Expand Down Expand Up @@ -29,5 +29,23 @@
}
],
"hooks": [],
"checks": []
"checks": [
{
"path": "{{TASKS_DIR}}/bugs/README.md",
"type": "file",
"maxBytes": 8192,
"level": "warn"
},
{
"pattern": "{{TASKS_DIR}}/bugs/*.md",
"type": "file",
"maxBytes": 16384,
"level": "warn"
},
{
"path": "{{TASKS_DIR}}/bugs/README.md",
"type": "links",
"level": "warn"
}
]
}
2 changes: 1 addition & 1 deletion modules/bugs/skills/bug-fix-trace/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: bug-fix-trace
description: Confirm a bug hypothesis at runtime, add a focused regression test when feasible, and retain the incident in the thematic bug ledger.
description: Confirm a bug hypothesis at runtime, add a focused regression test when feasible, and retain the incident in the thematic bug ledger. Use when diagnosing a functional bug, after fixing one, or when the user says "trace this bug" or "log this fix"; not for pure lint or formatting fixes.
---

# Bug Fix Trace
Expand Down
2 changes: 1 addition & 1 deletion modules/bugs/skills/bug-triage/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: bug-triage
description: Triage a reported defect by observable impact, reproducibility, ownership and existing thematic evidence before diagnosis or implementation.
description: Triage a reported defect by observable impact, reproducibility, ownership and existing thematic evidence before diagnosis or implementation. Use when a defect or regression is reported, before diagnosing it or writing any fix.
---

# Bug Triage
Expand Down
2 changes: 1 addition & 1 deletion modules/continuity/skills/context-relay/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: context-relay
description: Prepare a branch-scoped handoff before context saturation while preserving the current atomic step and loading boundaries.
description: Prepare a branch-scoped handoff before context saturation while preserving the current atomic step and loading boundaries. Use when the conversation has run long, many files have been read or edited, context is being compressed, or coherence degrades; act proactively.
---

# Context Relay
Expand Down
2 changes: 1 addition & 1 deletion modules/continuity/skills/project-handoff/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: project-handoff
description: Create or update the current branch handoff so another session can resume from its task, memory and verified state.
description: Create or update the current branch handoff so another session can resume from its task, memory and verified state. Use before ending a session or clearing context with unfinished work, or when the user asks for a handoff.
---

# Project Handoff
Expand Down
2 changes: 1 addition & 1 deletion modules/exploration/skills/wayfinder/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: wayfinder
description: Map a multi-session initiative into decision tickets, resolving one frontier ticket at a time before implementation tasks begin.
description: Map a multi-session initiative into decision tickets, resolving one frontier ticket at a time before implementation tasks begin. Use when the user says "wayfinder" or "plan this as tickets", or brings a foggy idea bigger than one session; not for a single well-scoped feature (use write-task).
disable-model-invocation: true
---

Expand Down
2 changes: 1 addition & 1 deletion modules/learning/skills/teach/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: teach
description: Teach the user a new skill or concept, within this workspace.
description: Teach the user a new skill or concept, within this workspace. Use when the user asks to learn, understand or be taught a concept, tool or technique rather than only to get a task done.
disable-model-invocation: true
argument-hint: "What would you like to learn about?"
---
Expand Down
24 changes: 23 additions & 1 deletion modules/memory/module.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"id": "memory",
"version": "1.0.0",
"version": "1.1.0",
"description": "Memory workflow capabilities",
"requires": {},
"skills": [
Expand Down Expand Up @@ -40,6 +40,28 @@
"path": "{{TASKS_DIR}}/DECISIONS.md",
"type": "file",
"maxBytes": 32768
},
{
"pattern": "{{TASKS_DIR}}/memory/*.md",
"type": "file",
"maxBytes": 16384,
"level": "warn"
},
{
"pattern": "{{TASKS_DIR}}/decisions/*.md",
"type": "file",
"maxBytes": 16384,
"level": "warn"
},
{
"path": "{{TASKS_DIR}}/PROJECT_MEMORY.md",
"type": "links",
"level": "warn"
},
{
"path": "{{TASKS_DIR}}/DECISIONS.md",
"type": "links",
"level": "warn"
}
]
}
2 changes: 1 addition & 1 deletion modules/memory/skills/memory-report/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: memory-report
description: Promote only proven reusable findings into branch or project memory while keeping raw evidence in its canonical task or bug record.
description: Promote only proven reusable findings into branch or project memory while keeping raw evidence in its canonical task or bug record. Use after a bug fix, a failed fix or a regression investigation, or when the user asks to update project memory.
---

# Memory Report
Expand Down
2 changes: 1 addition & 1 deletion modules/quality/skills/architect/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: architect
description: Validate file and folder placement against the current project's documented architecture before creating, moving or refactoring code.
description: Validate file and folder placement against the current project's documented architecture before creating, moving or refactoring code. Use when adding a file or directory, implementing a feature or moving code, to confirm the right layer and folder before writing anything.
---

# Architect
Expand Down
2 changes: 1 addition & 1 deletion modules/quality/skills/explicit-naming/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: explicit-naming
description: Enforce explicit, readable variable and function names when writing or reviewing TypeScript, JavaScript or React code.
description: Enforce explicit, readable variable and function names when writing or reviewing TypeScript, JavaScript or React code. Use when writing or reviewing any such code, including callbacks, loop variables and destructured values.
---

# Explicit Naming
Expand Down
2 changes: 1 addition & 1 deletion modules/quality/skills/merge-integrity/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: merge-integrity
description: Audit semantic divergence immediately after a cross-branch merge, even when Git reports no textual conflict.
description: Audit semantic divergence immediately after a cross-branch merge, even when Git reports no textual conflict. Use after any cross-branch merge, before declaring it done, and when a test passes on one branch but fails on another.
---

# Merge Integrity
Expand Down
2 changes: 1 addition & 1 deletion modules/quality/skills/perf-gate/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: perf-gate
description: Require a bounded ceiling, written prediction, fixed protocol and measured comparison before claiming a performance improvement.
description: Require a bounded ceiling, written prediction, fixed protocol and measured comparison before claiming a performance improvement. Use when a task claims a performance gain, when a change is justified by "it feels faster", when reading a profiler capture, or before optimizing anything.
---

# Performance Gate
Expand Down
2 changes: 1 addition & 1 deletion modules/quality/skills/resource-ownership/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: resource-ownership
description: Identify the owner of shared sockets, workers, subscriptions and timers before writing connect, disconnect or cleanup behavior.
description: Identify the owner of shared sockets, workers, subscriptions and timers before writing connect, disconnect or cleanup behavior. Use when writing or reviewing cleanup code that touches a shared resource or singleton, or when removing one consumer freezes or breaks another.
---

# Resource Ownership
Expand Down
2 changes: 1 addition & 1 deletion modules/quality/skills/review-gate/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: review-gate
description: Perform an independent review of a bounded task against a fixed Git SHA before a default-branch merge or when explicitly requested.
description: Perform an independent review of a bounded task against a fixed Git SHA before a default-branch merge or when explicitly requested. Use before any merge into the default branch, or when the user asks for an independent review or to mark a task reviewed.
---

# Review Gate
Expand Down
2 changes: 1 addition & 1 deletion modules/quality/skills/validate-task/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: validate-task
description: Confirm objective, invariants, ownership boundaries, scope and acceptance checks before ambiguous, contractual or multi-layer implementation, and after corrections that change them.
description: Confirm objective, invariants, ownership boundaries, scope and acceptance checks before ambiguous, contractual or multi-layer implementation, and after corrections that change them. Use when a request is ambiguous, contractual or spans several layers, before implementing it, and again after a correction changes its scope.
---

# Validate Task
Expand Down
16 changes: 14 additions & 2 deletions modules/tasks/module.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"id": "tasks",
"version": "1.0.0",
"version": "1.1.0",
"description": "Tasks workflow capabilities",
"requires": {},
"skills": [
Expand All @@ -24,5 +24,17 @@
}
],
"hooks": [],
"checks": []
"checks": [
{
"pattern": "{{TASKS_DIR}}/todo/*/README.md",
"type": "file",
"maxBytes": 8192,
"level": "warn"
},
{
"pattern": "{{TASKS_DIR}}/todo/*/README.md",
"type": "links",
"level": "warn"
}
]
}
2 changes: 1 addition & 1 deletion modules/tasks/skills/ants/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: ants
description: Structure implementation as small, atomic, traceable changes with one owner, one observable signal and an updated task record.
description: Structure implementation as small, atomic, traceable changes with one owner, one observable signal and an updated task record. Use when planning, implementing, reviewing or refactoring code, especially to avoid big patches, unrelated refactors, duplicated state or unclear ownership.
---

# ANTS
Expand Down
2 changes: 1 addition & 1 deletion modules/tasks/skills/write-task/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: write-task
description: Create or restructure ANTS task files at the resolved effort location with atomic steps, observable signals and an explicit trace.
description: Create or restructure ANTS task files at the resolved effort location with atomic steps, observable signals and an explicit trace. Use when asked to create, plan or restructure tasks for a feature, effort or branch; not for status-only updates.
---

# Write Task
Expand Down
29 changes: 26 additions & 3 deletions templates/project/.workflow/runtime/catalog.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { existsSync, readdirSync } from 'node:fs';
import { join, resolve } from 'node:path';
import { dirname, join, resolve } from 'node:path';
import { assertKeys, readJson, safePath } from './paths.mjs';

export const officialModules = ['tasks', 'memory', 'continuity', 'quality', 'bugs', 'reporting', 'exploration', 'learning'];
Expand Down Expand Up @@ -51,13 +51,29 @@ export function validateManifest(manifest) {
}
}
for (const check of manifest.checks ?? []) {
assertKeys(check, ['path', 'type', 'maxBytes'], 'check');
if (typeof check.path !== 'string' || !['file', 'json', 'timezone'].includes(check.type) ||
assertKeys(check, ['path', 'pattern', 'type', 'maxBytes', 'level'], 'check');
// Patterns match user-created files and links point to user content: the kit can only warn about them.
if ((check.path === undefined) === (check.pattern === undefined) || typeof (check.path ?? check.pattern) !== 'string' ||
!['file', 'json', 'timezone', 'links'].includes(check.type) || !['fail', 'warn'].includes(check.level ?? 'fail') ||
((check.pattern !== undefined || check.type === 'links') && check.level !== 'warn') ||
(check.maxBytes !== undefined && (!Number.isInteger(check.maxBytes) || check.maxBytes < 1))) throw new Error('Invalid check');
}
return manifest;
}

// The single verification of a declarative check, shared by install, add, update and doctor.
export function verifyCheck(check, path, content, projectRoot) {
if (check.maxBytes && content.length > check.maxBytes) throw new Error(`Size limit exceeded: ${path}`);
if (check.type === 'links') {
const broken = relativeLinks(content.toString()).filter(target => !existsSync(join(resolve(projectRoot), dirname(path), target)));
if (broken.length) throw new Error(`Broken link in ${path}: ${broken.join(', ')}`);
}
if (check.type === 'json' || check.type === 'timezone') {
const value = JSON.parse(content);
if (check.type === 'timezone') new Intl.DateTimeFormat('en', { timeZone: value.timezone });
}
}

export function loadCatalog(moduleDirectories, explicitSources) {
const catalog = new Map();
function addSource(source) {
Expand Down Expand Up @@ -97,3 +113,10 @@ export function resolveModules(catalog, selected, installed = []) {
for (const moduleId of [...known.keys(), ...selected].sort()) visit(moduleId);
return ordered;
}

// Markdown link targets that name a local file: URLs, anchors and absolute paths are left out.
function relativeLinks(markdown) {
return [...markdown.matchAll(/\]\((<[^>]+>|[^)\s]+)[^)]*\)/g)]
.map(match => decodeURIComponent(match[1].replace(/^<|>$/g, '').split('#')[0]))
.filter(target => target && !target.startsWith('/') && !/^[a-z][a-z0-9+.-]*:/i.test(target));
}
4 changes: 2 additions & 2 deletions templates/project/.workflow/runtime/compose.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ export function materializeModule(source, configuration, settings) {
});
const hooks = (manifest.hooks ?? []).map(hook => ({ ...hook, path: expandPath(hook.path), args: (hook.args ?? []).map(expandPath) }));
for (const hook of hooks) if (!entries.some(entry => entry.root === 'project' && entry.path === hook.path && !entry.editable)) throw new Error(`Hook must reference a module-owned managed file: ${hook.path}`);
const checks = (manifest.checks ?? []).map(check => ({ ...check, path: expandPath(check.path) }));
for (const check of checks) if (!entries.some(entry => entry.root === 'project' && entry.path === check.path)) throw new Error(`Check must reference an owned file: ${check.path}`);
const checks = (manifest.checks ?? []).map(check => check.pattern ? { ...check, pattern: expandPath(check.pattern) } : { ...check, path: expandPath(check.path) });
for (const check of checks) if (check.path && !entries.some(entry => entry.root === 'project' && entry.path === check.path)) throw new Error(`Check must reference an owned file: ${check.path}`);
const fingerprint = digest(JSON.stringify(manifest) + entries.map(entry => `${entry.root}:${entry.path}:${entry.mode}:${digest(entry.content)}`).join('\n'));
return { entries, module: { id: manifest.id, version: manifest.version, requires: manifest.requires ?? {}, rules, hooks, checks,
components, settings: moduleSettings, fingerprint } };
Expand Down
Loading
Loading