@fitlab-ai/agent-infra 0.5.7 → 0.5.8
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 +1 -1
- package/README.zh-CN.md +1 -1
- package/lib/defaults.json +4 -2
- package/lib/init.js +18 -1
- package/lib/sandbox/engine.js +19 -0
- package/lib/sandbox/shell.js +36 -2
- package/lib/update.js +14 -3
- package/package.json +4 -4
- package/templates/.agents/QUICKSTART.en.md +2 -2
- package/templates/.agents/QUICKSTART.zh-CN.md +2 -2
- package/templates/.agents/README.en.md +1 -1
- package/templates/.agents/README.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.github.en.md +60 -0
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +60 -0
- package/templates/.agents/rules/issue-sync.en.md +14 -0
- package/templates/.agents/rules/issue-sync.github.en.md +14 -0
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +14 -0
- package/templates/.agents/rules/issue-sync.zh-CN.md +14 -0
- package/templates/.agents/rules/label-milestone-setup.github.en.md +10 -0
- package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +10 -0
- package/templates/.agents/rules/release-commands.github.en.md +16 -0
- package/templates/.agents/rules/release-commands.github.zh-CN.md +16 -0
- package/templates/.agents/scripts/platform-adapters/find-existing-task.github.js +272 -0
- package/templates/.agents/scripts/platform-adapters/find-existing-task.js +5 -0
- package/templates/.agents/scripts/platform-adapters/platform-sync.github.js +88 -8
- package/templates/.agents/scripts/platform-adapters/platform-sync.js +7 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/analyze-task/config/verify.json +3 -1
- package/templates/.agents/skills/block-task/config/verify.json +2 -1
- package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/cancel-task/config/verify.json +2 -1
- package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/commit/SKILL.en.md +1 -1
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/config/verify.json +2 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-task/config/verify.json +2 -1
- package/templates/.agents/skills/create-issue/SKILL.en.md +8 -8
- package/templates/.agents/skills/create-issue/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/create-issue/config/verify.json +2 -1
- package/templates/.agents/skills/create-issue/reference/label-and-type.en.md +3 -3
- package/templates/.agents/skills/create-issue/reference/label-and-type.zh-CN.md +3 -3
- package/templates/.agents/skills/create-issue/reference/template-matching.en.md +6 -34
- package/templates/.agents/skills/create-issue/reference/template-matching.zh-CN.md +8 -36
- package/templates/.agents/skills/create-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/create-pr/config/verify.json +2 -1
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +7 -17
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +27 -37
- package/templates/.agents/skills/create-release-note/SKILL.en.md +9 -9
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +9 -9
- package/templates/.agents/skills/create-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/implement-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/implement-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/implement-task/config/verify.json +3 -1
- package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.en.md +39 -9
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +39 -9
- package/templates/.agents/skills/init-labels/SKILL.en.md +9 -9
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -9
- package/templates/.agents/skills/init-milestones/SKILL.en.md +7 -7
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +7 -7
- package/templates/.agents/skills/plan-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/plan-task/config/verify.json +3 -1
- package/templates/.agents/skills/refine-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/refine-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/refine-task/config/verify.json +3 -1
- package/templates/.agents/skills/restore-task/SKILL.en.md +13 -64
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +13 -64
- package/templates/.agents/skills/review-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/review-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/review-task/config/verify.json +3 -1
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +2 -0
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +2 -0
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +56 -5
- package/templates/.claude/commands/create-issue.en.md +1 -1
- package/templates/.claude/commands/create-issue.zh-CN.md +1 -1
- package/templates/.claude/commands/import-issue.en.md +1 -1
- package/templates/.claude/commands/import-issue.zh-CN.md +1 -1
- package/templates/.claude/commands/init-labels.en.md +1 -1
- package/templates/.claude/commands/init-labels.zh-CN.md +1 -1
- package/templates/.claude/commands/init-milestones.en.md +1 -1
- package/templates/.claude/commands/init-milestones.zh-CN.md +1 -1
- package/templates/.claude/commands/restore-task.en.md +1 -1
- package/templates/.claude/commands/restore-task.zh-CN.md +1 -1
- package/templates/.claude/hooks/check-version-format.sh +1 -1
- package/templates/.gemini/commands/_project_/create-issue.en.toml +1 -1
- package/templates/.gemini/commands/_project_/create-issue.zh-CN.toml +1 -1
- package/templates/.gemini/commands/_project_/import-issue.en.toml +1 -1
- package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +1 -1
- package/templates/.gemini/commands/_project_/init-labels.en.toml +2 -2
- package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +2 -2
- package/templates/.gemini/commands/_project_/init-milestones.en.toml +2 -2
- package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +2 -2
- package/templates/.gemini/commands/_project_/restore-task.en.toml +1 -1
- package/templates/.gemini/commands/_project_/restore-task.zh-CN.toml +1 -1
- package/templates/{.github/hooks → .git-hooks}/check-version-format.sh +2 -2
- package/templates/.github/workflows/pr-label.yml +1 -1
- package/templates/.opencode/commands/create-issue.en.md +1 -1
- package/templates/.opencode/commands/create-issue.zh-CN.md +1 -1
- package/templates/.opencode/commands/import-issue.en.md +1 -1
- package/templates/.opencode/commands/import-issue.zh-CN.md +1 -1
- package/templates/.opencode/commands/init-labels.en.md +1 -1
- package/templates/.opencode/commands/init-labels.zh-CN.md +1 -1
- package/templates/.opencode/commands/init-milestones.en.md +1 -1
- package/templates/.opencode/commands/init-milestones.zh-CN.md +1 -1
- package/templates/.opencode/commands/restore-task.en.md +1 -1
- package/templates/.opencode/commands/restore-task.zh-CN.md +1 -1
- /package/templates/{.github/hooks → .git-hooks}/pre-commit +0 -0
package/README.md
CHANGED
|
@@ -545,7 +545,7 @@ The generated `.agents/.airc.json` file is the central contract between the boot
|
|
|
545
545
|
"project": "my-project",
|
|
546
546
|
"org": "my-org",
|
|
547
547
|
"language": "en",
|
|
548
|
-
"templateVersion": "v0.5.
|
|
548
|
+
"templateVersion": "v0.5.8",
|
|
549
549
|
"templates": {
|
|
550
550
|
"sources": [
|
|
551
551
|
{ "type": "local", "path": "~/private-templates" }
|
package/README.zh-CN.md
CHANGED
|
@@ -545,7 +545,7 @@ import-issue #42 从 GitHub Issue 导入任务
|
|
|
545
545
|
"project": "my-project",
|
|
546
546
|
"org": "my-org",
|
|
547
547
|
"language": "en",
|
|
548
|
-
"templateVersion": "v0.5.
|
|
548
|
+
"templateVersion": "v0.5.8",
|
|
549
549
|
"templates": {
|
|
550
550
|
"sources": [
|
|
551
551
|
{ "type": "local", "path": "~/private-templates" }
|
package/lib/defaults.json
CHANGED
|
@@ -36,22 +36,24 @@
|
|
|
36
36
|
".claude/commands/",
|
|
37
37
|
".claude/hooks/",
|
|
38
38
|
".gemini/commands/",
|
|
39
|
-
".
|
|
39
|
+
".git-hooks/check-version-format.sh",
|
|
40
40
|
".github/scripts/",
|
|
41
41
|
".opencode/commands/"
|
|
42
42
|
],
|
|
43
43
|
"merged": [
|
|
44
|
+
"**/post-release.*",
|
|
44
45
|
"**/release.*",
|
|
45
46
|
"**/test-integration.*",
|
|
46
47
|
"**/test.*",
|
|
47
48
|
"**/upgrade-dependency.*",
|
|
49
|
+
".agents/skills/post-release/SKILL.*",
|
|
48
50
|
".agents/skills/release/SKILL.*",
|
|
49
51
|
".agents/skills/test-integration/SKILL.*",
|
|
50
52
|
".agents/skills/test/SKILL.*",
|
|
51
53
|
".agents/skills/upgrade-dependency/SKILL.*",
|
|
52
54
|
".claude/settings.json",
|
|
53
55
|
".gemini/settings.json",
|
|
54
|
-
".
|
|
56
|
+
".git-hooks/pre-commit",
|
|
55
57
|
".gitignore"
|
|
56
58
|
],
|
|
57
59
|
"ejected": []
|
package/lib/init.js
CHANGED
|
@@ -12,6 +12,23 @@ const defaults = JSON.parse(
|
|
|
12
12
|
fs.readFileSync(new URL('./defaults.json', import.meta.url), 'utf8')
|
|
13
13
|
);
|
|
14
14
|
|
|
15
|
+
function isPathOwnedByOtherPlatform(relativePath, platformType) {
|
|
16
|
+
const top = String(relativePath || '').replace(/\\/g, '/').replace(/^\.\//, '').split('/')[0];
|
|
17
|
+
if (!top.startsWith('.')) return false;
|
|
18
|
+
|
|
19
|
+
const candidate = top.slice(1);
|
|
20
|
+
if (!KNOWN_PLATFORMS.has(candidate)) return false;
|
|
21
|
+
return candidate !== platformType;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function buildDefaultFiles(platformType) {
|
|
25
|
+
return {
|
|
26
|
+
managed: (defaults.files.managed || []).filter((entry) => !isPathOwnedByOtherPlatform(entry, platformType)),
|
|
27
|
+
merged: (defaults.files.merged || []).filter((entry) => !isPathOwnedByOtherPlatform(entry, platformType)),
|
|
28
|
+
ejected: structuredClone(defaults.files.ejected || [])
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
15
32
|
function detectProjectName() {
|
|
16
33
|
try {
|
|
17
34
|
const url = execSync('git remote get-url origin', { stdio: ['pipe', 'pipe', 'pipe'] })
|
|
@@ -222,7 +239,7 @@ async function cmdInit() {
|
|
|
222
239
|
templateVersion: VERSION,
|
|
223
240
|
sandbox: structuredClone(defaults.sandbox),
|
|
224
241
|
labels: structuredClone(defaults.labels),
|
|
225
|
-
files:
|
|
242
|
+
files: buildDefaultFiles(platformType)
|
|
226
243
|
};
|
|
227
244
|
|
|
228
245
|
if (sandboxEngine) {
|
package/lib/sandbox/engine.js
CHANGED
|
@@ -8,8 +8,21 @@ export const ENGINES = Object.freeze({
|
|
|
8
8
|
DOCKER_DESKTOP: 'docker-desktop'
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
+
export const ENGINE_DOCKER_CONTEXT = Object.freeze({
|
|
12
|
+
[ENGINES.COLIMA]: 'colima',
|
|
13
|
+
[ENGINES.ORBSTACK]: 'orbstack',
|
|
14
|
+
[ENGINES.DOCKER_DESKTOP]: 'desktop-linux'
|
|
15
|
+
});
|
|
16
|
+
|
|
11
17
|
const VALID_CONFIG_ENGINES = new Set(Object.values(ENGINES));
|
|
12
18
|
|
|
19
|
+
function applyDockerContext(engine) {
|
|
20
|
+
const context = ENGINE_DOCKER_CONTEXT[engine];
|
|
21
|
+
if (context) {
|
|
22
|
+
process.env.DOCKER_CONTEXT = context;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
export function validateSandboxEngine(engine) {
|
|
14
27
|
if (engine === null || engine === undefined) {
|
|
15
28
|
return null;
|
|
@@ -68,6 +81,8 @@ export async function ensureColima(
|
|
|
68
81
|
onMessage,
|
|
69
82
|
{ runOkFn = runOk, runSafeFn = runSafe, runVerboseFn = runVerbose } = {}
|
|
70
83
|
) {
|
|
84
|
+
applyDockerContext(ENGINES.COLIMA);
|
|
85
|
+
|
|
71
86
|
if (!runOkFn('which', ['colima'])) {
|
|
72
87
|
onMessage?.('Installing colima + docker via Homebrew...');
|
|
73
88
|
runVerboseFn('brew', ['install', 'colima', 'docker']);
|
|
@@ -88,6 +103,8 @@ export async function ensureOrbStack(
|
|
|
88
103
|
onMessage,
|
|
89
104
|
{ runOkFn = runOk, runVerboseFn = runVerbose } = {}
|
|
90
105
|
) {
|
|
106
|
+
applyDockerContext(ENGINES.ORBSTACK);
|
|
107
|
+
|
|
91
108
|
if (!runOkFn('which', ['orb'])) {
|
|
92
109
|
onMessage?.('Installing OrbStack via Homebrew...');
|
|
93
110
|
runVerboseFn('brew', ['install', '--cask', 'orbstack']);
|
|
@@ -108,6 +125,8 @@ export async function ensureDockerDesktop(
|
|
|
108
125
|
onMessage,
|
|
109
126
|
{ runOkFn = runOk } = {}
|
|
110
127
|
) {
|
|
128
|
+
applyDockerContext(ENGINES.DOCKER_DESKTOP);
|
|
129
|
+
|
|
111
130
|
if (!runOkFn('docker', ['info'])) {
|
|
112
131
|
throw new Error('Docker Desktop is not running. Please start Docker Desktop manually.');
|
|
113
132
|
}
|
package/lib/sandbox/shell.js
CHANGED
|
@@ -60,10 +60,44 @@ export function runOk(cmd, args, opts = {}) {
|
|
|
60
60
|
return result.status === 0;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
export function restoreTerminal() {
|
|
64
|
+
if (!process.stdout.isTTY) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
process.stdout.write([
|
|
70
|
+
'\x1b[?1049l',
|
|
71
|
+
'\x1b[?25h',
|
|
72
|
+
'\x1b>',
|
|
73
|
+
'\x1b[?1000l',
|
|
74
|
+
'\x1b[?1002l',
|
|
75
|
+
'\x1b[?1003l',
|
|
76
|
+
'\x1b[?1006l'
|
|
77
|
+
].join(''));
|
|
78
|
+
} catch {
|
|
79
|
+
// Best-effort cleanup only; preserve the original command result.
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (process.platform === 'win32') {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
execFileSync('stty', ['sane'], { stdio: 'inherit' });
|
|
88
|
+
} catch {
|
|
89
|
+
// Some environments do not provide stty or reject sane; ANSI reset still helps.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
63
93
|
export function runInteractive(cmd, args, opts = {}) {
|
|
64
94
|
const resolved = resolveCommand(cmd);
|
|
65
|
-
|
|
66
|
-
|
|
95
|
+
try {
|
|
96
|
+
const result = spawnSync(resolved, args, commandOptions(resolved, normalizeOptions(opts, 'inherit')));
|
|
97
|
+
return result.status ?? 1;
|
|
98
|
+
} finally {
|
|
99
|
+
restoreTerminal();
|
|
100
|
+
}
|
|
67
101
|
}
|
|
68
102
|
|
|
69
103
|
export function runVerbose(cmd, args, opts = {}) {
|
package/lib/update.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { info, ok, err } from './log.js';
|
|
4
4
|
import { resolveTemplateDir } from './paths.js';
|
|
5
|
-
import { renderFile, copySkillDir } from './render.js';
|
|
5
|
+
import { renderFile, copySkillDir, KNOWN_PLATFORMS } from './render.js';
|
|
6
6
|
|
|
7
7
|
const defaults = JSON.parse(
|
|
8
8
|
fs.readFileSync(new URL('./defaults.json', import.meta.url), 'utf8')
|
|
@@ -11,7 +11,16 @@ const defaults = JSON.parse(
|
|
|
11
11
|
const CONFIG_DIR = '.agents';
|
|
12
12
|
const CONFIG_PATH = path.join(CONFIG_DIR, '.airc.json');
|
|
13
13
|
|
|
14
|
-
function
|
|
14
|
+
function isPathOwnedByOtherPlatform(relativePath, platformType) {
|
|
15
|
+
const top = String(relativePath || '').replace(/\\/g, '/').replace(/^\.\//, '').split('/')[0];
|
|
16
|
+
if (!top.startsWith('.')) return false;
|
|
17
|
+
|
|
18
|
+
const candidate = top.slice(1);
|
|
19
|
+
if (!KNOWN_PLATFORMS.has(candidate)) return false;
|
|
20
|
+
return candidate !== platformType;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function syncFileRegistry(config, platformType) {
|
|
15
24
|
config.files ||= {};
|
|
16
25
|
const before = JSON.stringify({
|
|
17
26
|
files: {
|
|
@@ -32,12 +41,14 @@ function syncFileRegistry(config) {
|
|
|
32
41
|
const added = { managed: [], merged: [] };
|
|
33
42
|
|
|
34
43
|
for (const entry of defaults.files.managed) {
|
|
44
|
+
if (isPathOwnedByOtherPlatform(entry, platformType)) continue;
|
|
35
45
|
if (!allExisting.includes(entry)) {
|
|
36
46
|
config.files.managed.push(entry);
|
|
37
47
|
added.managed.push(entry);
|
|
38
48
|
}
|
|
39
49
|
}
|
|
40
50
|
for (const entry of defaults.files.merged) {
|
|
51
|
+
if (isPathOwnedByOtherPlatform(entry, platformType)) continue;
|
|
41
52
|
if (!allExisting.includes(entry)) {
|
|
42
53
|
config.files.merged.push(entry);
|
|
43
54
|
added.merged.push(entry);
|
|
@@ -139,7 +150,7 @@ async function cmdUpdate() {
|
|
|
139
150
|
ok('Updated .opencode/commands/update-agent-infra.md');
|
|
140
151
|
|
|
141
152
|
// sync file registry
|
|
142
|
-
const { added, changed } = syncFileRegistry(config);
|
|
153
|
+
const { added, changed } = syncFileRegistry(config, platformType);
|
|
143
154
|
const hasNewEntries = added.managed.length > 0 || added.merged.length > 0;
|
|
144
155
|
const platformAdded = !config.platform;
|
|
145
156
|
const sandboxAdded = !config.sandbox;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fitlab-ai/agent-infra",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
4
4
|
"description": "Bootstrap tool for AI multi-tool collaboration infrastructure — works with Claude Code, Codex, Gemini CLI, and OpenCode",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "node scripts/build-inline.js",
|
|
49
49
|
"demo:regen": "sh scripts/demo-regen.sh",
|
|
50
|
-
"prepare": "git config core.hooksPath .
|
|
51
|
-
"test": "node scripts/build-inline.js --check && node --test tests/cli/*.test.js tests/templates/*.test.js tests/core/*.test.js",
|
|
52
|
-
"prepublishOnly": "node scripts/build-inline.js --check && node --test tests/cli/*.test.js tests/templates/*.test.js tests/core/*.test.js"
|
|
50
|
+
"prepare": "git config core.hooksPath .git-hooks || true",
|
|
51
|
+
"test": "node scripts/build-inline.js --check && node --test tests/cli/*.test.js tests/templates/*.test.js tests/core/*.test.js tests/scripts/*.test.js",
|
|
52
|
+
"prepublishOnly": "node scripts/build-inline.js --check && node --test tests/cli/*.test.js tests/templates/*.test.js tests/core/*.test.js tests/scripts/*.test.js"
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -13,10 +13,10 @@ This guide walks you through using multiple AI coding assistants together on a p
|
|
|
13
13
|
Enable the shared Git hooks path before relying on the template hook chain:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
git config core.hooksPath .
|
|
16
|
+
git config core.hooksPath .git-hooks
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
This makes Git invoke the hooks
|
|
19
|
+
This makes Git invoke the hooks in the project repository's `.git-hooks/` directory, including `pre-commit` and `check-version-format.sh`.
|
|
20
20
|
|
|
21
21
|
## External Templates And Skills
|
|
22
22
|
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
在依赖模板中的 Git hook 链路前,先启用共享 hooks 路径:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
git config core.hooksPath .
|
|
16
|
+
git config core.hooksPath .git-hooks
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
这样 Git
|
|
19
|
+
这样 Git 才会调用项目仓库 `.git-hooks/` 目录下的 hook,包括 `pre-commit` 和 `check-version-format.sh`。
|
|
20
20
|
|
|
21
21
|
## 外部模板与 Skill
|
|
22
22
|
|
|
@@ -108,7 +108,7 @@ This project uses the following collaboration label prefixes, each with a define
|
|
|
108
108
|
| `status:` | Yes | — | PRs already have their own state flow (Open / Draft / Merged / Closed); Issues use `status:` labels for project tracking states |
|
|
109
109
|
| `in:` | Yes | Yes | Both Issues and PRs can be filtered by module |
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
Run the `/init-labels` command to initialize these labels via the platform adapter.
|
|
112
112
|
|
|
113
113
|
## Private Platform Extensions
|
|
114
114
|
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
| `status:` | Yes | — | PR 有自身状态流转(Open / Draft / Merged / Closed);Issue 使用 `status:` label 标记等待反馈、已确认等项目管理状态 |
|
|
109
109
|
| `in:` | Yes | Yes | Issue 和 PR 均可按模块筛选 |
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
使用 `/init-labels` 命令可通过平台适配器一次性创建标准 labels。
|
|
112
112
|
|
|
113
113
|
## 私有平台扩展
|
|
114
114
|
|
|
@@ -22,6 +22,44 @@ Before any later `gh issue` or `gh api "repos/..."` call, follow `.agents/rules/
|
|
|
22
22
|
- keep `gh pr *` commands on the current repository without adding `-R`
|
|
23
23
|
- keep organization-scoped commands such as `gh api "orgs/{owner}/..."` unchanged
|
|
24
24
|
|
|
25
|
+
## Issue Template Detection
|
|
26
|
+
|
|
27
|
+
Detect GitHub Issue Forms with:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
rg --files .github/ISSUE_TEMPLATE -g '*.yml' -g '!config.yml'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Read matching form files locally before creating the Issue. If the directory is missing or no form matches the task, use the caller's fallback body format.
|
|
34
|
+
|
|
35
|
+
Typical candidate templates:
|
|
36
|
+
- `bug_report.yml` for bug work
|
|
37
|
+
- `question.yml` for question or investigation work
|
|
38
|
+
- `feature_request.yml` for feature work
|
|
39
|
+
- `documentation.yml` for documentation work
|
|
40
|
+
- `other.yml` as the general fallback
|
|
41
|
+
|
|
42
|
+
For GitHub Issue Forms, inspect the matched form's:
|
|
43
|
+
- `name`
|
|
44
|
+
- `type:`
|
|
45
|
+
- `labels:`
|
|
46
|
+
- `body:`
|
|
47
|
+
|
|
48
|
+
Field handling rules:
|
|
49
|
+
- `textarea` and `input`: use `attributes.label` as the markdown heading and fill values from task.md
|
|
50
|
+
- `markdown`: skip template explanation prose
|
|
51
|
+
- `dropdown` and `checkboxes`: skip
|
|
52
|
+
- when task.md lacks a suitable value, write `N/A`
|
|
53
|
+
|
|
54
|
+
Suggested field mapping:
|
|
55
|
+
|
|
56
|
+
| Template field hint | task.md source |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `summary`, `title` | task title |
|
|
59
|
+
| `description`, `problem`, `what happened`, `issue-description`, `current-content` | task description |
|
|
60
|
+
| `solution`, `requirements`, `steps`, `suggested-content`, `impact`, `context`, `alternatives`, `expected` | requirements list |
|
|
61
|
+
| other `textarea` / `input` fields | task description, otherwise `N/A` |
|
|
62
|
+
|
|
25
63
|
## Read and Create Issues
|
|
26
64
|
|
|
27
65
|
Read an Issue:
|
|
@@ -82,6 +120,28 @@ Read Issue comments or search for existing hidden markers:
|
|
|
82
120
|
gh api "repos/$upstream_repo/issues/{issue-number}/comments" --paginate
|
|
83
121
|
```
|
|
84
122
|
|
|
123
|
+
## PR Template and Metadata Helpers
|
|
124
|
+
|
|
125
|
+
Read a repository PR template when present:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
cat .github/PULL_REQUEST_TEMPLATE.md
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Review recent merged PRs for style:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
gh pr list --limit 3 --state merged --json number,title,body
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Verify that standard type labels exist before PR metadata sync:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
gh label list --search "type:" --limit 1 --json name --jq 'length'
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
If the result is `0`, run `init-labels` before retrying PR metadata sync.
|
|
144
|
+
|
|
85
145
|
## Read and Create PRs
|
|
86
146
|
|
|
87
147
|
Read a PR:
|
|
@@ -22,6 +22,44 @@ gh repo view --json nameWithOwner
|
|
|
22
22
|
- `gh pr *` 命令保持作用于当前仓库,不额外加 `-R`
|
|
23
23
|
- `gh api "orgs/{owner}/..."` 这类 org 级命令保持不变
|
|
24
24
|
|
|
25
|
+
## Issue 模板检测
|
|
26
|
+
|
|
27
|
+
使用以下命令检测 GitHub Issue Forms:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
rg --files .github/ISSUE_TEMPLATE -g '*.yml' -g '!config.yml'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
创建 Issue 前先读取匹配的 form 文件。目录不存在或没有匹配 form 时,使用调用方定义的 fallback 正文格式。
|
|
34
|
+
|
|
35
|
+
常见候选模板:
|
|
36
|
+
- `bug_report.yml`:bug 工作
|
|
37
|
+
- `question.yml`:问题或排查工作
|
|
38
|
+
- `feature_request.yml`:功能工作
|
|
39
|
+
- `documentation.yml`:文档工作
|
|
40
|
+
- `other.yml`:通用 fallback
|
|
41
|
+
|
|
42
|
+
对 GitHub Issue Forms,检查匹配 form 的:
|
|
43
|
+
- `name`
|
|
44
|
+
- `type:`
|
|
45
|
+
- `labels:`
|
|
46
|
+
- `body:`
|
|
47
|
+
|
|
48
|
+
字段处理规则:
|
|
49
|
+
- `textarea` 和 `input`:使用 `attributes.label` 作为 markdown 标题,并从 task.md 填充值
|
|
50
|
+
- `markdown`:跳过模板说明文案
|
|
51
|
+
- `dropdown` 和 `checkboxes`:跳过
|
|
52
|
+
- task.md 缺少合适值时,写入 `N/A`
|
|
53
|
+
|
|
54
|
+
建议字段映射:
|
|
55
|
+
|
|
56
|
+
| 模板字段提示 | task.md 来源 |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `summary`, `title` | 任务标题 |
|
|
59
|
+
| `description`, `problem`, `what happened`, `issue-description`, `current-content` | 任务描述 |
|
|
60
|
+
| `solution`, `requirements`, `steps`, `suggested-content`, `impact`, `context`, `alternatives`, `expected` | 需求列表 |
|
|
61
|
+
| 其他 `textarea` / `input` 字段 | 任务描述,否则 `N/A` |
|
|
62
|
+
|
|
25
63
|
## Issue 读取与创建
|
|
26
64
|
|
|
27
65
|
读取 Issue:
|
|
@@ -82,6 +120,28 @@ gh issue close {issue-number} -R "$upstream_repo" --reason "{reason}"
|
|
|
82
120
|
gh api "repos/$upstream_repo/issues/{issue-number}/comments" --paginate
|
|
83
121
|
```
|
|
84
122
|
|
|
123
|
+
## PR 模板与元数据辅助命令
|
|
124
|
+
|
|
125
|
+
存在仓库 PR 模板时读取:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
cat .github/PULL_REQUEST_TEMPLATE.md
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
参考最近合并的 PR 风格:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
gh pr list --limit 3 --state merged --json number,title,body
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
PR 元数据同步前验证标准 type labels 是否存在:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
gh label list --search "type:" --limit 1 --json name --jq 'length'
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
如果结果是 `0`,先运行 `init-labels`,再重试 PR 元数据同步。
|
|
144
|
+
|
|
85
145
|
## PR 读取与创建
|
|
86
146
|
|
|
87
147
|
读取 PR:
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Issue Sync
|
|
2
2
|
|
|
3
|
+
## Marker Registry
|
|
4
|
+
|
|
5
|
+
These hidden markers are the canonical registry for Issue synchronization:
|
|
6
|
+
|
|
7
|
+
| Key | Marker |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `task` | `<!-- sync-issue:{task-id}:task -->` |
|
|
10
|
+
| `artifact` | `<!-- sync-issue:{task-id}:{artifact-stem} -->` |
|
|
11
|
+
| `artifactChunk` | `<!-- sync-issue:{task-id}:{artifact-stem}:{part}/{total} -->` |
|
|
12
|
+
| `summary` | `<!-- sync-issue:{task-id}:summary -->` |
|
|
13
|
+
| `cancel` | `<!-- sync-issue:{task-id}:cancel -->` |
|
|
14
|
+
|
|
15
|
+
Callers should refer to the marker key in skill prose and keep concrete marker strings in this rule or the platform adapter defaults.
|
|
16
|
+
|
|
3
17
|
This code platform does not provide built-in issue synchronization.
|
|
4
18
|
|
|
5
19
|
Issue metadata, labels, milestones, assignees, and comments are skipped for custom platforms unless you provide matching `.{platform}.en.md` rule templates and platform adapters. Continue writing local task artifacts normally.
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Issue Sync Rules
|
|
2
2
|
|
|
3
|
+
## Marker Registry
|
|
4
|
+
|
|
5
|
+
These hidden markers are the canonical registry for Issue synchronization:
|
|
6
|
+
|
|
7
|
+
| Key | Marker |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `task` | `<!-- sync-issue:{task-id}:task -->` |
|
|
10
|
+
| `artifact` | `<!-- sync-issue:{task-id}:{artifact-stem} -->` |
|
|
11
|
+
| `artifactChunk` | `<!-- sync-issue:{task-id}:{artifact-stem}:{part}/{total} -->` |
|
|
12
|
+
| `summary` | `<!-- sync-issue:{task-id}:summary -->` |
|
|
13
|
+
| `cancel` | `<!-- sync-issue:{task-id}:cancel -->` |
|
|
14
|
+
|
|
15
|
+
Callers should refer to the marker key in skill prose and keep concrete marker strings in this rule or the platform adapter defaults.
|
|
16
|
+
|
|
3
17
|
Read this file before a task skill updates a GitHub Issue.
|
|
4
18
|
|
|
5
19
|
## Upstream Repository Detection
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Issue 同步规则
|
|
2
2
|
|
|
3
|
+
## Marker 注册表
|
|
4
|
+
|
|
5
|
+
以下隐藏标记是 Issue 同步的唯一权威注册表:
|
|
6
|
+
|
|
7
|
+
| Key | Marker |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `task` | `<!-- sync-issue:{task-id}:task -->` |
|
|
10
|
+
| `artifact` | `<!-- sync-issue:{task-id}:{artifact-stem} -->` |
|
|
11
|
+
| `artifactChunk` | `<!-- sync-issue:{task-id}:{artifact-stem}:{part}/{total} -->` |
|
|
12
|
+
| `summary` | `<!-- sync-issue:{task-id}:summary -->` |
|
|
13
|
+
| `cancel` | `<!-- sync-issue:{task-id}:cancel -->` |
|
|
14
|
+
|
|
15
|
+
Skill 正文应引用 marker key,具体 marker 字符串只保留在本规则或平台适配器默认值中。
|
|
16
|
+
|
|
3
17
|
在任务技能需要更新 GitHub Issue 时先读取本文件。
|
|
4
18
|
|
|
5
19
|
## Upstream 仓库检测
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Issue 同步
|
|
2
2
|
|
|
3
|
+
## Marker 注册表
|
|
4
|
+
|
|
5
|
+
以下隐藏标记是 Issue 同步的唯一权威注册表:
|
|
6
|
+
|
|
7
|
+
| Key | Marker |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `task` | `<!-- sync-issue:{task-id}:task -->` |
|
|
10
|
+
| `artifact` | `<!-- sync-issue:{task-id}:{artifact-stem} -->` |
|
|
11
|
+
| `artifactChunk` | `<!-- sync-issue:{task-id}:{artifact-stem}:{part}/{total} -->` |
|
|
12
|
+
| `summary` | `<!-- sync-issue:{task-id}:summary -->` |
|
|
13
|
+
| `cancel` | `<!-- sync-issue:{task-id}:cancel -->` |
|
|
14
|
+
|
|
15
|
+
Skill 正文应引用 marker key,具体 marker 字符串只保留在本规则或平台适配器默认值中。
|
|
16
|
+
|
|
3
17
|
当前代码平台未内置 Issue 同步支持。
|
|
4
18
|
|
|
5
19
|
自定义平台会跳过 Issue 元数据、标签、里程碑、负责人和评论同步,除非你提供匹配的 `.{platform}.zh-CN.md` 规则模板和平台适配器。请继续正常写入本地任务产物。
|
|
@@ -43,6 +43,16 @@ Update a milestone:
|
|
|
43
43
|
gh api "repos/$repo/milestones/{number}" -X PATCH -f state="{state}" -f description="{description}"
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
## Error Prompt Templates
|
|
47
|
+
|
|
48
|
+
Use these normalized prompts when the GitHub setup scripts fail:
|
|
49
|
+
|
|
50
|
+
| Condition | Prompt |
|
|
51
|
+
|---|---|
|
|
52
|
+
| CLI missing | GitHub CLI (`gh`) is not installed |
|
|
53
|
+
| Authentication failed | `GitHub CLI is not authenticated` |
|
|
54
|
+
| API rate limit | `GitHub API rate limit reached, please retry later` |
|
|
55
|
+
|
|
46
56
|
## Constraints
|
|
47
57
|
|
|
48
58
|
- use label names as the idempotency key
|
|
@@ -43,6 +43,16 @@ gh api "repos/$repo/milestones" -f title="{title}" -f description="{description}
|
|
|
43
43
|
gh api "repos/$repo/milestones/{number}" -X PATCH -f state="{state}" -f description="{description}"
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
## 错误提示模板
|
|
47
|
+
|
|
48
|
+
GitHub 初始化脚本失败时使用以下标准提示:
|
|
49
|
+
|
|
50
|
+
| 条件 | 提示 |
|
|
51
|
+
|---|---|
|
|
52
|
+
| CLI 缺失 | GitHub CLI (`gh`) is not installed |
|
|
53
|
+
| 认证失败 | `GitHub CLI is not authenticated` |
|
|
54
|
+
| API 限流 | `GitHub API rate limit reached, please retry later` |
|
|
55
|
+
|
|
46
56
|
## 约束
|
|
47
57
|
|
|
48
58
|
- label 以名称作为幂等键
|
|
@@ -21,6 +21,22 @@ When needed, read the linked Issue:
|
|
|
21
21
|
gh issue view {issue-number} --json number,title,labels,url
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
## Contributor Mapping Helpers
|
|
25
|
+
|
|
26
|
+
Merged PR queries used for release notes should include authors when contributors are needed:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
gh pr list --state merged --base "{branch}" --json number,title,mergedAt,labels,author
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Linked Issue queries used for reporter attribution should include the author:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
gh issue view {issue-number} --json number,title,labels,url,author
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Map GitHub no-reply emails with this rule: if `Name <email>` contains an email matching `(\d+\+)?(\S+?)@users\.noreply\.github\.com`, use the second capture group lowercased as the login. This covers both `{id}+{login}@users.noreply.github.com` and `{login}@users.noreply.github.com`.
|
|
39
|
+
|
|
24
40
|
## Create a Draft Release
|
|
25
41
|
|
|
26
42
|
```bash
|
|
@@ -21,6 +21,22 @@ gh pr list --state merged --base "{branch}" --json number,title,mergedAt,labels
|
|
|
21
21
|
gh issue view {issue-number} --json number,title,labels,url
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
## Contributor 映射辅助规则
|
|
25
|
+
|
|
26
|
+
release notes 需要 contributors 时,已合并 PR 查询应包含 author:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
gh pr list --state merged --base "{branch}" --json number,title,mergedAt,labels,author
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
关联 Issue 用于 reporter 归因时,查询应包含 author:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
gh issue view {issue-number} --json number,title,labels,url,author
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
GitHub no-reply 邮箱映射规则:如果 `Name <email>` 中的 email 匹配 `(\d+\+)?(\S+?)@users\.noreply\.github\.com`,使用第二个捕获组的小写形式作为 login。该规则同时覆盖 `{id}+{login}@users.noreply.github.com` 和 `{login}@users.noreply.github.com`。
|
|
39
|
+
|
|
24
40
|
## 创建 Draft Release
|
|
25
41
|
|
|
26
42
|
```bash
|