autosnippet 3.1.15 → 3.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 (41) hide show
  1. package/README.md +1 -0
  2. package/bin/cli.js +242 -23
  3. package/dashboard/dist/assets/{icons-CC5R_iwL.js → icons-18VxiaCT.js} +108 -98
  4. package/dashboard/dist/assets/index-BJiuaVPD.css +1 -0
  5. package/dashboard/dist/assets/{index-WmnJCXq4.js → index-CRH5Umim.js} +50 -50
  6. package/dashboard/dist/index.html +3 -3
  7. package/lib/cli/SetupService.js +152 -21
  8. package/lib/domain/task/Task.js +214 -0
  9. package/lib/domain/task/TaskDependency.js +48 -0
  10. package/lib/domain/task/TaskIdGenerator.js +83 -0
  11. package/lib/domain/task/index.js +6 -0
  12. package/lib/external/mcp/McpServer.js +4 -4
  13. package/lib/external/mcp/handlers/task.js +295 -0
  14. package/lib/external/mcp/tools.js +100 -3
  15. package/lib/http/HttpServer.js +8 -0
  16. package/lib/http/routes/guard.js +283 -0
  17. package/lib/http/routes/task.js +282 -0
  18. package/lib/infrastructure/config/Paths.js +18 -8
  19. package/lib/infrastructure/database/migrations/002_add_tasks.js +88 -0
  20. package/lib/injection/ServiceContainer.js +58 -0
  21. package/lib/repository/task/TaskRepository.impl.js +398 -0
  22. package/lib/service/cursor/AgentInstructionsGenerator.js +28 -9
  23. package/lib/service/cursor/CursorDeliveryPipeline.js +42 -20
  24. package/lib/service/cursor/KnowledgeCompressor.js +40 -0
  25. package/lib/service/cursor/TokenBudget.js +2 -2
  26. package/lib/service/guard/GuardFeedbackLoop.js +17 -2
  27. package/lib/service/knowledge/KnowledgeService.js +6 -0
  28. package/lib/service/task/TaskGraphService.js +410 -0
  29. package/lib/service/task/TaskKnowledgeBridge.js +86 -0
  30. package/lib/service/task/TaskReadyEngine.js +127 -0
  31. package/lib/shared/constants.js +3 -3
  32. package/package.json +1 -1
  33. package/skills/autosnippet-intent/SKILL.md +4 -1
  34. package/skills/autosnippet-recipes/SKILL.md +17 -2
  35. package/templates/claude-hooks.yaml +19 -0
  36. package/templates/copilot-instructions.md +33 -1
  37. package/templates/cursor-rules/autosnippet-conventions.mdc +12 -0
  38. package/templates/cursor-rules/autosnippet-workflow.mdc +43 -0
  39. package/templates/guard-ci.yml +1 -0
  40. package/templates/pre-commit-guard.sh +2 -1
  41. package/dashboard/dist/assets/index-6iola4rb.css +0 -1
@@ -0,0 +1,86 @@
1
+ import Logger from '../../infrastructure/logging/Logger.js';
2
+
3
+ /**
4
+ * TaskKnowledgeBridge — 任务 ↔ 知识桥接服务
5
+ *
6
+ * AutoSnippet 独有能力:返回「带知识上下文的任务」,而非裸任务。
7
+ *
8
+ * 桥接策略:
9
+ * 1. 任务标题/描述 → 搜索知识库 → 关联 pattern/rule/fact
10
+ * 2. 关联的 Guard 规则 → 嵌入任务上下文
11
+ */
12
+ export class TaskKnowledgeBridge {
13
+ /**
14
+ * @param {import('../../service/search/SearchEngine.js').SearchEngine} searchEngine
15
+ */
16
+ constructor(searchEngine) {
17
+ this._search = searchEngine;
18
+ this.logger = Logger.getInstance();
19
+ }
20
+
21
+ /**
22
+ * 为就绪任务附加知识上下文
23
+ * 并行搜索,不阻塞主流程
24
+ *
25
+ * @param {import('../../domain/task/Task.js').Task[]} tasks
26
+ * @returns {Promise<import('../../domain/task/Task.js').Task[]>}
27
+ */
28
+ async enrichWithKnowledge(tasks) {
29
+ if (!tasks || tasks.length === 0) return tasks;
30
+ if (!this._search) return tasks;
31
+
32
+ const results = await Promise.allSettled(tasks.map((task) => this._buildContext(task)));
33
+
34
+ return tasks.map((task, i) => {
35
+ if (results[i].status === 'fulfilled' && results[i].value) {
36
+ task.knowledgeContext = results[i].value;
37
+ }
38
+ return task;
39
+ });
40
+ }
41
+
42
+ /**
43
+ * 为单个任务构建知识上下文
44
+ * @private
45
+ */
46
+ async _buildContext(task) {
47
+ const query = `${task.title} ${task.description}`.trim();
48
+ if (!query) return null;
49
+
50
+ try {
51
+ const searchResult = await this._search.search(query, {
52
+ mode: 'auto',
53
+ limit: 5,
54
+ });
55
+
56
+ const allResults = searchResult?.items || searchResult?.results || [];
57
+ const knowledge = allResults.filter((r) => r.kind !== 'rule').slice(0, 3);
58
+ const guardRules = allResults.filter((r) => r.kind === 'rule').slice(0, 5);
59
+
60
+ return {
61
+ relatedKnowledge: knowledge.map((k) => ({
62
+ id: k.id,
63
+ title: k.title,
64
+ kind: k.kind,
65
+ trigger: k.trigger,
66
+ actionHint: k.actionHint || k.doClause || '',
67
+ })),
68
+ guardRules: guardRules.map((r) => ({
69
+ id: r.id,
70
+ title: r.title,
71
+ trigger: r.trigger,
72
+ actionHint: r.actionHint || r.doClause || '',
73
+ })),
74
+ searchQuery: query,
75
+ };
76
+ } catch (err) {
77
+ this.logger.debug('TaskKnowledgeBridge._buildContext error', {
78
+ taskId: task.id,
79
+ error: err.message,
80
+ });
81
+ return null;
82
+ }
83
+ }
84
+ }
85
+
86
+ export default TaskKnowledgeBridge;
@@ -0,0 +1,127 @@
1
+ import { Task } from '../../domain/task/Task.js';
2
+
3
+ /**
4
+ * TaskReadyEngine — 就绪检测引擎
5
+ *
6
+ * 核心能力:通过递归 CTE 计算传递性阻塞,返回所有无阻塞依赖的就绪任务。
7
+ *
8
+ * 排序策略 (默认 hybrid):
9
+ * priority ASC → 高优先级优先
10
+ * created_at ASC → 同优先级先创建优先(防止 starvation)
11
+ */
12
+ export class TaskReadyEngine {
13
+ /**
14
+ * @param {import('better-sqlite3').Database} db — raw SQLite handle
15
+ */
16
+ constructor(db) {
17
+ this._db = db;
18
+ this._prepareStatements();
19
+ }
20
+
21
+ /** @private */
22
+ _prepareStatements() {
23
+ // ── 核心: 递归 CTE 计算传递性阻塞 ──
24
+ this._readyStmt = this._db.prepare(`
25
+ WITH RECURSIVE blocked_tasks(id, depth) AS (
26
+ -- Base case: 直接被阻塞的任务
27
+ SELECT td.task_id, 1
28
+ FROM task_dependencies td
29
+ JOIN tasks blocker ON td.depends_on_id = blocker.id
30
+ WHERE td.dep_type IN ('blocks', 'waits-for')
31
+ AND blocker.status != 'closed'
32
+
33
+ UNION
34
+
35
+ -- Recursive case: 传递性阻塞(深度保护 ≤ 50 层)
36
+ SELECT td.task_id, bt.depth + 1
37
+ FROM task_dependencies td
38
+ JOIN blocked_tasks bt ON td.depends_on_id = bt.id
39
+ WHERE td.dep_type IN ('blocks', 'waits-for')
40
+ AND bt.depth < 50
41
+ )
42
+ SELECT t.*
43
+ FROM tasks t
44
+ WHERE t.status = 'open'
45
+ AND t.id NOT IN (SELECT id FROM blocked_tasks)
46
+ ORDER BY t.priority ASC, t.created_at ASC
47
+ LIMIT ?
48
+ `);
49
+
50
+ // ── 查询被阻塞的任务 ──
51
+ this._blockedStmt = this._db.prepare(`
52
+ SELECT t.*, GROUP_CONCAT(td.depends_on_id) as blocked_by
53
+ FROM tasks t
54
+ JOIN task_dependencies td ON t.id = td.task_id
55
+ JOIN tasks blocker ON td.depends_on_id = blocker.id
56
+ WHERE t.status IN ('open', 'in_progress')
57
+ AND td.dep_type IN ('blocks', 'waits-for')
58
+ AND blocker.status != 'closed'
59
+ GROUP BY t.id
60
+ ORDER BY t.priority ASC
61
+ `);
62
+
63
+ // ── 依赖树查询 ──
64
+ this._depTreeStmt = this._db.prepare(`
65
+ WITH RECURSIVE dep_tree(id, depth, path) AS (
66
+ SELECT depends_on_id, 1, depends_on_id
67
+ FROM task_dependencies
68
+ WHERE task_id = ?
69
+ AND dep_type IN ('blocks', 'waits-for')
70
+
71
+ UNION ALL
72
+
73
+ SELECT td.depends_on_id, dt.depth + 1, dt.path || '>' || td.depends_on_id
74
+ FROM task_dependencies td
75
+ JOIN dep_tree dt ON td.task_id = dt.id
76
+ WHERE td.dep_type IN ('blocks', 'waits-for')
77
+ AND dt.depth < 10
78
+ )
79
+ SELECT t.*, dt.depth
80
+ FROM dep_tree dt
81
+ JOIN tasks t ON t.id = dt.id
82
+ ORDER BY dt.depth ASC
83
+ `);
84
+ }
85
+
86
+ /**
87
+ * 获取就绪任务(核心方法)
88
+ *
89
+ * 就绪 = status='open' 且无未完成的阻塞型依赖(传递性检测)
90
+ *
91
+ * @param {object} [options]
92
+ * @param {number} [options.limit=10]
93
+ * @returns {Task[]}
94
+ */
95
+ getReadyWork(options = {}) {
96
+ const limit = Math.max(1, Math.min(options.limit || 10, 200));
97
+ const rows = this._readyStmt.all(limit);
98
+ return rows.map((r) => Task.fromRow(r));
99
+ }
100
+
101
+ /**
102
+ * 获取被阻塞的任务列表
103
+ * @returns {Array<Object>} 带 blocked_by 字段的任务列表
104
+ */
105
+ getBlockedWork() {
106
+ const rows = this._blockedStmt.all();
107
+ return rows.map((r) => ({
108
+ ...Task.fromRow(r).toJSON(),
109
+ blockedBy: r.blocked_by ? r.blocked_by.split(',') : [],
110
+ }));
111
+ }
112
+
113
+ /**
114
+ * 获取依赖树
115
+ * @param {string} taskId
116
+ * @returns {Array<Object>} 带 depth 的任务列表
117
+ */
118
+ getDependencyTree(taskId) {
119
+ const rows = this._depTreeStmt.all(taskId);
120
+ return rows.map((r) => ({
121
+ ...Task.fromRow(r).toJSON(),
122
+ depth: r.depth,
123
+ }));
124
+ }
125
+ }
126
+
127
+ export default TaskReadyEngine;
@@ -10,11 +10,11 @@
10
10
 
11
11
  /** QualityScorer 维度权重 */
12
12
  export const QUALITY_WEIGHTS = Object.freeze({
13
- completeness: 0.35,
13
+ completeness: 0.30,
14
14
  format: 0.25,
15
15
  codeQuality: 0.25,
16
- metadata: 0.15,
17
- engagement: 0.0,
16
+ metadata: 0.10,
17
+ engagement: 0.10,
18
18
  });
19
19
 
20
20
  /** QualityScorer 等级分界线 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autosnippet",
3
- "version": "3.1.15",
3
+ "version": "3.2.2",
4
4
  "description": "Extract code patterns into a knowledge base for AI coding assistants",
5
5
  "type": "module",
6
6
  "main": "lib/bootstrap.js",
@@ -34,7 +34,7 @@ Use this skill when the user's intent is unclear or overlaps multiple capabiliti
34
34
  - `autosnippet-batch-scan` / `autosnippet-recipe-candidates` → merged into autosnippet-candidates
35
35
  - `autosnippet-dep-graph` → merged into autosnippet-structure
36
36
 
37
- ## MCP tools (reference only — 12 个整合工具)
37
+ ## MCP tools (reference only — 20 个整合工具)
38
38
 
39
39
  - System: `autosnippet_health`, `autosnippet_capabilities`
40
40
  - Search: `autosnippet_search` (mode: auto / context / keyword / semantic)
@@ -45,7 +45,10 @@ Use this skill when the user's intent is unclear or overlaps multiple capabiliti
45
45
  - Document: `autosnippet_save_document`
46
46
  - Guard: `autosnippet_guard` (code 单文件 / files[] 批量)
47
47
  - Bootstrap: `autosnippet_bootstrap` (no params — Mission Briefing) + `autosnippet_dimension_complete`
48
+ - Wiki: `autosnippet_wiki_plan` (topic planning) + `autosnippet_wiki_finalize` (meta.json + dedup)
49
+ - Task: `autosnippet_task` (operation: create / ready / claim / close / fail / defer / progress / prime / stats / decompose)
48
50
  - Skills: `autosnippet_skill` (operation: list / load / create / update / delete / suggest)
51
+ - Admin: `autosnippet_enrich_candidates`, `autosnippet_knowledge_lifecycle`, `autosnippet_validate_candidate`, `autosnippet_check_duplicate`
49
52
 
50
53
  This skill is a router only; it does not perform actions itself.
51
54
 
@@ -78,7 +78,7 @@ Recipe is the core knowledge unit. V3 uses a unified structured model:
78
78
 
79
79
  ---
80
80
 
81
- ## MCP Tools Reference (12 个整合工具)
81
+ ## MCP Tools Reference (20 个整合工具)
82
82
 
83
83
  ### Query (Agent can freely use)
84
84
 
@@ -89,6 +89,7 @@ Recipe is the core knowledge unit. V3 uses a unified structured model:
89
89
  | `autosnippet_knowledge` | Knowledge browse (`operation`: list/get/insights/confirm_usage) |
90
90
  | `autosnippet_graph` | Knowledge graph (`operation`: query/impact/path/stats) |
91
91
  | `autosnippet_structure` | Project structure (`operation`: targets/files/metadata) |
92
+ | `autosnippet_capabilities` | Service capability discovery |
92
93
 
93
94
  ### Candidate Submit (Agent core capability)
94
95
 
@@ -103,7 +104,21 @@ Recipe is the core knowledge unit. V3 uses a unified structured model:
103
104
  | Tool | Description |
104
105
  |------|-------------|
105
106
  | `autosnippet_guard` | Code Guard check (`code` single / `files[]` batch — auto-routed) |
106
- | `autosnippet_bootstrap` | Cold-start + scan (`operation`: knowledge/refine/scan) |
107
+ | `autosnippet_bootstrap` | Cold-start Mission Briefing (no params — returns project analysis + dimension tasks) |
108
+ | `autosnippet_dimension_complete` | Dimension analysis completion (dimensionId + analysisText required) |
109
+
110
+ ### Wiki
111
+
112
+ | Tool | Description |
113
+ |------|-------------|
114
+ | `autosnippet_wiki_plan` | Plan Wiki doc generation (scan project → topic data packages) |
115
+ | `autosnippet_wiki_finalize` | Finalize Wiki (meta.json + dedup + validation) |
116
+
117
+ ### Task Management
118
+
119
+ | Tool | Description |
120
+ |------|-------------|
121
+ | `autosnippet_task` | TaskGraph lifecycle (`operation`: create/ready/claim/close/fail/defer/progress/prime/stats/decompose) |
107
122
 
108
123
  ### Skills Management
109
124
 
@@ -0,0 +1,19 @@
1
+ # AutoSnippet Claude Code Hooks
2
+ # Auto-generated by AutoSnippet. Do not edit manually.
3
+ #
4
+ # 用法:将此文件放到项目 .claude/ 目录下
5
+ # Claude Code 在会话开始时会自动执行 SessionStart hook
6
+ #
7
+ # SessionStart hook 自动调用 prime,恢复任务上下文
8
+ # 无需手动调用 autosnippet_task(operation: "prime")
9
+
10
+ hooks:
11
+ SessionStart:
12
+ # 会话开始时自动 prime TaskGraph 上下文
13
+ - command: |
14
+ curl -s -X POST http://localhost:3000/api/v1/task \
15
+ -H "Content-Type: application/json" \
16
+ -d '{"operation": "prime"}' \
17
+ 2>/dev/null || echo '{"success": false, "message": "AutoSnippet server not running"}'
18
+ description: "AutoSnippet TaskGraph auto-prime"
19
+ timeout: 5000
@@ -1,5 +1,7 @@
1
1
  # AutoSnippet Copilot Instructions
2
2
 
3
+ > Auto-generated by AutoSnippet. Do not edit manually — regenerated on `asd setup` / `asd bootstrap`.
4
+
3
5
  ## 项目概览
4
6
  - 项目名称:AutoSnippet
5
7
  - 版本:V3(ESM, SQLite, MCP 11 工具 — 整合版)
@@ -29,7 +31,7 @@
29
31
  5. MCP 调用失败时,**不要在同一轮重复重试**,回退到已读文档或静态上下文。
30
32
  6. Skills 负责语义与流程,MCP 负责能力与调用;不要在 Skill 内硬编码 URL/HTTP。
31
33
 
32
- ## MCP 工具速查(12 个整合工具)
34
+ ## MCP 工具速查(20 个整合工具)
33
35
 
34
36
  ### 检索
35
37
  - `autosnippet_search` — 统合搜索入口(通过 `mode` 参数切换)
@@ -68,10 +70,23 @@
68
70
  - `autosnippet_bootstrap` — 冷启动 Mission Briefing(无参数,返回项目分析 + 维度任务清单)
69
71
  - `autosnippet_dimension_complete` — 维度分析完成通知(dimensionId + analysisText 必填)
70
72
 
73
+ ### Wiki 文档
74
+ - `autosnippet_wiki_plan` — Wiki 文档规划(扫描项目生成主题数据包)
75
+ - `autosnippet_wiki_finalize` — Wiki 完成(meta.json + 去重 + 验证)
76
+
77
+ ### 任务管理
78
+ - `autosnippet_task` — TaskGraph 任务图管理(`operation`: create / ready / claim / close / fail / defer / progress / prime / stats / decompose / dep_add / dep_tree 等)
79
+
71
80
  ### 系统
72
81
  - `autosnippet_health` — 服务健康状态与知识库统计(可检测空 KB 触发冷启动)
73
82
  - `autosnippet_capabilities` — 服务能力清单(列出所有可用 MCP 工具,供 Agent 自发现)
74
83
 
84
+ ### 管理员工具(Admin Tier)
85
+ - `autosnippet_enrich_candidates` — 候选字段完整性诊断(不使用 AI)
86
+ - `autosnippet_knowledge_lifecycle` — 知识条目生命周期操作(publish/deprecate/reactivate 等)
87
+ - `autosnippet_validate_candidate` — 候选结构化预校验(调试用)
88
+ - `autosnippet_check_duplicate` — 相似度检测(调试用)
89
+
75
90
  ## Recipe 结构要点
76
91
  - 必须包含:Frontmatter(`title`、`trigger` 必填)+ `## Snippet / Code Reference` + `## AI Context / Usage Guide`。
77
92
  - Frontmatter 必填字段(7):`title`、`trigger`(@开头)、`category`(8 选 1)、`language`、`summary_cn`、`summary_en`、`headers`。
@@ -94,6 +109,23 @@ autosnippet_skill({ operation: "load", name: "autosnippet-coldstart" })
94
109
  Skill 包含:完整的 V3 字段格式、JSON 示例模板、维度分析策略。
95
110
  **不加载 Skill 直接提交知识会因字段格式问题被反复拒绝。**
96
111
 
112
+ ## Guard 诊断响应
113
+
114
+ 当编辑器出现来自 "AutoSnippet Guard" 的诊断(黄色/红色波浪线)时:
115
+ 1. 读取诊断消息中的 `ruleId`
116
+ 2. 调用 `autosnippet_search(query: ruleId)` 查找对应 Recipe
117
+ 3. 按 Recipe 的 `doClause` + `coreCode` 修复代码
118
+ 4. 保存文件并确认诊断消失
119
+
120
+ 灯泡菜单中可快捷搜索知识库或禁用该行检查。
121
+
122
+ ## 上下文压力应对
123
+
124
+ - 如果任何工具返回 `_contextHint` 包含 `CONTEXT_PRESSURE:WARNING`:
125
+ → 简要总结已完成工作,然后继续。
126
+ - 如果任何工具返回 `_contextHint` 包含 `CONTEXT_PRESSURE:CRITICAL`:
127
+ → 立即调用 `autosnippet_task(operation: "prime")` 恢复会话上下文。
128
+
97
129
  ### V3 字段格式关键提醒
98
130
  - `content` **必须是 JSON 对象**(不是字符串):`{ "pattern": "代码...", "markdown": "## 标题\n正文...", "rationale": "设计原理" }`
99
131
  - `reasoning` **必须是 JSON 对象**:`{ "whyStandard": "原因", "sources": ["file.ts"], "confidence": 0.85 }`
@@ -98,3 +98,15 @@ Recipes are classified into three kinds:
98
98
  ## Recipe over code
99
99
 
100
100
  When both a Recipe and the codebase have relevant implementations, prefer the Recipe. Recipes are the project's agreed standard; source code may be legacy or non-standard.
101
+
102
+ ## Guard 诊断响应
103
+
104
+ 当编辑器出现 "AutoSnippet Guard" 诊断时:
105
+ 1. 读取 ruleId → `autosnippet_search(query: ruleId)`
106
+ 2. 按 Recipe 的 doClause + coreCode 修改代码
107
+ 3. 保存并确认诊断消失
108
+
109
+ ## 上下文压力应对
110
+
111
+ - `_contextHint` 包含 `CONTEXT_PRESSURE:WARNING` → 总结已完成工作,继续。
112
+ - `_contextHint` 包含 `CONTEXT_PRESSURE:CRITICAL` → 立即 prime 恢复上下文。
@@ -0,0 +1,43 @@
1
+ ---
2
+ description: AutoSnippet TaskGraph & Guard 工作流 — 任务管理 + 诊断闭环
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # AutoSnippet TaskGraph Workflow
7
+
8
+ ## 任务管理
9
+
10
+ 1. 新会话开始 → `autosnippet_task(operation: "prime")`
11
+ 2. 编码前 → `claim`,完成后 → `close`
12
+ 3. 遇到错误 → `fail`(不要跳过)
13
+ 4. 发现新工作 → `create` + `dep_add(depType: "discovered-from")`
14
+ 5. MCP 调用失败 → 不要在同一轮重复重试
15
+
16
+ ## Guard 诊断响应
17
+
18
+ 当编辑器出现 "AutoSnippet Guard" 诊断时:
19
+ 1. 读取 ruleId → `autosnippet_search(query: ruleId)`
20
+ 2. 按 Recipe 的 doClause + coreCode 修改代码
21
+ 3. 保存并确认诊断消失
22
+
23
+ ## 知识搜索
24
+
25
+ 编码前搜索相关知识:`autosnippet_search(query: "相关关键词")`
26
+
27
+ ## 上下文压力
28
+
29
+ - `_contextHint` 包含 `CONTEXT_PRESSURE:WARNING` → 总结已完成工作,继续
30
+ - `_contextHint` 包含 `CONTEXT_PRESSURE:CRITICAL` → 立即 prime 恢复上下文
31
+
32
+ ## 任务操作速查
33
+
34
+ | 操作 | 用途 |
35
+ |------|------|
36
+ | `prime` | 恢复会话上下文(新会话必做) |
37
+ | `claim(id)` | 开始处理任务 |
38
+ | `close(id)` | 完成任务 → 返回 newlyReady |
39
+ | `fail(id, reason)` | 标记失败 |
40
+ | `defer(id, reason)` | 延后处理 |
41
+ | `progress(id, desc)` | 更新进度 |
42
+ | `create(title)` | 创建新任务 |
43
+ | `ready` | 获取就绪任务(带知识上下文) |
@@ -1,4 +1,5 @@
1
1
  # AutoSnippet Guard CI/CD Check
2
+ # Auto-generated by AutoSnippet. Do not edit manually.
2
3
  # 在 push 和 PR 时自动运行 Guard 合规检查
3
4
  #
4
5
  # 使用方法:将此文件复制到项目的 .github/workflows/ 目录
@@ -1,6 +1,7 @@
1
1
  #!/bin/sh
2
2
  # AutoSnippet Guard pre-commit hook
3
- #
3
+ # Auto-generated by AutoSnippet. Do not edit manually.
4
+ #
4
5
  # 安装方法:
5
6
  # cp templates/pre-commit-guard.sh .git/hooks/pre-commit
6
7
  # chmod +x .git/hooks/pre-commit