@haaaiawd/anws 2.2.0 → 2.2.2

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.
Files changed (28) hide show
  1. package/README.md +180 -343
  2. package/bin/cli.js +112 -112
  3. package/lib/changelog.js +258 -258
  4. package/lib/copy.js +116 -109
  5. package/lib/diff.js +11 -0
  6. package/lib/manifest.js +4 -1
  7. package/lib/update.js +319 -319
  8. package/package.json +4 -3
  9. package/templates/.agents/skills/anws-system/SKILL.md +9 -7
  10. package/templates/.agents/skills/code-reviewer/SKILL.md +102 -327
  11. package/templates/.agents/skills/concept-modeler/SKILL.md +19 -17
  12. package/templates/.agents/skills/craft-authoring/SKILL.md +123 -0
  13. package/templates/.agents/skills/e2e-testing-guide/SKILL.md +59 -0
  14. package/templates/.agents/skills/system-designer/SKILL.md +6 -6
  15. package/templates/.agents/skills/system-designer/references/system-design-template.md +17 -17
  16. package/templates/.agents/skills/task-planner/SKILL.md +113 -113
  17. package/templates/.agents/skills/task-planner/references/TASK_TEMPLATE.md +82 -82
  18. package/templates/.agents/workflows/blueprint.md +284 -284
  19. package/templates/.agents/workflows/challenge.md +450 -491
  20. package/templates/.agents/workflows/change.md +263 -286
  21. package/templates/.agents/workflows/craft.md +243 -664
  22. package/templates/.agents/workflows/design-system.md +624 -624
  23. package/templates/.agents/workflows/explore.md +400 -371
  24. package/templates/.agents/workflows/forge.md +444 -413
  25. package/templates/.agents/workflows/genesis.md +342 -395
  26. package/templates/.agents/workflows/probe.md +21 -16
  27. package/templates/.agents/workflows/quickstart.md +123 -138
  28. package/templates/AGENTS.md +149 -134
package/lib/copy.js CHANGED
@@ -1,109 +1,116 @@
1
- 'use strict';
2
-
3
- const fs = require('node:fs/promises');
4
- const path = require('node:path');
5
-
6
- /**
7
- * 递归复制目录,返回已写入的文件路径数组(相对于 destDir)。
8
- *
9
- * @param {string} srcDir 源目录绝对路径
10
- * @param {string} destDir 目标目录绝对路径(不存在时自动创建)
11
- * @returns {Promise<string[]>} 已写入文件的绝对路径列表
12
- */
13
- async function copyDir(srcDir, destDir) {
14
- const written = [];
15
-
16
- async function walk(src, dest) {
17
- await fs.mkdir(dest, { recursive: true });
18
- const entries = await fs.readdir(src, { withFileTypes: true });
19
-
20
- for (const entry of entries) {
21
- const srcPath = path.join(src, entry.name);
22
- const destPath = path.join(dest, entry.name);
23
-
24
- if (entry.isDirectory()) {
25
- await walk(srcPath, destPath);
26
- } else if (entry.isFile()) {
27
- await fs.copyFile(srcPath, destPath);
28
- written.push(destPath);
29
- }
30
- // 忽略 symlink 等特殊文件类型
31
- }
32
- }
33
-
34
- await walk(srcDir, destDir);
35
- return written;
36
- }
37
-
38
- async function pathExists(targetPath) {
39
- return fs.access(targetPath).then(() => true).catch(() => false);
40
- }
41
-
42
- async function writeTargetFiles(cwd, options = {}) {
43
- const targetPlan = options.targetPlan || {};
44
- const protectedFiles = options.protectedFiles || targetPlan.userProtectedFiles || [];
45
- const projectionEntries = targetPlan.projectionEntries || [];
46
- const shouldWriteRootAgents = options.shouldWriteRootAgents !== false;
47
- const srcAgents = options.srcAgents;
48
- const agentsUpdatePlan = options.agentsUpdatePlan;
49
- const resolveCanonicalSource = options.resolveCanonicalSource;
50
- const projectionMap = new Map(projectionEntries.map((item) => [item.outputPath, item]));
51
- const written = [];
52
- const skipped = [];
53
-
54
- for (const rel of targetPlan.managedFiles || []) {
55
- if (rel === 'AGENTS.md' && !shouldWriteRootAgents) {
56
- skipped.push(rel);
57
- continue;
58
- }
59
-
60
- if (rel === 'AGENTS.md') {
61
- const destPath = path.join(cwd, rel);
62
- await fs.mkdir(path.dirname(destPath), { recursive: true });
63
-
64
- if (agentsUpdatePlan && agentsUpdatePlan.mode === 'skip') {
65
- skipped.push(rel);
66
- continue;
67
- }
68
-
69
- if (agentsUpdatePlan && agentsUpdatePlan.content) {
70
- await fs.writeFile(destPath, agentsUpdatePlan.content, 'utf8');
71
- written.push(rel);
72
- continue;
73
- }
74
-
75
- if (await pathExists(srcAgents)) {
76
- await fs.copyFile(srcAgents, destPath);
77
- written.push(rel);
78
- continue;
79
- }
80
- }
81
-
82
- if (protectedFiles.includes(rel)) {
83
- const destPath = path.join(cwd, rel);
84
- if (await pathExists(destPath)) {
85
- skipped.push(rel);
86
- continue;
87
- }
88
- }
89
-
90
- const entry = projectionMap.get(rel);
91
- const destPath = path.join(cwd, rel);
92
- await fs.mkdir(path.dirname(destPath), { recursive: true });
93
-
94
- const srcPath = resolveCanonicalSource(entry.source);
95
- if (await pathExists(srcPath)) {
96
- await fs.copyFile(srcPath, destPath);
97
- written.push(rel);
98
- }
99
- }
100
-
101
- return {
102
- targetId: targetPlan.targetId,
103
- targetLabel: targetPlan.targetLabel,
104
- written,
105
- skipped
106
- };
107
- }
108
-
109
- module.exports = { copyDir, writeTargetFiles };
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs/promises');
4
+ const path = require('node:path');
5
+
6
+ /**
7
+ * 递归复制目录,返回已写入的文件路径数组(相对于 destDir)。
8
+ *
9
+ * @param {string} srcDir 源目录绝对路径
10
+ * @param {string} destDir 目标目录绝对路径(不存在时自动创建)
11
+ * @returns {Promise<string[]>} 已写入文件的绝对路径列表
12
+ */
13
+ async function copyDir(srcDir, destDir) {
14
+ const written = [];
15
+
16
+ async function walk(src, dest) {
17
+ await fs.mkdir(dest, { recursive: true });
18
+ const entries = await fs.readdir(src, { withFileTypes: true });
19
+
20
+ for (const entry of entries) {
21
+ const srcPath = path.join(src, entry.name);
22
+ const destPath = path.join(dest, entry.name);
23
+
24
+ if (entry.isDirectory()) {
25
+ await walk(srcPath, destPath);
26
+ } else if (entry.isFile()) {
27
+ await fs.copyFile(srcPath, destPath);
28
+ written.push(destPath);
29
+ }
30
+ // 忽略 symlink 等特殊文件类型
31
+ }
32
+ }
33
+
34
+ await walk(srcDir, destDir);
35
+ return written;
36
+ }
37
+
38
+ async function pathExists(targetPath) {
39
+ return fs.access(targetPath).then(() => true).catch(() => false);
40
+ }
41
+
42
+ async function writeTargetFiles(cwd, options = {}) {
43
+ const targetPlan = options.targetPlan || {};
44
+ const protectedFiles = options.protectedFiles || targetPlan.userProtectedFiles || [];
45
+ const projectionEntries = targetPlan.projectionEntries || [];
46
+ const shouldWriteRootAgents = options.shouldWriteRootAgents !== false;
47
+ const srcAgents = options.srcAgents;
48
+ const agentsUpdatePlan = options.agentsUpdatePlan;
49
+ const resolveCanonicalSource = options.resolveCanonicalSource;
50
+ const projectionMap = new Map(projectionEntries.map((item) => [item.outputPath, item]));
51
+ const written = [];
52
+ const skipped = [];
53
+
54
+ for (const rel of targetPlan.managedFiles || []) {
55
+ if (rel === 'AGENTS.md' && !shouldWriteRootAgents) {
56
+ skipped.push(rel);
57
+ continue;
58
+ }
59
+
60
+ if (rel === 'AGENTS.md') {
61
+ const destPath = path.join(cwd, rel);
62
+ await fs.mkdir(path.dirname(destPath), { recursive: true });
63
+
64
+ if (agentsUpdatePlan && agentsUpdatePlan.mode === 'skip') {
65
+ skipped.push(rel);
66
+ continue;
67
+ }
68
+
69
+ if (agentsUpdatePlan && agentsUpdatePlan.content) {
70
+ await fs.writeFile(destPath, agentsUpdatePlan.content, 'utf8');
71
+ written.push(rel);
72
+ continue;
73
+ }
74
+
75
+ if (await pathExists(srcAgents)) {
76
+ await fs.copyFile(srcAgents, destPath);
77
+ written.push(rel);
78
+ continue;
79
+ }
80
+ }
81
+
82
+ if (protectedFiles.includes(rel)) {
83
+ const destPath = path.join(cwd, rel);
84
+ if (await pathExists(destPath)) {
85
+ skipped.push(rel);
86
+ continue;
87
+ }
88
+ }
89
+
90
+ const entry = projectionMap.get(rel);
91
+ if (!entry) {
92
+ throw new Error(`anws: managed file "${rel}" has no projection entry — manifest/registry mismatch`);
93
+ }
94
+
95
+ const destPath = path.join(cwd, rel);
96
+ await fs.mkdir(path.dirname(destPath), { recursive: true });
97
+
98
+ const srcPath = resolveCanonicalSource(entry.source);
99
+ if (!(await pathExists(srcPath))) {
100
+ throw new Error(
101
+ `anws: missing canonical template for "${rel}" (${entry.source}). Expected: ${srcPath}`
102
+ );
103
+ }
104
+ await fs.copyFile(srcPath, destPath);
105
+ written.push(rel);
106
+ }
107
+
108
+ return {
109
+ targetId: targetPlan.targetId,
110
+ targetLabel: targetPlan.targetLabel,
111
+ written,
112
+ skipped
113
+ };
114
+ }
115
+
116
+ module.exports = { copyDir, writeTargetFiles };
package/lib/diff.js CHANGED
@@ -145,6 +145,10 @@ async function collectManagedFileDiffs({
145
145
  }
146
146
 
147
147
  const entry = projectionMap.get(rel);
148
+ if (!entry && rel !== 'AGENTS.md') {
149
+ throw new Error(`anws: managed file "${rel}" has no projection entry — manifest/registry mismatch`);
150
+ }
151
+
148
152
  const metadata = entry
149
153
  ? {
150
154
  source: entry.source,
@@ -161,6 +165,13 @@ async function collectManagedFileDiffs({
161
165
  const srcPath = rel === 'AGENTS.md'
162
166
  ? srcAgents
163
167
  : path.join(path.join(__dirname, '..', 'templates'), entry.source);
168
+
169
+ if (rel !== 'AGENTS.md' && !(await pathExists(srcPath))) {
170
+ throw new Error(
171
+ `anws: missing canonical template for "${rel}" (${entry.source}). Expected: ${srcPath}`
172
+ );
173
+ }
174
+
164
175
  const existing = rel === 'AGENTS.md'
165
176
  ? { file: rel, absolutePath: path.join(cwd, rel), sourceKind: 'current' }
166
177
  : await resolveExistingManagedPath(cwd, rel);
package/lib/manifest.js CHANGED
@@ -21,6 +21,7 @@ const RESOURCE_REGISTRY = [
21
21
  { id: 'upgrade', type: 'workflow', source: '.agents/workflows/upgrade.md', fileName: 'upgrade.md' },
22
22
  { id: 'anws-system', type: 'skill', source: '.agents/skills/anws-system/SKILL.md', fileName: 'anws-system/SKILL.md', targets: ['codex', 'trae'] },
23
23
  { id: 'concept-modeler', type: 'skill', source: '.agents/skills/concept-modeler/SKILL.md', fileName: 'concept-modeler/SKILL.md' },
24
+ { id: 'code-reviewer', type: 'skill', source: '.agents/skills/code-reviewer/SKILL.md', fileName: 'code-reviewer/SKILL.md' },
24
25
  { id: 'design-reviewer', type: 'skill', source: '.agents/skills/design-reviewer/SKILL.md', fileName: 'design-reviewer/SKILL.md' },
25
26
  { id: 'nexus-mapper', type: 'skill', source: '.agents/skills/nexus-mapper/SKILL.md', fileName: 'nexus-mapper/SKILL.md' },
26
27
  { id: 'nexus-mapper-language-customization', type: 'skill', source: '.agents/skills/nexus-mapper/references/language-customization.md', fileName: 'nexus-mapper/references/language-customization.md' },
@@ -46,7 +47,9 @@ const RESOURCE_REGISTRY = [
46
47
  { id: 'task-planner-template', type: 'skill', source: '.agents/skills/task-planner/references/TASK_TEMPLATE.md', fileName: 'task-planner/references/TASK_TEMPLATE.md' },
47
48
  { id: 'task-reviewer', type: 'skill', source: '.agents/skills/task-reviewer/SKILL.md', fileName: 'task-reviewer/SKILL.md' },
48
49
  { id: 'tech-evaluator', type: 'skill', source: '.agents/skills/tech-evaluator/SKILL.md', fileName: 'tech-evaluator/SKILL.md' },
49
- { id: 'tech-evaluator-adr-template', type: 'skill', source: '.agents/skills/tech-evaluator/references/ADR_TEMPLATE.md', fileName: 'tech-evaluator/references/ADR_TEMPLATE.md' }
50
+ { id: 'tech-evaluator-adr-template', type: 'skill', source: '.agents/skills/tech-evaluator/references/ADR_TEMPLATE.md', fileName: 'tech-evaluator/references/ADR_TEMPLATE.md' },
51
+ { id: 'e2e-testing-guide', type: 'skill', source: '.agents/skills/e2e-testing-guide/SKILL.md', fileName: 'e2e-testing-guide/SKILL.md' },
52
+ { id: 'craft-authoring', type: 'skill', source: '.agents/skills/craft-authoring/SKILL.md', fileName: 'craft-authoring/SKILL.md' }
50
53
  ];
51
54
 
52
55
  function toArray(value) {