@haaaiawd/anws 1.2.5 → 2.0.0

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 (71) hide show
  1. package/README.md +208 -172
  2. package/bin/cli.js +22 -9
  3. package/lib/adapters/index.js +157 -0
  4. package/lib/agents.js +136 -1
  5. package/lib/changelog.js +187 -0
  6. package/lib/copy.js +72 -1
  7. package/lib/diff.js +270 -0
  8. package/lib/init.js +143 -125
  9. package/lib/install-state.js +195 -0
  10. package/lib/manifest.js +184 -42
  11. package/lib/output.js +185 -13
  12. package/lib/prompt.js +284 -0
  13. package/lib/resources/index.js +27 -0
  14. package/lib/update.js +291 -83
  15. package/package.json +10 -6
  16. package/templates/.agents/skills/concept-modeler/SKILL.md +176 -0
  17. package/templates/{.agent → .agents}/skills/design-reviewer/SKILL.md +6 -6
  18. package/templates/.agents/skills/nexus-mapper/SKILL.md +306 -0
  19. package/templates/.agents/skills/nexus-mapper/references/language-customization.md +164 -0
  20. package/templates/.agents/skills/nexus-mapper/references/output-schema.md +298 -0
  21. package/templates/.agents/skills/nexus-mapper/references/probe-protocol.md +246 -0
  22. package/templates/.agents/skills/nexus-mapper/scripts/extract_ast.py +706 -0
  23. package/templates/.agents/skills/nexus-mapper/scripts/git_detective.py +194 -0
  24. package/templates/.agents/skills/nexus-mapper/scripts/languages.json +127 -0
  25. package/templates/.agents/skills/nexus-mapper/scripts/query_graph.py +556 -0
  26. package/templates/.agents/skills/nexus-mapper/scripts/requirements.txt +6 -0
  27. package/templates/{.agent → .agents}/skills/report-template/SKILL.md +11 -14
  28. package/templates/.agents/skills/report-template/references/REPORT_TEMPLATE.md +100 -0
  29. package/templates/{.agent → .agents}/skills/runtime-inspector/SKILL.md +1 -1
  30. package/templates/.agents/skills/sequential-thinking/SKILL.md +166 -0
  31. package/templates/.agents/skills/spec-writer/SKILL.md +108 -0
  32. package/templates/{.agent → .agents}/skills/spec-writer/references/prd_template.md +1 -1
  33. package/templates/{.agent → .agents}/skills/system-architect/SKILL.md +3 -3
  34. package/templates/.agents/skills/system-architect/references/rfc_template.md +59 -0
  35. package/templates/{.agent → .agents}/skills/system-designer/SKILL.md +6 -6
  36. package/templates/{.agent → .agents}/skills/system-designer/references/system-design-template.md +75 -25
  37. package/templates/{.agent → .agents}/skills/task-planner/SKILL.md +1 -1
  38. package/templates/.agents/skills/task-planner/references/TASK_TEMPLATE.md +144 -0
  39. package/templates/{.agent → .agents}/skills/task-reviewer/SKILL.md +4 -3
  40. package/templates/{.agent → .agents}/skills/tech-evaluator/SKILL.md +2 -2
  41. package/templates/{.agent → .agents}/skills/tech-evaluator/references/ADR_TEMPLATE.md +10 -0
  42. package/templates/{.agent → .agents}/workflows/blueprint.md +32 -27
  43. package/templates/{.agent → .agents}/workflows/challenge.md +21 -15
  44. package/templates/{.agent → .agents}/workflows/change.md +23 -14
  45. package/templates/{.agent → .agents}/workflows/craft.md +8 -19
  46. package/templates/{.agent → .agents}/workflows/design-system.md +81 -54
  47. package/templates/{.agent → .agents}/workflows/explore.md +6 -19
  48. package/templates/{.agent → .agents}/workflows/forge.md +30 -32
  49. package/templates/{.agent → .agents}/workflows/genesis.md +68 -56
  50. package/templates/.agents/workflows/probe.md +168 -0
  51. package/templates/{.agent → .agents}/workflows/quickstart.md +7 -12
  52. package/templates/.agents/workflows/upgrade.md +192 -0
  53. package/templates/AGENTS.md +66 -45
  54. package/templates/.agent/skills/build-inspector/SKILL.md +0 -83
  55. package/templates/.agent/skills/complexity-guard/SKILL.md +0 -71
  56. package/templates/.agent/skills/complexity-guard/references/anti_patterns.md +0 -21
  57. package/templates/.agent/skills/concept-modeler/SKILL.md +0 -112
  58. package/templates/.agent/skills/concept-modeler/prompts/GLOSSARY_PROMPT.md +0 -40
  59. package/templates/.agent/skills/concept-modeler/references/ENTITY_EXTRACTION_PROMPT.md +0 -299
  60. package/templates/.agent/skills/concept-modeler/scripts/glossary_gen.py +0 -66
  61. package/templates/.agent/skills/git-forensics/SKILL.md +0 -74
  62. package/templates/.agent/skills/git-forensics/references/ANALYSIS_METHODOLOGY.md +0 -193
  63. package/templates/.agent/skills/git-forensics/scripts/__pycache__/git_forensics.cpython-313.pyc +0 -0
  64. package/templates/.agent/skills/git-forensics/scripts/git_forensics.py +0 -615
  65. package/templates/.agent/skills/git-forensics/scripts/git_hotspots.py +0 -118
  66. package/templates/.agent/skills/report-template/references/REPORT_TEMPLATE.md +0 -100
  67. package/templates/.agent/skills/spec-writer/SKILL.md +0 -108
  68. package/templates/.agent/skills/system-architect/references/rfc_template.md +0 -59
  69. package/templates/.agent/skills/task-planner/references/TASK_TEMPLATE.md +0 -144
  70. package/templates/.agent/workflows/scout.md +0 -139
  71. /package/templates/{.agent → .agents}/skills/system-designer/references/system-design-detail-template.md +0 -0
package/lib/update.js CHANGED
@@ -2,85 +2,186 @@
2
2
 
3
3
  const fs = require('node:fs/promises');
4
4
  const path = require('node:path');
5
- const { MANAGED_FILES, USER_PROTECTED_FILES } = require('./manifest');
6
- const { resolveAgentsInstall, printLegacyMigrationWarning, pathExists } = require('./agents');
7
- const { success, warn, error, info, fileLine, skippedLine, blank, logo } = require('./output');
8
-
9
- /**
10
- * anws update 将当前项目的托管文件更新到最新版本
11
- */
12
- async function update() {
5
+ const { buildProjectionPlan } = require('./manifest');
6
+ const { getTarget } = require('./adapters');
7
+ const { planAgentsUpdate, resolveAgentsInstall, printLegacyMigrationWarning, pathExists } = require('./agents');
8
+ const { collectManagedFileDiffs, printPreview } = require('./diff');
9
+ const { detectUpgrade, generateChangelog } = require('./changelog');
10
+ const { writeTargetFiles } = require('./copy');
11
+ const { createInstallLock, dedupeTargets, detectInstallState, summarizeTargetState, writeInstallLock } = require('./install-state');
12
+ const { confirm } = require('./prompt');
13
+ const { ROOT_AGENTS_FILE, resolveCanonicalSource } = require('./resources');
14
+ const { success, warn, error, info, fileLine, skippedLine, blank, logo, section } = require('./output');
15
+
16
+ async function update(options = {}) {
13
17
  const cwd = process.cwd();
14
- const agentDir = path.join(cwd, '.agent');
18
+ const check = !!options.check;
19
+ const legacyAgentDir = path.join(cwd, '.agent');
20
+ const { version } = require(path.join(__dirname, '..', 'package.json'));
21
+ const installState = await detectInstallState(cwd);
22
+ const legacyAgentExists = await pathExists(legacyAgentDir);
23
+ const isLegacyMigration = installState.selectedTargets.length === 0 && legacyAgentExists;
24
+ const selectedTargetIds = isLegacyMigration ? ['antigravity'] : installState.selectedTargets;
25
+ const targetPlans = buildProjectionPlan(selectedTargetIds);
15
26
 
16
- // 检查 .agent/ 是否存在
17
- const agentExists = await pathExists(agentDir);
18
- if (!agentExists) {
27
+ if (selectedTargetIds.length === 0 && !legacyAgentExists) {
19
28
  logo();
20
- error('No .agent/ found in current directory.');
29
+ error('No supported Anws target layout found in current directory.');
21
30
  info('Run `anws init` first to set up the workflow system.');
22
31
  process.exit(1);
23
32
  }
24
33
 
25
- // 询问确认
26
- const confirmed = await askUpdate();
27
- if (!confirmed) {
34
+ const srcAgents = ROOT_AGENTS_FILE;
35
+
36
+ if (isLegacyMigration) {
37
+ logo();
38
+ blank();
39
+ printLegacyMigrationNotice();
28
40
  blank();
29
- info('Aborted. No files were changed.');
30
- process.exit(0);
31
41
  }
32
42
 
33
- logo();
34
- // 仅覆盖托管文件;USER_PROTECTED_FILES 永远跳过
35
- const srcRoot = path.join(__dirname, '..', 'templates', '.agent');
36
- const srcAgents = path.join(__dirname, '..', 'templates', 'AGENTS.md');
37
- const agentsDecision = await resolveAgentsInstall({
38
- cwd,
39
- askMigrate,
40
- forceYes: !!global.__ANWS_FORCE_YES
41
- });
43
+ const versionState = await detectUpgrade({ cwd, version });
44
+ const targetContexts = [];
42
45
 
43
- if (!agentsDecision.shouldWriteRootAgents && agentsDecision.legacyExists) {
44
- info('Keeping legacy .agent/rules/agents.md. Will not pull root AGENTS.md.');
45
- }
46
- if (agentsDecision.shouldWarnMigration) {
47
- printLegacyMigrationWarning();
48
- }
46
+ for (const targetPlan of targetPlans) {
47
+ const target = getTarget(targetPlan.targetId);
48
+ const agentsDecision = target.id === 'antigravity'
49
+ ? await resolveAgentsInstall({
50
+ cwd,
51
+ askMigrate,
52
+ forceYes: !!global.__ANWS_FORCE_YES
53
+ })
54
+ : {
55
+ shouldWriteRootAgents: false,
56
+ shouldWarnMigration: false,
57
+ rootExists: false,
58
+ legacyExists: false
59
+ };
49
60
 
50
- const updated = [];
51
- const skipped = [];
61
+ if (!agentsDecision.shouldWriteRootAgents && agentsDecision.legacyExists) {
62
+ info('Keeping legacy .agent/rules/agents.md. Will not pull root AGENTS.md.');
63
+ }
64
+ if (agentsDecision.shouldWarnMigration) {
65
+ printLegacyMigrationWarning();
66
+ }
52
67
 
53
- for (const rel of MANAGED_FILES) {
54
- if (rel === 'AGENTS.md' && !agentsDecision.shouldWriteRootAgents) {
55
- skipped.push(rel);
56
- continue;
68
+ let agentsUpdatePlan = null;
69
+ if (agentsDecision.shouldWriteRootAgents && agentsDecision.rootExists) {
70
+ const templateContent = await fs.readFile(srcAgents, 'utf8');
71
+ const existingContent = await fs.readFile(path.join(cwd, 'AGENTS.md'), 'utf8');
72
+ agentsUpdatePlan = planAgentsUpdate({ templateContent, existingContent });
73
+
74
+ if (agentsUpdatePlan.warning) {
75
+ warn(agentsUpdatePlan.warning);
76
+ }
57
77
  }
58
78
 
59
- if (USER_PROTECTED_FILES.includes(rel)) {
60
- if (!(rel === 'AGENTS.md' && agentsDecision.shouldWriteRootAgents && !agentsDecision.rootExists)) {
61
- skipped.push(rel);
62
- continue;
79
+ const rawChanges = await collectManagedFileDiffs({
80
+ cwd,
81
+ projectionPlan: [targetPlan],
82
+ srcAgents,
83
+ shouldWriteRootAgents: agentsDecision.shouldWriteRootAgents,
84
+ agentsUpdatePlan
85
+ });
86
+ const changes = rawChanges.filter((item) => {
87
+ if (item.file !== 'AGENTS.md') return true;
88
+ if (agentsUpdatePlan && agentsUpdatePlan.mode === 'skip') return false;
89
+ return agentsDecision.shouldWriteRootAgents;
90
+ });
91
+
92
+ targetContexts.push({
93
+ target,
94
+ targetPlan,
95
+ agentsDecision,
96
+ agentsUpdatePlan,
97
+ changes
98
+ });
99
+ }
100
+
101
+ const changes = targetContexts.flatMap((context) => context.changes);
102
+
103
+ if (check) {
104
+ if (!versionState.needUpgrade) {
105
+ if (!isLegacyMigration) {
106
+ logo();
107
+ blank();
63
108
  }
109
+ info(`Already up to date. Latest recorded version is v${versionState.latestVersion || version}.`);
110
+ printTargetSelection(installState, targetContexts.map((context) => context.target));
111
+ return;
64
112
  }
113
+ if (!isLegacyMigration) {
114
+ logo();
115
+ blank();
116
+ }
117
+ printTargetSelection(installState, targetContexts.map((context) => context.target));
118
+ printPreview({
119
+ fromVersion: versionState.fromVersion,
120
+ toVersion: versionState.toVersion,
121
+ changes
122
+ });
123
+ return;
124
+ }
65
125
 
66
- const srcPath = rel === 'AGENTS.md' ? srcAgents : path.join(path.dirname(srcRoot), rel);
67
- const destPath = path.join(cwd, rel);
126
+ if (!versionState.needUpgrade) {
127
+ if (!isLegacyMigration) {
128
+ logo();
129
+ blank();
130
+ }
131
+ info(`Already up to date. Latest recorded version is v${versionState.latestVersion || version}.`);
132
+ return;
133
+ }
68
134
 
69
- const srcExists = await pathExists(srcPath);
70
- if (!srcExists) continue;
135
+ if (!isLegacyMigration) {
136
+ logo();
137
+ blank();
138
+ }
71
139
 
72
- await fs.mkdir(path.dirname(destPath), { recursive: true });
73
- await fs.copyFile(srcPath, destPath);
74
- updated.push(rel);
140
+ const confirmed = await askUpdate({
141
+ installState,
142
+ targets: targetContexts.map((context) => context.target)
143
+ });
144
+ if (!confirmed) {
145
+ blank();
146
+ info('Aborted. No files were changed.');
147
+ return;
148
+ }
149
+
150
+ const updated = [];
151
+ const skipped = [];
152
+ const successfulTargets = [];
153
+ const failedTargets = [];
154
+
155
+ for (const context of targetContexts) {
156
+ try {
157
+ const result = await writeTargetFiles(cwd, {
158
+ targetPlan: context.targetPlan,
159
+ protectedFiles: context.targetPlan.userProtectedFiles,
160
+ srcAgents,
161
+ shouldWriteRootAgents: context.agentsDecision.shouldWriteRootAgents,
162
+ agentsUpdatePlan: context.agentsUpdatePlan,
163
+ resolveCanonicalSource
164
+ });
165
+
166
+ updated.push(...result.written);
167
+ skipped.push(...result.skipped);
168
+ successfulTargets.push(summarizeTargetState(context.targetPlan, version));
169
+ } catch (error) {
170
+ failedTargets.push({
171
+ targetId: context.target.id,
172
+ targetLabel: context.target.label,
173
+ reason: error.message
174
+ });
175
+ }
75
176
  }
76
177
 
77
- // 打印摘要
78
178
  blank();
79
179
  info('Updated files:');
80
180
  blank();
81
181
  for (const rel of updated) {
82
182
  fileLine(rel.replace(/\\/g, '/'));
83
183
  }
184
+
84
185
  if (skipped.length > 0) {
85
186
  blank();
86
187
  info('Skipped (project-specific, preserved):');
@@ -89,16 +190,50 @@ async function update() {
89
190
  }
90
191
  }
91
192
 
92
- blank();
93
- success(`Done! ${updated.length} file(s) updated${skipped.length > 0 ? `, ${skipped.length} skipped` : ''}.`);
94
- info('Managed files have been updated to the latest version.');
95
- info('Your custom files in .agent/ were not touched.');
193
+ printTargetUpdateSummary(successfulTargets, failedTargets);
194
+
195
+ const changelogPath = await generateChangelog({
196
+ cwd,
197
+ version,
198
+ changes,
199
+ targetSummary: {
200
+ successfulTargets: successfulTargets.map((item) => `${item.targetLabel} (${item.targetId})`),
201
+ failedTargets: failedTargets.map((item) => `${item.targetLabel} (${item.targetId})`)
202
+ }
203
+ });
204
+ const generatedAt = new Date().toISOString();
205
+ await writeInstallLock(cwd, createInstallLock({
206
+ cliVersion: version,
207
+ generatedAt,
208
+ targets: dedupeTargets([
209
+ ...(installState.lockResult.lock?.targets || []),
210
+ ...successfulTargets
211
+ ]),
212
+ lastUpdateSummary: {
213
+ successfulTargets: successfulTargets.map((item) => item.targetId),
214
+ failedTargets: failedTargets.map((item) => item.targetId),
215
+ updatedAt: generatedAt
216
+ }
217
+ }));
218
+
219
+ let legacyCleanupLine = '';
220
+ if (isLegacyMigration) {
221
+ legacyCleanupLine = 'Legacy .agent/ was preserved. You can review and delete it manually after migration.';
222
+ const deleted = await maybeDeleteLegacyDir(legacyAgentDir);
223
+ if (deleted) {
224
+ legacyCleanupLine = 'Legacy .agent/ directory was deleted after confirmation.';
225
+ }
226
+ }
227
+
228
+ printUpdateCompletionSummary({
229
+ updatedCount: updated.length,
230
+ skippedCount: skipped.length,
231
+ changelogPath: path.relative(cwd, changelogPath).replace(/\\/g, '/'),
232
+ legacyCleanupLine
233
+ });
96
234
  }
97
235
 
98
- /**
99
- * 交互式确认更新操作(默认 N)。
100
- */
101
- async function askUpdate() {
236
+ async function askUpdate({ installState, targets }) {
102
237
  if (global.__ANWS_FORCE_YES) return true;
103
238
 
104
239
  if (!process.stdin.isTTY) {
@@ -106,23 +241,15 @@ async function askUpdate() {
106
241
  return false;
107
242
  }
108
243
 
109
- const readline = require('node:readline');
110
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
111
-
112
- return new Promise((resolve) => {
113
- rl.question(
114
- '\n\u26a0 This will overwrite all managed .agent/ files. Continue? [y/N] ',
115
- (answer) => {
116
- rl.close();
117
- resolve(answer.trim().toLowerCase() === 'y');
118
- }
119
- );
244
+ return confirm({
245
+ message: buildUpdateConfirmationMessage(targets),
246
+ contextLines: buildUpdateConfirmationContextLines(installState, targets),
247
+ confirmLabel: 'Continue',
248
+ cancelLabel: 'Cancel',
249
+ defaultValue: false
120
250
  });
121
251
  }
122
252
 
123
- /**
124
- * 询问用户是否同意迁移 agents.md
125
- */
126
253
  async function askMigrate() {
127
254
  if (global.__ANWS_FORCE_YES) return true;
128
255
 
@@ -130,18 +257,99 @@ async function askMigrate() {
130
257
  return false;
131
258
  }
132
259
 
133
- const readline = require('node:readline');
134
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
260
+ return confirm({
261
+ message: 'Legacy .agent/ directory detected. Migrate to .agents/?',
262
+ confirmLabel: 'Migrate',
263
+ cancelLabel: 'Keep legacy',
264
+ defaultValue: false
265
+ });
266
+ }
267
+
268
+ async function maybeDeleteLegacyDir(legacyAgentDir) {
269
+ const exists = await pathExists(legacyAgentDir);
270
+ if (!exists) return false;
271
+
272
+ if (global.__ANWS_FORCE_YES) {
273
+ return false;
274
+ }
275
+
276
+ if (!process.stdin.isTTY) {
277
+ return false;
278
+ }
135
279
 
136
- return new Promise((resolve) => {
137
- rl.question(
138
- '\n\u26a0 Legacy .agent/rules/agents.md detected. Do you want to migrate to root AGENTS.md? [y/N] ',
139
- (answer) => {
140
- rl.close();
141
- resolve(answer.trim().toLowerCase() === 'y');
142
- }
143
- );
280
+ const shouldDelete = await confirm({
281
+ message: 'Legacy .agent/ directory has been preserved. Delete it now?',
282
+ confirmLabel: 'Delete',
283
+ cancelLabel: 'Keep',
284
+ defaultValue: false
144
285
  });
286
+
287
+ if (!shouldDelete) return false;
288
+
289
+ await fs.rm(legacyAgentDir, { recursive: true, force: true });
290
+ return true;
291
+ }
292
+
293
+ function buildUpdateConfirmationMessage(targets) {
294
+ const labels = targets.map((target) => target.label).filter(Boolean);
295
+ if (labels.length === 0) {
296
+ return 'This will overwrite all managed files for the detected target layout.';
297
+ }
298
+ return `This will overwrite all managed files for: ${labels.join(', ')}.`;
299
+ }
300
+
301
+ function buildUpdateConfirmationContextLines(installState, targets) {
302
+ const lines = [
303
+ `Matched targets: ${targets.map((target) => `${target.label} (${target.id})`).join(', ') || 'none'}`,
304
+ installState.needsFallback ? 'State source: directory scan fallback' : 'State source: install-lock + directory scan'
305
+ ];
306
+ if (installState.drift.hasDrift) {
307
+ lines.push(`State drift detected. Missing on disk: ${installState.drift.missingOnDisk.join(', ') || 'none'}; untracked on disk: ${installState.drift.untrackedOnDisk.join(', ') || 'none'}.`);
308
+ }
309
+ return lines;
310
+ }
311
+
312
+ function printLegacyMigrationNotice() {
313
+ section('Legacy migration', [
314
+ 'Legacy .agent/ directory detected.',
315
+ 'anws update will migrate managed files into the Antigravity target structure.',
316
+ 'Your old .agent/ directory will be preserved for manual review.'
317
+ ], { minWidth: 60 });
318
+ }
319
+
320
+ function printTargetSelection(installState, targets) {
321
+ blank();
322
+ section('Target selection', [
323
+ `Matched targets: ${targets.map((target) => `${target.label} (${target.id})`).join(', ') || 'none'}`,
324
+ installState.needsFallback ? 'State source: directory scan fallback' : 'State source: install-lock + directory scan',
325
+ ...(installState.drift.hasDrift
326
+ ? [`State drift detected. Missing on disk: ${installState.drift.missingOnDisk.join(', ') || 'none'}; untracked on disk: ${installState.drift.untrackedOnDisk.join(', ') || 'none'}.`]
327
+ : [])
328
+ ]);
329
+ }
330
+
331
+ function printTargetUpdateSummary(successfulTargets, failedTargets) {
332
+ blank();
333
+ section('Update summary by target', [
334
+ ...successfulTargets.map((target) => `✔ ${target.targetLabel} (${target.targetId})`),
335
+ ...failedTargets.map((target) => `✖ ${target.targetLabel} (${target.targetId}) — ${target.reason}`)
336
+ ]);
337
+ }
338
+
339
+ function printUpdateCompletionSummary({ updatedCount, skippedCount, changelogPath, legacyCleanupLine }) {
340
+ blank();
341
+ section('Update completed', [
342
+ `✔ Done! ${updatedCount} file(s) updated${skippedCount > 0 ? `, ${skippedCount} skipped` : ''}.`,
343
+ 'Managed files have been updated to the latest version.',
344
+ 'Your custom files outside the selected target projections were not touched.',
345
+ ...(legacyCleanupLine ? [legacyCleanupLine] : []),
346
+ `Generated upgrade record: ${changelogPath}`,
347
+ 'Run `/upgrade` in your AI IDE to update your architecture docs.'
348
+ ], { minWidth: 60 });
145
349
  }
146
350
 
147
351
  module.exports = update;
352
+
353
+
354
+
355
+
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@haaaiawd/anws",
3
- "version": "1.2.5",
4
- "description": "A spec-driven workflow framework for AI-assisted development. Empowers prompt engineers to build production-ready software through structured PRD → Architecture → Task decomposition. Designed for Antigravity to enforce design-first principles and prevent architectural drift in vibe coding.",
3
+ "version": "2.0.0",
4
+ "description": "Anws — A spec-driven workflow framework for AI-assisted development. Empowers prompt engineers to build production-ready software through structured PRD → Architecture → Task decomposition. Works with Claude Code, GitHub Copilot, Cursor, Windsurf, and any tool that reads AGENTS.md.",
5
5
  "keywords": [
6
- "antigravity",
6
+ "anws",
7
7
  "agentic-ai",
8
8
  "workflow-orchestration",
9
9
  "spec-driven",
@@ -11,12 +11,16 @@
11
11
  "vibe-coding",
12
12
  "prompt-engineering",
13
13
  "devops-for-ai",
14
- "skills-framework"
14
+ "skills-framework",
15
+ "claude-code",
16
+ "github-copilot",
17
+ "cursor",
18
+ "windsurf"
15
19
  ],
16
- "homepage": "https://github.com/Haaaiawd/Antigravity-Workflow-System",
20
+ "homepage": "https://github.com/Haaaiawd/Anws",
17
21
  "repository": {
18
22
  "type": "git",
19
- "url": "git+https://github.com/Haaaiawd/Antigravity-Workflow-System.git"
23
+ "url": "git+https://github.com/Haaaiawd/Anws.git"
20
24
  },
21
25
  "author": "haaaiawd <1134180104@qq.com>",
22
26
  "license": "MIT",
@@ -0,0 +1,176 @@
1
+ ---
2
+ name: concept-modeler
3
+ description: 当用户需求模糊、术语不清晰时使用。通过交互式追问澄清领域概念,提取实体、流程和暗物质。由 /genesis Step 1 调用。
4
+ ---
5
+
6
+ # 领域建模师 (Domain Modeler)
7
+
8
+ > "如果你描述不清楚,你就造不出来。" —— Eric Evans
9
+
10
+ 本技能通过**交互式追问**将用户的"感觉词"转化为清晰的领域模型。
11
+
12
+ ---
13
+
14
+ ## 🎯 使命与定位
15
+
16
+ **这个技能是什么**: 通过与用户交互,澄清模糊需求,建立领域模型(实体、流程、暗物质)。
17
+
18
+ **何时调用**:
19
+ - `/genesis` Step 1: 需求澄清阶段
20
+ - 用户需求使用模糊术语("同步"、"列表"、"管理")
21
+ - 需要建立 Ubiquitous Language
22
+
23
+ **何时不调用**:
24
+ - 需求已经清晰、术语已定义
25
+ - 纯技术实现讨论(无需领域建模)
26
+
27
+ ---
28
+
29
+ ## ⚠️ 核心原则
30
+
31
+ > [!IMPORTANT]
32
+ > **一次只问一个问题,不一次性输出所有问题。**
33
+ >
34
+ > **为什么?** 用户一次只能思考一个问题。逐个追问能获得更准确的答案,也避免用户被问题淹没。
35
+
36
+ ---
37
+
38
+ ## 🧭 交互流程 (Interactive Process)
39
+
40
+ ### Step 1: 扫描模糊区域
41
+
42
+ **目标**: 识别需求中的模糊术语和缺失信息。
43
+
44
+ > [!IMPORTANT]
45
+ > 你**必须**先扫描用户需求,识别以下类别的模糊点:
46
+ >
47
+ > | 类别 | 检查问题 |
48
+ > | :--- | :--- |
49
+ > | **实体模糊** | "列表"是什么?`Wishlist`?`ShoppingCart`?`TodoList`? |
50
+ > | **动词模糊** | "同步"是单向/双向?实时/批量?失败策略? |
51
+ > | **暗物质** | 用户只描述 Happy Path——错误处理?持久化?认证? |
52
+ > | **边界模糊** | 谁能访问?数据量多大?并发要求? |
53
+
54
+ **内部产出**: 生成候选问题队列(最多 5 个),按影响排序。**不输出队列**。
55
+
56
+ ---
57
+
58
+ ### Step 2: 交互式追问循环
59
+
60
+ **目标**: 逐个澄清模糊点,每次只问一个问题。
61
+
62
+ > [!IMPORTANT]
63
+ > **追问规则**:
64
+ > - 最多问 **5 个问题**
65
+ > - 每个问题必须是**多选题**或**短回答(≤5 词)**
66
+ > - 每次只输出**一个问题**
67
+
68
+ #### 2.1 多选题格式
69
+
70
+ 对于有多种明确选项的问题:
71
+
72
+ ```markdown
73
+ **推荐:** 选项 B - 实时双向同步能保证数据一致性,适合用户多设备场景。
74
+
75
+ | 选项 | 描述 |
76
+ | :--- | :--- |
77
+ | A | 单向同步(仅上传) |
78
+ | B | 实时双向同步 |
79
+ | C | 批量定时同步 |
80
+ | 自定义 | 提供简短描述(≤5 词) |
81
+
82
+ 回复选项字母(如 "B"),说 "yes" 或 "推荐" 接受推荐,或提供自定义答案。
83
+ ```
84
+
85
+ #### 2.2 短回答格式
86
+
87
+ 对于需要用户自定义的问题:
88
+
89
+ ```markdown
90
+ **建议:** 用户愿望清单 - 这是电商场景最常见的术语。
91
+
92
+ 格式: 简短回答(≤5 词)。说 "yes" 或 "建议" 接受建议,或提供你的答案。
93
+ ```
94
+
95
+ #### 2.3 停止条件
96
+
97
+ 停止追问当:
98
+ - 所有关键模糊点已澄清
99
+ - 用户说 "done"、"好了"、"继续"
100
+ - 已问满 5 个问题
101
+
102
+ ---
103
+
104
+ ### Step 3: 增量更新模型
105
+
106
+ **目标**: 每次获得答案后,立即更新领域模型。
107
+
108
+ > [!IMPORTANT]
109
+ > **每个答案接受后立即更新**,不要等所有问题结束。
110
+
111
+ **更新规则**:
112
+ 1. 实体澄清 → 更新 `entities` 列表
113
+ 2. 动词澄清 → 更新 `flows` 列表
114
+ 3. 暗物质识别 → 更新 `missing_components` 列表
115
+ 4. 术语统一 → 记录到 `glossary`
116
+
117
+ ---
118
+
119
+ ## 📤 输出格式
120
+
121
+ **输出路径**: `.anws/v{N}/concept_model.json`
122
+
123
+ ```json
124
+ {
125
+ "glossary": {
126
+ "Wishlist": "用户的愿望清单,可添加商品但不直接结算",
127
+ "Sync": "实时双向同步,保证多设备数据一致"
128
+ },
129
+ "entities": [
130
+ { "name": "Wishlist", "type": "聚合根", "necessity": "必须", "description": "用户的愿望清单" },
131
+ { "name": "WishlistItem", "type": "实体", "necessity": "必须", "description": "愿望清单中的商品项" }
132
+ ],
133
+ "flows": [
134
+ { "from": "User", "action": "添加", "to": "Wishlist", "data": "Product ID", "trigger": "用户点击" },
135
+ { "from": "Wishlist", "action": "同步", "to": "RemoteServer", "data": "全量数据", "mode": "实时双向" }
136
+ ],
137
+ "missing_components": [
138
+ { "component": "同步冲突解决", "category": "错误处理", "priority": "高", "reason": "多设备同时修改" },
139
+ { "component": "离线队列", "category": "可靠性", "priority": "中", "reason": "网络断开时暂存操作" }
140
+ ],
141
+ "clarifications": [
142
+ { "question": "同步是实时的还是批量的?", "answer": "实时双向同步" }
143
+ ]
144
+ }
145
+ ```
146
+
147
+ ---
148
+
149
+ ## 🛡️ 老师傅守则
150
+
151
+ 1. **不要假设**: 永远不要假设你理解了用户的词汇。追问确认。
152
+ 2. **一次一个**: 用户一次只能思考一个问题。不要输出问题列表。
153
+ 3. **推荐优先**: 给出推荐选项 + 理由,让用户更容易决策。
154
+ 4. **增量更新**: 每个答案立即写入文件,避免上下文丢失。
155
+ 5. **术语统一**: 一旦确定术语,全程使用该术语,避免同义词。
156
+ 6. **工具优先提问**: 如果当前环境提供 `ask question` 等结构化提问工具,优先使用工具发起问题,而不是让用户手动输入整段回复。
157
+
158
+ ---
159
+
160
+ ## 📋 完成标准
161
+
162
+ <completion_criteria>
163
+ - ✅ 澄清了关键模糊术语(记录到 glossary)
164
+ - ✅ 识别了核心实体和关系
165
+ - ✅ 发现了用户没说的暗物质组件
166
+ - ✅ 领域模型保存到 `.anws/v{N}/concept_model.json`
167
+ - ✅ 用户确认术语理解正确
168
+ </completion_criteria>
169
+
170
+ ---
171
+
172
+ ## Collaboration
173
+
174
+ * **Before**: 用户提供的模糊需求描述
175
+ * **After**: `spec-writer` 基于澄清后的需求生成 PRD
176
+ * **Synergy**: 你的领域模型为后续架构设计提供清晰的术语基础