agent-method 1.5.12
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 +343 -0
- package/bin/wwa.js +115 -0
- package/docs/internal/cli-commands.yaml +259 -0
- package/docs/internal/doc-tokens.yaml +1103 -0
- package/docs/internal/feature-registry.yaml +1643 -0
- package/lib/boundaries.js +247 -0
- package/lib/cli/add.js +170 -0
- package/lib/cli/casestudy.js +1000 -0
- package/lib/cli/check.js +323 -0
- package/lib/cli/close.js +838 -0
- package/lib/cli/completion.js +735 -0
- package/lib/cli/deps.js +234 -0
- package/lib/cli/digest.js +73 -0
- package/lib/cli/doc-review.js +486 -0
- package/lib/cli/docs.js +315 -0
- package/lib/cli/helpers.js +198 -0
- package/lib/cli/implement.js +169 -0
- package/lib/cli/init.js +280 -0
- package/lib/cli/pipeline.js +206 -0
- package/lib/cli/plan.js +140 -0
- package/lib/cli/record.js +98 -0
- package/lib/cli/refine.js +202 -0
- package/lib/cli/report-helpers.js +113 -0
- package/lib/cli/review.js +76 -0
- package/lib/cli/routable.js +109 -0
- package/lib/cli/route.js +101 -0
- package/lib/cli/scan.js +133 -0
- package/lib/cli/serve.js +23 -0
- package/lib/cli/status.js +65 -0
- package/lib/cli/update-docs.js +574 -0
- package/lib/cli/upgrade.js +222 -0
- package/lib/cli/watch.js +32 -0
- package/lib/dependencies.js +196 -0
- package/lib/init.js +692 -0
- package/lib/mcp-server.js +612 -0
- package/lib/pipeline.js +907 -0
- package/lib/registry.js +132 -0
- package/lib/watcher.js +165 -0
- package/package.json +54 -0
- package/templates/README.md +363 -0
- package/templates/entry-points/.cursorrules +90 -0
- package/templates/entry-points/AGENT.md +90 -0
- package/templates/entry-points/CLAUDE.md +88 -0
- package/templates/extensions/MANIFEST.md +110 -0
- package/templates/extensions/analytical-system.md +96 -0
- package/templates/extensions/code-project.md +77 -0
- package/templates/extensions/data-exploration.md +117 -0
- package/templates/full/.context/BASE.md +101 -0
- package/templates/full/.context/COMPOSITION.md +47 -0
- package/templates/full/.context/INDEX.yaml +56 -0
- package/templates/full/.context/METHODOLOGY.md +246 -0
- package/templates/full/.context/PROTOCOL.yaml +169 -0
- package/templates/full/.context/REGISTRY.md +75 -0
- package/templates/full/.cursorrules +90 -0
- package/templates/full/AGENT.md +90 -0
- package/templates/full/CLAUDE.md +90 -0
- package/templates/full/Management/DIGEST.md +23 -0
- package/templates/full/Management/STATUS.md +46 -0
- package/templates/full/PLAN.md +67 -0
- package/templates/full/PROJECT-PROFILE.md +61 -0
- package/templates/full/PROJECT.md +80 -0
- package/templates/full/REQUIREMENTS.md +30 -0
- package/templates/full/ROADMAP.md +39 -0
- package/templates/full/Reviews/INDEX.md +41 -0
- package/templates/full/Reviews/backlog.md +52 -0
- package/templates/full/Reviews/plan.md +43 -0
- package/templates/full/Reviews/project.md +41 -0
- package/templates/full/Reviews/requirements.md +42 -0
- package/templates/full/Reviews/roadmap.md +41 -0
- package/templates/full/Reviews/state.md +56 -0
- package/templates/full/SESSION-LOG.md +102 -0
- package/templates/full/STATE.md +42 -0
- package/templates/full/SUMMARY.md +27 -0
- package/templates/full/agentWorkflows/INDEX.md +42 -0
- package/templates/full/agentWorkflows/observations.md +65 -0
- package/templates/full/agentWorkflows/patterns.md +68 -0
- package/templates/full/agentWorkflows/sessions.md +92 -0
- package/templates/full/intro/README.md +39 -0
- package/templates/full/registry/feature-registry.yaml +25 -0
- package/templates/full/registry/features/catalog.yaml +743 -0
- package/templates/full/registry/features/protocol.yaml +121 -0
- package/templates/full/registry/features/routing.yaml +358 -0
- package/templates/full/registry/features/workflows.yaml +404 -0
- package/templates/full/todos/backlog.md +19 -0
- package/templates/starter/.context/BASE.md +66 -0
- package/templates/starter/.context/INDEX.yaml +51 -0
- package/templates/starter/.context/METHODOLOGY.md +228 -0
- package/templates/starter/.context/PROTOCOL.yaml +165 -0
- package/templates/starter/.cursorrules +90 -0
- package/templates/starter/AGENT.md +90 -0
- package/templates/starter/CLAUDE.md +90 -0
- package/templates/starter/Management/DIGEST.md +23 -0
- package/templates/starter/Management/STATUS.md +46 -0
- package/templates/starter/PLAN.md +67 -0
- package/templates/starter/PROJECT-PROFILE.md +44 -0
- package/templates/starter/PROJECT.md +80 -0
- package/templates/starter/ROADMAP.md +39 -0
- package/templates/starter/Reviews/INDEX.md +75 -0
- package/templates/starter/SESSION-LOG.md +102 -0
- package/templates/starter/STATE.md +42 -0
- package/templates/starter/SUMMARY.md +27 -0
- package/templates/starter/agentWorkflows/INDEX.md +61 -0
- package/templates/starter/intro/README.md +37 -0
- package/templates/starter/registry/feature-registry.yaml +25 -0
- package/templates/starter/registry/features/catalog.yaml +743 -0
- package/templates/starter/registry/features/protocol.yaml +121 -0
- package/templates/starter/registry/features/routing.yaml +358 -0
- package/templates/starter/registry/features/workflows.yaml +404 -0
package/lib/registry.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry loader and structured query interface.
|
|
3
|
+
*
|
|
4
|
+
* Loads feature-registry.yaml and provides typed access to features,
|
|
5
|
+
* workflows, patterns, activation maps, and protocol directives.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFileSync, statSync } from "node:fs";
|
|
9
|
+
import { resolve, join, dirname } from "node:path";
|
|
10
|
+
import { existsSync } from "node:fs";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import yaml from "js-yaml";
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Locate feature-registry.yaml by walking upward from start.
|
|
19
|
+
*
|
|
20
|
+
* Search order:
|
|
21
|
+
* 1. docs/internal/feature-registry.yaml relative to package root
|
|
22
|
+
* 2. Walk parent directories looking for docs/internal/feature-registry.yaml
|
|
23
|
+
* 3. feature-registry.yaml in start or its parents
|
|
24
|
+
*/
|
|
25
|
+
export function findRegistry(start) {
|
|
26
|
+
if (!start) {
|
|
27
|
+
// Default: package root (one level up from lib/)
|
|
28
|
+
start = resolve(__dirname, "..");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Direct relative paths from the start
|
|
32
|
+
const candidates = [
|
|
33
|
+
join(start, "registry", "feature-registry.yaml"),
|
|
34
|
+
join(start, "docs", "internal", "feature-registry.yaml"),
|
|
35
|
+
join(start, ".context", "feature-registry.yaml"),
|
|
36
|
+
join(start, "feature-registry.yaml"),
|
|
37
|
+
];
|
|
38
|
+
for (const p of candidates) {
|
|
39
|
+
if (existsSync(p)) return p;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Walk upward
|
|
43
|
+
let current = resolve(start);
|
|
44
|
+
for (let i = 0; i < 10; i++) {
|
|
45
|
+
const regCandidate = join(current, "registry", "feature-registry.yaml");
|
|
46
|
+
if (existsSync(regCandidate)) return regCandidate;
|
|
47
|
+
const candidate = join(current, "docs", "internal", "feature-registry.yaml");
|
|
48
|
+
if (existsSync(candidate)) return candidate;
|
|
49
|
+
const parent = dirname(current);
|
|
50
|
+
if (parent === current) break;
|
|
51
|
+
current = parent;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
throw new Error(
|
|
55
|
+
"Cannot find feature-registry.yaml. " +
|
|
56
|
+
"Provide --registry or run from the wwa repo."
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Load and return the parsed registry.
|
|
62
|
+
* Handles {placeholder} patterns in YAML by quoting them before parsing.
|
|
63
|
+
*/
|
|
64
|
+
export function loadRegistry(path) {
|
|
65
|
+
if (!path) path = findRegistry();
|
|
66
|
+
// If path is a directory, find the registry file within it
|
|
67
|
+
if (existsSync(path) && statSync(path).isDirectory()) path = findRegistry(path);
|
|
68
|
+
let content = readFileSync(path, "utf-8");
|
|
69
|
+
// The registry uses {placeholder} in flow sequences — replace them.
|
|
70
|
+
content = content.replace(/\{([^}]+)\}/g, "_$1_");
|
|
71
|
+
const parsed = yaml.load(content);
|
|
72
|
+
|
|
73
|
+
// Split index: has 'layers' key but no 'features' — assemble from components
|
|
74
|
+
if (parsed?.layers && !parsed.features) {
|
|
75
|
+
const dir = dirname(path);
|
|
76
|
+
const assembled = { version: parsed.version };
|
|
77
|
+
for (const layer of parsed.layers) {
|
|
78
|
+
const componentPath = join(dir, layer.file);
|
|
79
|
+
if (existsSync(componentPath)) {
|
|
80
|
+
let cContent = readFileSync(componentPath, "utf-8");
|
|
81
|
+
cContent = cContent.replace(/\{([^}]+)\}/g, "_$1_");
|
|
82
|
+
const component = yaml.load(cContent);
|
|
83
|
+
if (component) Object.assign(assembled, component);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return assembled;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return parsed;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Return a map of feature ID to feature spec. */
|
|
93
|
+
export function getFeatures(registry) {
|
|
94
|
+
const features = {};
|
|
95
|
+
for (const f of registry.features || []) {
|
|
96
|
+
features[f.id] = f;
|
|
97
|
+
}
|
|
98
|
+
return features;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Return the list of workflow specs. */
|
|
102
|
+
export function getWorkflows(registry) {
|
|
103
|
+
return registry.workflows || [];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Return a single workflow by ID, or null. */
|
|
107
|
+
export function getWorkflow(registry, workflowId) {
|
|
108
|
+
for (const wf of getWorkflows(registry)) {
|
|
109
|
+
if (wf.id === workflowId) return wf;
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Return the list of query pattern specs. */
|
|
115
|
+
export function getQueryPatterns(registry) {
|
|
116
|
+
return registry.query_patterns || [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Return the activation map (stage -> feature list). */
|
|
120
|
+
export function getActivation(registry) {
|
|
121
|
+
return registry.activation || {};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Return the list of protocol directives. */
|
|
125
|
+
export function getDirectives(registry) {
|
|
126
|
+
return (registry.protocol || {}).core_directives || [];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Return the registry version string. */
|
|
130
|
+
export function getVersion(registry) {
|
|
131
|
+
return String(registry.version || "unknown");
|
|
132
|
+
}
|
package/lib/watcher.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry watcher — chokidar-based file monitoring with proactive validation.
|
|
3
|
+
*
|
|
4
|
+
* Watches:
|
|
5
|
+
* - Entry points (CLAUDE.md, .cursorrules, AGENT.md)
|
|
6
|
+
* - Feature registry (feature-registry.yaml)
|
|
7
|
+
* - Markdown files for 300-line threshold violations
|
|
8
|
+
*
|
|
9
|
+
* On change: runs S7 validation and reports results.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { watch } from "chokidar";
|
|
13
|
+
import { readFileSync, statSync } from "node:fs";
|
|
14
|
+
import { resolve, basename, extname } from "node:path";
|
|
15
|
+
|
|
16
|
+
import { loadRegistry } from "./registry.js";
|
|
17
|
+
import { validateEntryPoint, detectProjectType } from "./pipeline.js";
|
|
18
|
+
|
|
19
|
+
const SCALE_THRESHOLD = 300;
|
|
20
|
+
|
|
21
|
+
const ENTRY_POINT_NAMES = new Set(["CLAUDE.md", ".cursorrules", "AGENT.md"]);
|
|
22
|
+
const INTELLIGENCE_LAYER = new Set([
|
|
23
|
+
"STATE.md", "ROADMAP.md", "PLAN.md", "SUMMARY.md", "PROJECT.md",
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Validation handlers
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
function validateEntry(filePath, registryPath) {
|
|
31
|
+
const reg = loadRegistry(registryPath || undefined);
|
|
32
|
+
const dir = resolve(filePath, "..");
|
|
33
|
+
const detected = detectProjectType(dir);
|
|
34
|
+
const projectType = detected.project_type || "general";
|
|
35
|
+
const result = validateEntryPoint(filePath, projectType, reg);
|
|
36
|
+
return { type: "entry_point", file: filePath, projectType, result };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function checkScale(filePath) {
|
|
40
|
+
try {
|
|
41
|
+
const content = readFileSync(resolve(filePath), "utf-8");
|
|
42
|
+
const lineCount = content.split("\n").length;
|
|
43
|
+
const over = lineCount > SCALE_THRESHOLD;
|
|
44
|
+
return {
|
|
45
|
+
type: "scale_check",
|
|
46
|
+
file: filePath,
|
|
47
|
+
line_count: lineCount,
|
|
48
|
+
threshold: SCALE_THRESHOLD,
|
|
49
|
+
over_threshold: over,
|
|
50
|
+
};
|
|
51
|
+
} catch {
|
|
52
|
+
return { type: "scale_check", file: filePath, error: "Cannot read file" };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Watcher creation
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
export function createWatcher(directory, options = {}) {
|
|
61
|
+
const dir = resolve(directory);
|
|
62
|
+
const registryPath = options.registryPath || null;
|
|
63
|
+
const onResult = options.onResult || defaultReporter;
|
|
64
|
+
|
|
65
|
+
// Watch patterns: markdown files and yaml files
|
|
66
|
+
const patterns = [
|
|
67
|
+
`${dir}/**/*.md`,
|
|
68
|
+
`${dir}/**/feature-registry.yaml`,
|
|
69
|
+
`${dir}/.cursorrules`,
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const ignored = [
|
|
73
|
+
"**/node_modules/**",
|
|
74
|
+
"**/.git/**",
|
|
75
|
+
"**/dist/**",
|
|
76
|
+
"**/build/**",
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
const watcher = watch(patterns, {
|
|
80
|
+
ignored,
|
|
81
|
+
persistent: true,
|
|
82
|
+
ignoreInitial: true,
|
|
83
|
+
awaitWriteFinish: {
|
|
84
|
+
stabilityThreshold: 300,
|
|
85
|
+
pollInterval: 100,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
watcher.on("change", (filePath) => {
|
|
90
|
+
const name = basename(filePath);
|
|
91
|
+
const ext = extname(filePath);
|
|
92
|
+
|
|
93
|
+
// Entry point changed — run full validation
|
|
94
|
+
if (ENTRY_POINT_NAMES.has(name)) {
|
|
95
|
+
try {
|
|
96
|
+
const report = validateEntry(filePath, registryPath);
|
|
97
|
+
onResult(report);
|
|
98
|
+
} catch (err) {
|
|
99
|
+
onResult({ type: "error", file: filePath, message: err.message });
|
|
100
|
+
}
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Registry changed — reload and validate all entry points
|
|
105
|
+
if (name === "feature-registry.yaml") {
|
|
106
|
+
onResult({ type: "registry_reload", file: filePath, message: "Registry changed — reload triggered" });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Markdown file changed — check scale threshold
|
|
111
|
+
if (ext === ".md") {
|
|
112
|
+
const report = checkScale(filePath);
|
|
113
|
+
// Only report if over threshold or if it's an intelligence layer file
|
|
114
|
+
if (report.over_threshold || INTELLIGENCE_LAYER.has(name)) {
|
|
115
|
+
onResult(report);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
watcher.on("add", (filePath) => {
|
|
121
|
+
const name = basename(filePath);
|
|
122
|
+
if (ENTRY_POINT_NAMES.has(name)) {
|
|
123
|
+
onResult({ type: "entry_point_added", file: filePath, message: "New entry point detected" });
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
return watcher;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// Default reporter — console output
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
|
|
134
|
+
function defaultReporter(report) {
|
|
135
|
+
const timestamp = new Date().toISOString().substring(11, 19);
|
|
136
|
+
|
|
137
|
+
switch (report.type) {
|
|
138
|
+
case "entry_point": {
|
|
139
|
+
const status = report.result.valid ? "PASS" : "FAIL";
|
|
140
|
+
console.log(`[${timestamp}] Entry point ${status}: ${report.file}`);
|
|
141
|
+
if (!report.result.valid && report.result.issues) {
|
|
142
|
+
for (const issue of report.result.issues) {
|
|
143
|
+
console.log(` [${issue.severity}] ${issue.check}: ${issue.description}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
case "scale_check":
|
|
149
|
+
if (report.over_threshold) {
|
|
150
|
+
console.log(
|
|
151
|
+
`[${timestamp}] Scale warning: ${report.file} (${report.line_count} lines, threshold: ${report.threshold})`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
break;
|
|
155
|
+
case "registry_reload":
|
|
156
|
+
console.log(`[${timestamp}] ${report.message}`);
|
|
157
|
+
break;
|
|
158
|
+
case "entry_point_added":
|
|
159
|
+
console.log(`[${timestamp}] ${report.message}: ${report.file}`);
|
|
160
|
+
break;
|
|
161
|
+
case "error":
|
|
162
|
+
console.error(`[${timestamp}] Error: ${report.file} — ${report.message}`);
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-method",
|
|
3
|
+
"version": "1.5.12",
|
|
4
|
+
"description": "CLI tools for the wwa methodology — registry-driven routing, validation, and project setup for AI-agent-assisted development",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai-agents",
|
|
7
|
+
"prompt-engineering",
|
|
8
|
+
"context-engineering",
|
|
9
|
+
"methodology",
|
|
10
|
+
"developer-tools",
|
|
11
|
+
"cli",
|
|
12
|
+
"claude-code",
|
|
13
|
+
"cursor",
|
|
14
|
+
"gemini",
|
|
15
|
+
"codex",
|
|
16
|
+
"mcp",
|
|
17
|
+
"agent-framework"
|
|
18
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"author": "wwa contributors",
|
|
22
|
+
"bin": {
|
|
23
|
+
"wwa": "bin/wwa.js",
|
|
24
|
+
"agent-method": "bin/wwa.js"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"bin/",
|
|
28
|
+
"lib/",
|
|
29
|
+
"templates/",
|
|
30
|
+
"docs/internal/feature-registry.yaml",
|
|
31
|
+
"docs/internal/doc-tokens.yaml",
|
|
32
|
+
"docs/internal/cli-commands.yaml"
|
|
33
|
+
],
|
|
34
|
+
"main": "lib/registry.js",
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.0.0"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
40
|
+
"chalk": "^5.6.2",
|
|
41
|
+
"chokidar": "^4.0.3",
|
|
42
|
+
"commander": "^12.0.0",
|
|
43
|
+
"inquirer": "^9.0.0",
|
|
44
|
+
"js-yaml": "^4.1.1"
|
|
45
|
+
},
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "https://github.com/anthropics/wwa"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"test": "node --test tests/js/cli-smoke.test.cjs",
|
|
52
|
+
"test:setup": "node tests/js/test-setup-wrapper.cjs"
|
|
53
|
+
}
|
|
54
|
+
}
|