autosnippet 3.2.3 → 3.2.6
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 +2 -4
- package/bin/cli.js +164 -145
- package/config/constitution.yaml +3 -0
- package/dashboard/dist/assets/{index-DNOHYBhy.css → index-BaGY7kJI.css} +1 -1
- package/dashboard/dist/assets/{index-6itPuGFl.js → index-DfHY_3ln.js} +25 -25
- package/dashboard/dist/index.html +2 -2
- package/lib/cli/CliLogger.js +78 -0
- package/lib/cli/SetupService.js +9 -719
- package/lib/cli/UpgradeService.js +23 -398
- package/lib/cli/deploy/FileDeployer.js +562 -0
- package/lib/cli/deploy/FileManifest.js +272 -0
- package/lib/external/mcp/McpServer.js +22 -26
- package/lib/external/mcp/autoApproveInjector.js +1 -0
- package/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +5 -5
- package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +25 -3
- package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +6 -6
- package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +4 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +5 -5
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +89 -44
- package/lib/external/mcp/handlers/consolidated.js +8 -9
- package/lib/external/mcp/handlers/dimension-complete-external.js +4 -4
- package/lib/external/mcp/handlers/guard.js +283 -5
- package/lib/external/mcp/handlers/task.js +183 -9
- package/lib/external/mcp/tools.js +32 -81
- package/lib/http/routes/task.js +55 -0
- package/lib/service/chat/AnalystAgent.js +12 -12
- package/lib/service/chat/ChatAgent.js +227 -545
- package/lib/service/chat/ChatAgentPrompts.js +9 -11
- package/lib/service/chat/ContextWindow.js +2 -296
- package/lib/service/chat/EpisodicConsolidator.js +15 -15
- package/lib/service/chat/ExplorationTracker.js +1262 -0
- package/lib/service/chat/HandoffProtocol.js +8 -9
- package/lib/service/chat/Memory.js +4 -0
- package/lib/service/chat/ProducerAgent.js +9 -6
- package/lib/service/chat/ProjectSemanticMemory.js +4 -0
- package/lib/service/chat/ReasoningTrace.js +182 -0
- package/lib/service/chat/WorkingMemory.js +4 -0
- package/lib/service/chat/memory/ActiveContext.js +910 -0
- package/lib/service/chat/memory/MemoryCoordinator.js +662 -0
- package/lib/service/chat/memory/PersistentMemory.js +450 -0
- package/lib/service/chat/memory/SessionStore.js +896 -0
- package/lib/service/chat/memory/index.js +13 -0
- package/lib/service/chat/tools/ast-graph.js +17 -16
- package/lib/service/cursor/AgentInstructionsGenerator.js +75 -40
- package/lib/service/cursor/FileProtection.js +4 -1
- package/lib/service/guard/GuardCheckEngine.js +10 -3
- package/lib/service/task/TaskGraphService.js +3 -3
- package/lib/shared/LanguageService.js +2 -1
- package/package.json +1 -1
- package/skills/autosnippet-intent/SKILL.md +1 -3
- package/skills/autosnippet-recipes/SKILL.md +1 -3
- package/templates/claude-code/commands/prime.md +19 -0
- package/templates/claude-code/hooks/autosnippet-session.sh +63 -0
- package/templates/claude-code/settings.json +21 -0
- package/templates/copilot-instructions.md +66 -177
- package/templates/cursor-hooks/commands/prime.md +12 -0
- package/templates/cursor-hooks/hooks/session-start.sh +10 -0
- package/templates/cursor-hooks/hooks.json +11 -0
- package/templates/cursor-rules/autosnippet-conventions.mdc +52 -3
- package/templates/cursor-rules/autosnippet-workflow.mdc +51 -27
- package/lib/external/mcp/handlers/decide.js +0 -109
- package/lib/external/mcp/handlers/ready.js +0 -42
- package/lib/service/chat/ReasoningLayer.js +0 -888
- package/templates/claude-hooks.yaml +0 -19
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Module — 统一导出
|
|
3
|
+
*
|
|
4
|
+
* Phase 2: MemoryCoordinator + legacy module re-exports
|
|
5
|
+
* Phase 3: ActiveContext (合并 WorkingMemory + ReasoningTrace)
|
|
6
|
+
* Phase 4: SessionStore (合并 EpisodicMemory + ToolResultCache)
|
|
7
|
+
* Phase 5: PersistentMemory (继承 ProjectSemanticMemory + 增强)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export { MemoryCoordinator } from './MemoryCoordinator.js';
|
|
11
|
+
export { ActiveContext } from './ActiveContext.js';
|
|
12
|
+
export { SessionStore } from './SessionStore.js';
|
|
13
|
+
export { PersistentMemory } from './PersistentMemory.js';
|
|
@@ -451,19 +451,18 @@ export const noteFinding = {
|
|
|
451
451
|
required: ['finding'],
|
|
452
452
|
},
|
|
453
453
|
handler: async (params, ctx) => {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
return `📌 已记录发现 [${importance}/10]: "${finding.substring(0, 80)}" — 当前共 ${workingMemory.scratchpadSize} 条关键发现`;
|
|
454
|
+
// v5.0: 通过 MemoryCoordinator
|
|
455
|
+
const coordinator = ctx._memoryCoordinator;
|
|
456
|
+
if (coordinator) {
|
|
457
|
+
const finding = params.finding || '';
|
|
458
|
+
const evidence = params.evidence || '';
|
|
459
|
+
const importance = params.importance || 5;
|
|
460
|
+
const round = ctx._currentRound || 0;
|
|
461
|
+
const scopeId = ctx._dimensionScopeId || undefined;
|
|
462
|
+
return coordinator.noteFinding(finding, evidence, importance, round, scopeId);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return '⚠ 工作记忆未初始化 (仅在 bootstrap 分析期间可用)';
|
|
467
466
|
},
|
|
468
467
|
};
|
|
469
468
|
|
|
@@ -490,12 +489,14 @@ export const getPreviousEvidence = {
|
|
|
490
489
|
required: ['query'],
|
|
491
490
|
},
|
|
492
491
|
handler: async (params, ctx) => {
|
|
493
|
-
|
|
494
|
-
|
|
492
|
+
// v5.0: 通过 MemoryCoordinator 获取 SessionStore
|
|
493
|
+
const coordinator = ctx._memoryCoordinator;
|
|
494
|
+
const sessionStore = coordinator?.getSessionStore();
|
|
495
|
+
if (!sessionStore) {
|
|
495
496
|
return '没有前序维度的证据可用。';
|
|
496
497
|
}
|
|
497
498
|
|
|
498
|
-
const results =
|
|
499
|
+
const results = sessionStore.searchEvidence(params.query, params.dimId || undefined);
|
|
499
500
|
|
|
500
501
|
if (results.length === 0) {
|
|
501
502
|
return `没有找到与 "${params.query}" 相关的前序证据。建议自行搜索。`;
|
|
@@ -55,9 +55,7 @@ const MCP_TOOLS_SUMMARY = [
|
|
|
55
55
|
{ name: 'autosnippet_skill', desc: 'Skill management (list/load/create/update/delete/suggest)' },
|
|
56
56
|
{ name: 'autosnippet_save_document', desc: 'Save development document (auto-publish)' },
|
|
57
57
|
{ name: 'autosnippet_bootstrap', desc: 'Project cold-start & scan (knowledge/refine/scan)' },
|
|
58
|
-
{ name: '
|
|
59
|
-
{ name: 'autosnippet_decide', desc: 'Decision management (record/revise/unpin/list)' },
|
|
60
|
-
{ name: 'autosnippet_task', desc: 'Task CRUD (create/claim/close/fail/defer/progress/decompose)' },
|
|
58
|
+
{ name: 'autosnippet_task', desc: 'Unified task & decision management: prime (session entry, CALL FIRST) / create/claim/close/fail/defer/progress/decompose (task CRUD) / record_decision/revise_decision/unpin_decision/list_decisions (decisions)' },
|
|
61
59
|
{ name: 'autosnippet_health', desc: 'Service health & KB statistics' },
|
|
62
60
|
{ name: 'autosnippet_capabilities', desc: 'List all available MCP tools (self-discovery)' },
|
|
63
61
|
];
|
|
@@ -89,14 +87,22 @@ export class AgentInstructionsGenerator {
|
|
|
89
87
|
// 构建共享内容块
|
|
90
88
|
const sections = this._buildSections({ rules, patterns, skills });
|
|
91
89
|
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
// 避免 IDE 上下文重复:
|
|
91
|
+
// - 不自动生成 CLAUDE.md(用户自己维护)
|
|
92
|
+
// - 如果项目已有 CLAUDE.md,跳过 AGENTS.md(避免两份文件同时注入 IDE 上下文)
|
|
93
|
+
const claudePath = path.join(this.projectRoot, 'CLAUDE.md');
|
|
94
|
+
const hasClaudeMd = fs.existsSync(claudePath);
|
|
95
|
+
|
|
96
|
+
const agents = hasClaudeMd
|
|
97
|
+
? { filePath: path.join(this.projectRoot, 'AGENTS.md'), tokensUsed: 0, skipped: true }
|
|
98
|
+
: this._writeAgentsMd(sections);
|
|
99
|
+
const claude = { filePath: claudePath, tokensUsed: 0, skipped: true }; // 不自动生成
|
|
95
100
|
const copilot = this._writeCopilotInstructions(sections);
|
|
96
101
|
|
|
97
102
|
const duration = Date.now() - startTime;
|
|
98
|
-
const
|
|
99
|
-
const
|
|
103
|
+
const allResults = [agents, claude, copilot];
|
|
104
|
+
const filesWritten = allResults.filter((r) => !r.skipped).length;
|
|
105
|
+
const skippedFiles = allResults.filter((r) => r.skipped);
|
|
100
106
|
if (skippedFiles.length > 0) {
|
|
101
107
|
this.logger.info?.(
|
|
102
108
|
`[AgentInstructions] Skipped ${skippedFiles.length} file(s) — ` +
|
|
@@ -279,21 +285,24 @@ export class AgentInstructionsGenerator {
|
|
|
279
285
|
lines.push('');
|
|
280
286
|
|
|
281
287
|
// Key tools highlight for Claude
|
|
282
|
-
lines.push('###
|
|
288
|
+
lines.push('### Task Workflow', '');
|
|
289
|
+
lines.push(
|
|
290
|
+
'1. **Every message → `autosnippet_task({ operation: "prime" })`** — Load decisions + tasks + knowledge context (ALWAYS FIRST)'
|
|
291
|
+
);
|
|
283
292
|
lines.push(
|
|
284
|
-
'
|
|
293
|
+
'2. **Create task for non-trivial work** — ≥2 files OR ≥10 lines → `create` → `claim` → code → `close`'
|
|
285
294
|
);
|
|
286
295
|
lines.push(
|
|
287
|
-
'
|
|
296
|
+
'3. **User agrees/disagrees → `autosnippet_task({ operation: "record_decision" })`** — Persist decision immediately'
|
|
288
297
|
);
|
|
289
298
|
lines.push(
|
|
290
|
-
'
|
|
299
|
+
'4. **Before writing code**: `autosnippet_search({ query: "<topic>" })` to find relevant patterns'
|
|
291
300
|
);
|
|
292
301
|
lines.push(
|
|
293
|
-
'
|
|
302
|
+
'5. **Complete task**: `autosnippet_task({ operation: "close", id: "<id>", reason: "..." })`'
|
|
294
303
|
);
|
|
295
304
|
lines.push(
|
|
296
|
-
'
|
|
305
|
+
'6. **Session end**: Close or defer ALL in_progress tasks — zero in_progress on exit'
|
|
297
306
|
);
|
|
298
307
|
lines.push('');
|
|
299
308
|
|
|
@@ -361,12 +370,7 @@ export class AgentInstructionsGenerator {
|
|
|
361
370
|
lines.push('');
|
|
362
371
|
|
|
363
372
|
// Workflow
|
|
364
|
-
lines.push(
|
|
365
|
-
lines.push('1. Search before coding: `autosnippet_search({ query: "..." })`');
|
|
366
|
-
lines.push('2. Prefer Recipe over raw source code');
|
|
367
|
-
lines.push('3. Submit discoveries: `autosnippet_submit_knowledge({ ... })`');
|
|
368
|
-
lines.push('4. Do NOT directly modify `AutoSnippet/` or `.autosnippet/` files');
|
|
369
|
-
lines.push('');
|
|
373
|
+
lines.push(...this._renderWorkflow());
|
|
370
374
|
|
|
371
375
|
const content = `${lines.join('\n')}\n`;
|
|
372
376
|
const destDir = path.join(this.projectRoot, '.github');
|
|
@@ -388,10 +392,34 @@ export class AgentInstructionsGenerator {
|
|
|
388
392
|
*/
|
|
389
393
|
_renderConstraints() {
|
|
390
394
|
return [
|
|
391
|
-
'##
|
|
395
|
+
'## CRITICAL: You Operate autosnippet_task — The User Doesn\'t',
|
|
396
|
+
'',
|
|
397
|
+
'You are the task operator. Users speak naturally; you translate to task operations.',
|
|
398
|
+
'DO NOT tell users to call autosnippet_task. That\'s YOUR job.',
|
|
399
|
+
'',
|
|
400
|
+
'- WRONG: "You can run autosnippet_task({ operation: \'create\' }) to create a task"',
|
|
401
|
+
'- RIGHT: *(you run create yourself and tell the user "Created task asd-42: Fix login bug")*',
|
|
402
|
+
'',
|
|
403
|
+
'## Task Tracking Rules (MANDATORY)',
|
|
392
404
|
'',
|
|
393
|
-
'1. **
|
|
394
|
-
'2.
|
|
405
|
+
'1. **MUST prime on EVERY message** — `autosnippet_task({ operation: "prime" })` BEFORE anything else. No exceptions.',
|
|
406
|
+
'2. **MUST create task for non-trivial work** — ≥2 files OR ≥10 lines → create BEFORE starting.',
|
|
407
|
+
'3. **MUST claim before coding** — `autosnippet_task({ operation: "claim", id })` then code.',
|
|
408
|
+
'4. **MUST close when done** — `autosnippet_task({ operation: "close", id, reason })` with meaningful reason.',
|
|
409
|
+
'5. **MUST handle unfinished tasks first** — If prime shows in-progress, ask user: Continue, Defer, Abandon? Do NOT auto-resume.',
|
|
410
|
+
'6. **NEVER skip prime** — Even for follow-up messages.',
|
|
411
|
+
'7. **NEVER start new work with open in-progress tasks** — Handle existing first.',
|
|
412
|
+
'8. **NEVER leave tasks in in_progress when session ends** — Close or defer everything.',
|
|
413
|
+
'9. **NEVER tell the user to run task commands** — You are the operator.',
|
|
414
|
+
'',
|
|
415
|
+
'When in doubt → create a task. When idle → `autosnippet_task({ operation: "ready" })`.',
|
|
416
|
+
'',
|
|
417
|
+
'**When NOT to create**: Quick questions, single-file trivial fixes (<10 lines), code explanation, running tests.',
|
|
418
|
+
'',
|
|
419
|
+
'## Knowledge Rules',
|
|
420
|
+
'',
|
|
421
|
+
'1. **User agrees/disagrees with a plan → `autosnippet_task({ operation: "record_decision" })` immediately** — Persist team memory first.',
|
|
422
|
+
'2. **Do NOT modify** knowledge base files directly (`AutoSnippet/recipes/`, `.autosnippet/`).',
|
|
395
423
|
'3. **Prefer Recipes** as project standards; source code is supplementary.',
|
|
396
424
|
'4. Use `autosnippet_search` for knowledge retrieval; do not retry on failure in the same turn.',
|
|
397
425
|
'5. Skills handle semantics and workflow; MCP handles capabilities — do not hardcode URLs in Skills.',
|
|
@@ -404,28 +432,35 @@ export class AgentInstructionsGenerator {
|
|
|
404
432
|
*/
|
|
405
433
|
_renderWorkflow() {
|
|
406
434
|
return [
|
|
407
|
-
'##
|
|
435
|
+
'## User Says → You Run',
|
|
436
|
+
'',
|
|
437
|
+
'| User Says | Your Action |',
|
|
438
|
+
'|---|---|',
|
|
439
|
+
'| "Fix this bug" / "帮我修 bug" | `create` → `claim` → code → `close` |',
|
|
440
|
+
'| "Implement this" / "做功能" | `create` → `claim` → code → `close` |',
|
|
441
|
+
'| "Continue" / "继续" | resume in-progress → code → `close` |',
|
|
442
|
+
'| "Pause" / "先不做了" | `defer(id, reason)` |',
|
|
443
|
+
'| "Abandon" / "不做了" | `fail(id, reason)` |',
|
|
444
|
+
'| "Break it down" / "太大了" | `decompose(id, subtasks)` |',
|
|
445
|
+
'| "What\'s next" / "有什么要做的" | `ready()` → present list |',
|
|
446
|
+
'| "Agreed" / "就这么定了" | `record_decision(...)` |',
|
|
447
|
+
'| Quick question (no code) | No task. Just answer. |',
|
|
448
|
+
'',
|
|
449
|
+
'## Session Closing Protocol',
|
|
450
|
+
'',
|
|
451
|
+
'Before ending work, you MUST complete this checklist:',
|
|
408
452
|
'',
|
|
409
|
-
'
|
|
410
|
-
'
|
|
453
|
+
'- [ ] Close every claimed task with reason describing what was accomplished',
|
|
454
|
+
'- [ ] Defer any incomplete tasks with notes on why and what remains',
|
|
455
|
+
'- [ ] Verify zero tasks in in_progress state',
|
|
456
|
+
'- [ ] If prime showed ready tasks, mention them to the user for next session',
|
|
411
457
|
'',
|
|
412
|
-
'
|
|
413
|
-
'2. `autosnippet_task({ operation: "claim", id: "asd-xxx" })` — Start working',
|
|
414
|
-
'3. `autosnippet_search({ query: "<topic>" })` — Search knowledge before coding',
|
|
415
|
-
'4. **CODE** — Write the implementation',
|
|
416
|
-
'5. `autosnippet_guard({ code: "<code>" })` — Check compliance',
|
|
417
|
-
'6. `autosnippet_task({ operation: "close", id: "asd-xxx" })` — Complete',
|
|
458
|
+
'**Work is not done until all tasks are closed or deferred.**',
|
|
418
459
|
'',
|
|
419
|
-
'
|
|
420
|
-
'When editor shows diagnostics from "AutoSnippet Guard":',
|
|
421
|
-
'1. Read the `ruleId` from the diagnostic message',
|
|
422
|
-
'2. `autosnippet_search({ query: "<ruleId>" })` to find the Recipe',
|
|
423
|
-
'3. Apply the Recipe\'s `doClause` + `coreCode` to fix',
|
|
424
|
-
'4. Save and verify the diagnostic disappears',
|
|
460
|
+
'## Context Pressure',
|
|
425
461
|
'',
|
|
426
|
-
'### Context Pressure',
|
|
427
462
|
'- `_contextHint: CONTEXT_PRESSURE:WARNING` → Summarize completed work, then continue',
|
|
428
|
-
'- `_contextHint: CONTEXT_PRESSURE:CRITICAL` → Call `
|
|
463
|
+
'- `_contextHint: CONTEXT_PRESSURE:CRITICAL` → Call `autosnippet_task({ operation: "prime" })` immediately',
|
|
429
464
|
'',
|
|
430
465
|
];
|
|
431
466
|
}
|
|
@@ -17,8 +17,11 @@ import fs from 'node:fs';
|
|
|
17
17
|
/**
|
|
18
18
|
* AutoSnippet 文件签名模式(case-insensitive)
|
|
19
19
|
* 检查文件前 1024 字节即可——签名总在文件头部
|
|
20
|
+
* 匹配以下任一标记:
|
|
21
|
+
* - "Auto-generated by AutoSnippet" / "Auto-generated by [AutoSnippet]"
|
|
22
|
+
* - "<!-- autosnippet:begin -->" (模板起始标记)
|
|
20
23
|
*/
|
|
21
|
-
const SIGNATURE_PATTERN = /auto-generated by (?:\[)?autosnippet(?:\])
|
|
24
|
+
const SIGNATURE_PATTERN = /auto-generated by (?:\[)?autosnippet(?:\])?|autosnippet:begin/i;
|
|
22
25
|
|
|
23
26
|
/**
|
|
24
27
|
* 检查文件是否可以被 AutoSnippet 安全写入
|
|
@@ -592,7 +592,7 @@ export class GuardCheckEngine {
|
|
|
592
592
|
id: g.id || r.id,
|
|
593
593
|
name: g.name || r.title,
|
|
594
594
|
message: g.message || r.description || r.title,
|
|
595
|
-
languages: r.language ? [r.language] : [],
|
|
595
|
+
languages: r.language ? [r.language, LanguageService.toGuardLangId(r.language)] : [],
|
|
596
596
|
severity: g.severity || 'warning',
|
|
597
597
|
dimension: r.scope || 'file',
|
|
598
598
|
source: 'database',
|
|
@@ -647,9 +647,16 @@ export class GuardCheckEngine {
|
|
|
647
647
|
}
|
|
648
648
|
}
|
|
649
649
|
|
|
650
|
-
//
|
|
650
|
+
// 按语言过滤(标准化比较:objc == objectivec == objective-c)
|
|
651
651
|
if (language) {
|
|
652
|
-
|
|
652
|
+
const langNorm = LanguageService.toGuardLangId(language);
|
|
653
|
+
rules = rules.filter(
|
|
654
|
+
(r) =>
|
|
655
|
+
!r.languages?.length ||
|
|
656
|
+
r.languages.includes(language) ||
|
|
657
|
+
r.languages.includes(langNorm) ||
|
|
658
|
+
r.languages.some((l) => LanguageService.toGuardLangId(l) === langNorm)
|
|
659
|
+
);
|
|
653
660
|
}
|
|
654
661
|
|
|
655
662
|
// 按 disabledRules 配置过滤
|
|
@@ -398,7 +398,7 @@ export class TaskGraphService {
|
|
|
398
398
|
}
|
|
399
399
|
|
|
400
400
|
// P1 Result Compaction: compact 模式 — description 截断到 120 chars
|
|
401
|
-
// Agent 需要完整内容时调用
|
|
401
|
+
// Agent 需要完整内容时调用 autosnippet_task({ operation: 'list_decisions' })
|
|
402
402
|
result.decisions = activeDecisions.map((t) => ({
|
|
403
403
|
id: t.id,
|
|
404
404
|
title: t.title,
|
|
@@ -424,13 +424,13 @@ export class TaskGraphService {
|
|
|
424
424
|
|
|
425
425
|
result._decisionHint =
|
|
426
426
|
'These are team-agreed decisions (compact view). Respect them in your response. ' +
|
|
427
|
-
'Call
|
|
427
|
+
'Call autosnippet_task({ operation: "list_decisions" }) for full details. ' +
|
|
428
428
|
"If the user's request conflicts with a decision, point out the conflict and ask whether to revise_decision.";
|
|
429
429
|
|
|
430
430
|
if (staleDecisions.length > 0) {
|
|
431
431
|
result._staleHint =
|
|
432
432
|
`${staleDecisions.length} decision(s) are stale (>${Math.floor(staleThresholdSec / 86400)} days). ` +
|
|
433
|
-
'Consider reviewing with
|
|
433
|
+
'Consider reviewing with autosnippet_task({ operation: "list_decisions" }) and unpin outdated ones.';
|
|
434
434
|
}
|
|
435
435
|
}
|
|
436
436
|
|
|
@@ -386,7 +386,8 @@ export class LanguageService {
|
|
|
386
386
|
* @returns {string}
|
|
387
387
|
*/
|
|
388
388
|
static toGuardLangId(langId) {
|
|
389
|
-
|
|
389
|
+
const id = (langId || '').toLowerCase().replace(/[_-]/g, '');
|
|
390
|
+
return id === 'objectivec' ? 'objc' : langId;
|
|
390
391
|
}
|
|
391
392
|
|
|
392
393
|
// ─── 显示名 ────────────────────────────────────
|
package/package.json
CHANGED
|
@@ -46,9 +46,7 @@ Use this skill when the user's intent is unclear or overlaps multiple capabiliti
|
|
|
46
46
|
- Guard: `autosnippet_guard` (code 单文件 / files[] 批量)
|
|
47
47
|
- Bootstrap: `autosnippet_bootstrap` (no params — Mission Briefing) + `autosnippet_dimension_complete`
|
|
48
48
|
- Wiki: `autosnippet_wiki_plan` (topic planning) + `autosnippet_wiki_finalize` (meta.json + dedup)
|
|
49
|
-
-
|
|
50
|
-
- Decide: `autosnippet_decide` (operation: record / revise / unpin / list)
|
|
51
|
-
- Task: `autosnippet_task` (operation: create / ready / claim / close / fail / defer / progress / stats / decompose)
|
|
49
|
+
- Task: `autosnippet_task` (operation: prime (session entry) / create / ready / claim / close / fail / defer / progress / stats / decompose / record_decision / revise_decision / unpin_decision / list_decisions)
|
|
52
50
|
- Skills: `autosnippet_skill` (operation: list / load / create / update / delete / suggest)
|
|
53
51
|
- Admin: `autosnippet_enrich_candidates`, `autosnippet_knowledge_lifecycle`, `autosnippet_validate_candidate`, `autosnippet_check_duplicate`
|
|
54
52
|
|
|
@@ -118,9 +118,7 @@ Recipe is the core knowledge unit. V3 uses a unified structured model:
|
|
|
118
118
|
|
|
119
119
|
| Tool | Description |
|
|
120
120
|
|------|-------------|
|
|
121
|
-
| `
|
|
122
|
-
| `autosnippet_decide` | Decision management (`operation`: record/revise/unpin/list) |
|
|
123
|
-
| `autosnippet_task` | Task CRUD (`operation`: create/ready/claim/close/fail/defer/progress/stats/decompose) |
|
|
121
|
+
| `autosnippet_task` | Unified task & decision management (`operation`: prime/create/claim/close/fail/defer/progress/decompose/record_decision/revise_decision/unpin_decision/list_decisions) |
|
|
124
122
|
|
|
125
123
|
### Skills Management
|
|
126
124
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "MANDATORY: Load AutoSnippet project context — decisions, tasks, knowledge"
|
|
3
|
+
allowed-tools: ["mcp__autosnippet__autosnippet_task"]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Call autosnippet_task with `{ "operation": "prime" }` to load the current project context.
|
|
7
|
+
|
|
8
|
+
**You MUST call this on EVERY user message BEFORE doing anything else.**
|
|
9
|
+
|
|
10
|
+
This returns:
|
|
11
|
+
- **Active decisions** — team agreements that must be followed
|
|
12
|
+
- **Ready tasks** — next items to work on
|
|
13
|
+
- **In-progress tasks** — unfinished work (ask user before resuming)
|
|
14
|
+
- **Task rules reminder** — behavioral rules for task management
|
|
15
|
+
- **Project statistics**
|
|
16
|
+
|
|
17
|
+
If there are unfinished tasks, present them to the user and ask: **Continue**, **Defer**, or **Abandon**? Do NOT auto-resume.
|
|
18
|
+
|
|
19
|
+
Call again after long conversations, compaction, or when `_contextHint` shows `CONTEXT_PRESSURE:CRITICAL`.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# AutoSnippet session hook for Claude Code
|
|
3
|
+
# SessionStart: full task rules + prime reminder
|
|
4
|
+
# PreCompact (--brief): minimal rules to survive compaction
|
|
5
|
+
|
|
6
|
+
if [[ "$1" == "--brief" ]]; then
|
|
7
|
+
# Brief mode — survives compaction, minimal context
|
|
8
|
+
cat <<'EOF'
|
|
9
|
+
📋 AutoSnippet Task Rules (MANDATORY):
|
|
10
|
+
• Prime EVERY message: autosnippet_task({ operation: "prime" }) FIRST.
|
|
11
|
+
• Create task for non-trivial work (≥2 files OR ≥10 lines). Claim → code → close.
|
|
12
|
+
• Handle in-progress tasks before new work. Close/defer ALL on session end.
|
|
13
|
+
• You are the task operator — user speaks naturally, you run task operations.
|
|
14
|
+
• User agrees/disagrees → record_decision immediately.
|
|
15
|
+
• "fix bug"/"implement" → create→claim→code→close | "pause" → defer | "abandon" → fail | "next" → ready()
|
|
16
|
+
EOF
|
|
17
|
+
else
|
|
18
|
+
# Full mode — SessionStart
|
|
19
|
+
cat <<'EOF'
|
|
20
|
+
[AutoSnippet Task Rules]
|
|
21
|
+
|
|
22
|
+
⚡ FIRST: Call autosnippet_task({ "operation": "prime" }) on EVERY message. No exceptions.
|
|
23
|
+
|
|
24
|
+
🔑 CRITICAL: YOU Operate autosnippet_task — The User Doesn't
|
|
25
|
+
• WRONG: "You can run autosnippet_task to create a task"
|
|
26
|
+
• RIGHT: (you run create yourself and tell the user "Created task asd-42")
|
|
27
|
+
|
|
28
|
+
📋 MUST:
|
|
29
|
+
• Create task for non-trivial work (≥2 files OR ≥10 lines) BEFORE starting
|
|
30
|
+
• Claim before coding, close when done with meaningful reason
|
|
31
|
+
• Handle unfinished tasks first (ask user: Continue/Defer/Abandon)
|
|
32
|
+
• Close or defer ALL in_progress tasks before session ends
|
|
33
|
+
|
|
34
|
+
🚫 NEVER:
|
|
35
|
+
• Skip prime
|
|
36
|
+
• Start new work with open in_progress tasks
|
|
37
|
+
• Tell user to run task commands (YOU are the operator)
|
|
38
|
+
• Leave tasks in in_progress when session ends
|
|
39
|
+
|
|
40
|
+
📖 User Says → You Run:
|
|
41
|
+
• "fix bug" / "implement" → create → claim → code → close
|
|
42
|
+
• "continue" → resume in-progress → code → close
|
|
43
|
+
• "pause" → defer(id, reason)
|
|
44
|
+
• "abandon" → fail(id, reason)
|
|
45
|
+
• "break down" → decompose(id, subtasks)
|
|
46
|
+
• "what's next" → ready() → present list
|
|
47
|
+
• "agreed" → record_decision(...)
|
|
48
|
+
• Quick question → No task. Just answer.
|
|
49
|
+
|
|
50
|
+
💡 When in doubt → create a task. When idle → autosnippet_task({ operation: "ready" })
|
|
51
|
+
|
|
52
|
+
📌 User agrees/disagrees with plan → autosnippet_task({ operation: "record_decision" }) immediately
|
|
53
|
+
|
|
54
|
+
✅ Session end checklist:
|
|
55
|
+
[ ] Close every claimed task with reason
|
|
56
|
+
[ ] Defer incomplete tasks with notes
|
|
57
|
+
[ ] Verify zero in_progress
|
|
58
|
+
[ ] Mention ready tasks for next session
|
|
59
|
+
|
|
60
|
+
🔎 Search knowledge: autosnippet_search({ query: "..." })
|
|
61
|
+
📚 Do NOT modify AutoSnippet/recipes/ or .autosnippet/ directly
|
|
62
|
+
EOF
|
|
63
|
+
fi
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(asd *)",
|
|
5
|
+
"Bash(curl -s * localhost:3000/*)",
|
|
6
|
+
"mcp__autosnippet__*"
|
|
7
|
+
]
|
|
8
|
+
},
|
|
9
|
+
"hooks": {
|
|
10
|
+
"SessionStart": [
|
|
11
|
+
{
|
|
12
|
+
"command": "bash .claude/hooks/autosnippet-session.sh"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"PreCompact": [
|
|
16
|
+
{
|
|
17
|
+
"command": "bash .claude/hooks/autosnippet-session.sh --brief"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
}
|