@ethlete/agent-rules 0.1.0-next.4 → 0.1.0-next.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/CHANGELOG.md +26 -0
- package/README.md +192 -11
- package/content/git-hooks/post-checkout.sh +10 -0
- package/content/git-hooks/pre-push.sh +5 -0
- package/content/hooks/context-warning.py +259 -97
- package/content/skills/figma-export/SKILL.md +193 -0
- package/content/skills/figma-export/dump-figma-layers.py +83 -0
- package/content/skills/figma-export/dump-figma-svg.py +235 -0
- package/content/skills/figma-export/measure-template.mjs +87 -0
- package/content/skills/git-flow/SKILL.md +83 -0
- package/content/skills/handoff/SKILL.md +4 -0
- package/content/skills/query/SKILL.md +23 -13
- package/package.json +12 -1
- package/src/index.js +10 -5
- package/src/index.js.map +1 -1
- package/src/lib/config.d.ts +30 -2
- package/src/lib/config.js +20 -3
- package/src/lib/config.js.map +1 -1
- package/src/lib/git-flow/build.d.ts +35 -0
- package/src/lib/git-flow/build.js +24 -0
- package/src/lib/git-flow/build.js.map +1 -0
- package/src/lib/git-flow/config.d.ts +59 -0
- package/src/lib/git-flow/config.js +50 -0
- package/src/lib/git-flow/config.js.map +1 -0
- package/src/lib/git-flow/index.d.ts +5 -0
- package/src/lib/git-flow/index.js +9 -0
- package/src/lib/git-flow/index.js.map +1 -0
- package/src/lib/git-flow/parse.d.ts +49 -0
- package/src/lib/git-flow/parse.js +274 -0
- package/src/lib/git-flow/parse.js.map +1 -0
- package/src/lib/git-flow/start.d.ts +22 -0
- package/src/lib/git-flow/start.js +24 -0
- package/src/lib/git-flow/start.js.map +1 -0
- package/src/lib/git-flow/validate.d.ts +34 -0
- package/src/lib/git-flow/validate.js +72 -0
- package/src/lib/git-flow/validate.js.map +1 -0
- package/src/lib/git-flow-command.d.ts +4 -0
- package/src/lib/git-flow-command.js +157 -0
- package/src/lib/git-flow-command.js.map +1 -0
- package/src/lib/git-flow-repair.d.ts +17 -0
- package/src/lib/git-flow-repair.js +150 -0
- package/src/lib/git-flow-repair.js.map +1 -0
- package/src/lib/git-flow-start.d.ts +20 -0
- package/src/lib/git-flow-start.js +147 -0
- package/src/lib/git-flow-start.js.map +1 -0
- package/src/lib/git.d.ts +27 -0
- package/src/lib/git.js +49 -0
- package/src/lib/git.js.map +1 -0
- package/src/lib/gitlab.d.ts +35 -0
- package/src/lib/gitlab.js +98 -0
- package/src/lib/gitlab.js.map +1 -0
- package/src/lib/jira.d.ts +28 -0
- package/src/lib/jira.js +83 -0
- package/src/lib/jira.js.map +1 -0
- package/src/lib/owned-paths.js +19 -1
- package/src/lib/owned-paths.js.map +1 -1
- package/src/lib/plan.js +29 -5
- package/src/lib/plan.js.map +1 -1
- package/src/lib/prompt.d.ts +8 -0
- package/src/lib/prompt.js +27 -0
- package/src/lib/prompt.js.map +1 -0
- package/src/lib/render.d.ts +12 -1
- package/src/lib/render.js +23 -6
- package/src/lib/render.js.map +1 -1
- package/src/lib/targets/claude-hooks.d.ts +1 -23
- package/src/lib/targets/claude-hooks.js +15 -84
- package/src/lib/targets/claude-hooks.js.map +1 -1
- package/src/lib/targets/codex-hooks.d.ts +12 -0
- package/src/lib/targets/codex-hooks.js +33 -0
- package/src/lib/targets/codex-hooks.js.map +1 -0
- package/src/lib/targets/git-hooks.d.ts +25 -0
- package/src/lib/targets/git-hooks.js +70 -0
- package/src/lib/targets/git-hooks.js.map +1 -0
- package/src/lib/targets/hooks-shared.d.ts +38 -0
- package/src/lib/targets/hooks-shared.js +95 -0
- package/src/lib/targets/hooks-shared.js.map +1 -0
package/src/lib/jira.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchJiraIssue = exports.resolveJiraCredentials = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const config_1 = require("./config");
|
|
6
|
+
const TIMEOUT_MS = 15000;
|
|
7
|
+
const readEnv = (name) => {
|
|
8
|
+
var _a;
|
|
9
|
+
const value = (_a = process.env[name]) === null || _a === void 0 ? void 0 : _a.trim();
|
|
10
|
+
return value ? value : undefined;
|
|
11
|
+
};
|
|
12
|
+
const normalizeHost = (host) => {
|
|
13
|
+
const withScheme = /^https?:\/\//.test(host) ? host : `https://${host}`;
|
|
14
|
+
return withScheme.replace(/\/+$/, '');
|
|
15
|
+
};
|
|
16
|
+
const CREDENTIAL_HELP = [
|
|
17
|
+
`Set JIRA_HOST, JIRA_EMAIL and JIRA_API_TOKEN, or add a "jira" block to ${config_1.LOCAL_CONFIG_FILE_NAME} (gitignored):`,
|
|
18
|
+
' { "jira": { "host": "https://your-team.atlassian.net", "email": "you@example.com", "token": "…" } }',
|
|
19
|
+
'Create a token at https://id.atlassian.com/manage-profile/security/api-tokens.',
|
|
20
|
+
].join('\n');
|
|
21
|
+
/**
|
|
22
|
+
* The host may also be committed in `ethlete-agents.config.json` (it is not a secret); the email and
|
|
23
|
+
* token may only come from the environment or the gitignored local config.
|
|
24
|
+
*/
|
|
25
|
+
const resolveJiraCredentials = (options) => {
|
|
26
|
+
var _a, _b, _c, _d, _e;
|
|
27
|
+
const local = (0, config_1.readLocalConfig)(options.root);
|
|
28
|
+
const localJira = (_a = (local.exists && local.valid ? local.config.jira : undefined)) !== null && _a !== void 0 ? _a : {};
|
|
29
|
+
const host = (_c = (_b = readEnv('JIRA_HOST')) !== null && _b !== void 0 ? _b : localJira.host) !== null && _c !== void 0 ? _c : options.settings.host;
|
|
30
|
+
const email = (_d = readEnv('JIRA_EMAIL')) !== null && _d !== void 0 ? _d : localJira.email;
|
|
31
|
+
const token = (_e = readEnv('JIRA_API_TOKEN')) !== null && _e !== void 0 ? _e : localJira.token;
|
|
32
|
+
const missing = [...(host ? [] : ['host']), ...(email ? [] : ['email']), ...(token ? [] : ['API token'])];
|
|
33
|
+
if (!host || !email || !token) {
|
|
34
|
+
throw new Error(`Jira is not configured — missing ${missing.join(', ')}.\n${CREDENTIAL_HELP}`);
|
|
35
|
+
}
|
|
36
|
+
return { host: normalizeHost(host), email, token };
|
|
37
|
+
};
|
|
38
|
+
exports.resolveJiraCredentials = resolveJiraCredentials;
|
|
39
|
+
const request = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
40
|
+
const { url, credentials, describe } = options;
|
|
41
|
+
const authorization = Buffer.from(`${credentials.email}:${credentials.token}`).toString('base64');
|
|
42
|
+
const response = yield fetch(url, {
|
|
43
|
+
headers: { authorization: `Basic ${authorization}`, accept: 'application/json' },
|
|
44
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
45
|
+
});
|
|
46
|
+
if (response.status === 401 || response.status === 403) {
|
|
47
|
+
throw new Error(`Jira rejected the credentials (${response.status}).\n${CREDENTIAL_HELP}`);
|
|
48
|
+
}
|
|
49
|
+
if (response.status === 404)
|
|
50
|
+
throw new Error(`Jira has no ${describe}, or the token cannot see it.`);
|
|
51
|
+
if (!response.ok)
|
|
52
|
+
throw new Error(`Jira responded ${response.status} ${response.statusText} for ${describe}.`);
|
|
53
|
+
return (yield response.json());
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* A branch subject must be a plain string. A rich-text or select field configured as the subject
|
|
57
|
+
* field yields an object, which is a misconfiguration to report rather than something to stringify.
|
|
58
|
+
*/
|
|
59
|
+
const readSubjectField = (fields, field) => {
|
|
60
|
+
if (!field)
|
|
61
|
+
return undefined;
|
|
62
|
+
const value = fields[field];
|
|
63
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
64
|
+
};
|
|
65
|
+
const fetchJiraIssue = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
66
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
67
|
+
const { key, credentials, settings } = options;
|
|
68
|
+
const fields = ['summary', 'issuetype', 'parent', ...(settings.subjectField ? [settings.subjectField] : [])];
|
|
69
|
+
const issue = (yield request({
|
|
70
|
+
url: `${credentials.host}/rest/api/3/issue/${encodeURIComponent(key)}?fields=${fields.join(',')}`,
|
|
71
|
+
credentials,
|
|
72
|
+
describe: `issue ${key}`,
|
|
73
|
+
}));
|
|
74
|
+
return {
|
|
75
|
+
key: (_a = issue.key) !== null && _a !== void 0 ? _a : key,
|
|
76
|
+
summary: (_c = (_b = issue.fields) === null || _b === void 0 ? void 0 : _b.summary) !== null && _c !== void 0 ? _c : '',
|
|
77
|
+
issueType: (_f = (_e = (_d = issue.fields) === null || _d === void 0 ? void 0 : _d.issuetype) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : '',
|
|
78
|
+
parentKey: (_h = (_g = issue.fields) === null || _g === void 0 ? void 0 : _g.parent) === null || _h === void 0 ? void 0 : _h.key,
|
|
79
|
+
subject: readSubjectField((_j = issue.fields) !== null && _j !== void 0 ? _j : {}, settings.subjectField),
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
exports.fetchJiraIssue = fetchJiraIssue;
|
|
83
|
+
//# sourceMappingURL=jira.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jira.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/jira.ts"],"names":[],"mappings":"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"}
|
package/src/lib/owned-paths.js
CHANGED
|
@@ -5,7 +5,7 @@ const fs_1 = require("fs");
|
|
|
5
5
|
const path_1 = require("path");
|
|
6
6
|
// `.agents/ethlete` and `.github/instructions/ethlete-*` are no longer emitted, but stay owned so
|
|
7
7
|
// a sync prunes them from repos generated by older versions.
|
|
8
|
-
const OWNED_DIRECTORIES = ['.agents/ethlete', '.claude/rules/ethlete', '.claude/hooks/ethlete'];
|
|
8
|
+
const OWNED_DIRECTORIES = ['.agents/ethlete', '.claude/rules/ethlete', '.claude/hooks/ethlete', '.codex/hooks/ethlete'];
|
|
9
9
|
const OWNED_PARENTS = [
|
|
10
10
|
{ dir: '.agents/skills', match: (entry) => entry.startsWith('ethlete-') },
|
|
11
11
|
{ dir: '.claude/skills', match: (entry) => entry.startsWith('ethlete-') },
|
|
@@ -15,6 +15,23 @@ const OWNED_PARENTS = [
|
|
|
15
15
|
match: (entry) => entry.startsWith('ethlete-') && entry.endsWith('.instructions.md'),
|
|
16
16
|
},
|
|
17
17
|
];
|
|
18
|
+
/**
|
|
19
|
+
* Files that exist only to register hooks: once the last generated entry is removed the merge
|
|
20
|
+
* leaves `{}` behind, which is ours to clean up. Any hand-written entry keeps the file non-empty
|
|
21
|
+
* and therefore unowned.
|
|
22
|
+
*/
|
|
23
|
+
const OWNED_WHEN_EMPTY = ['.codex/hooks.json'];
|
|
24
|
+
const isEmptyObject = (absolute) => {
|
|
25
|
+
if (!(0, fs_1.existsSync)(absolute))
|
|
26
|
+
return false;
|
|
27
|
+
try {
|
|
28
|
+
const parsed = JSON.parse((0, fs_1.readFileSync)(absolute, 'utf8'));
|
|
29
|
+
return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) && Object.keys(parsed).length === 0;
|
|
30
|
+
}
|
|
31
|
+
catch (_a) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
18
35
|
const walk = (root, absoluteDir) => {
|
|
19
36
|
if (!(0, fs_1.existsSync)(absoluteDir))
|
|
20
37
|
return [];
|
|
@@ -44,6 +61,7 @@ const collectOwnedPaths = (root) => {
|
|
|
44
61
|
owned.push(...((0, fs_1.statSync)(absolute).isDirectory() ? walk(root, absolute) : [`${parent.dir}/${entry}`]));
|
|
45
62
|
}
|
|
46
63
|
}
|
|
64
|
+
owned.push(...OWNED_WHEN_EMPTY.filter((path) => isEmptyObject((0, path_1.join)(root, path))));
|
|
47
65
|
return owned;
|
|
48
66
|
};
|
|
49
67
|
exports.collectOwnedPaths = collectOwnedPaths;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"owned-paths.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/owned-paths.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"owned-paths.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/owned-paths.ts"],"names":[],"mappings":"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"}
|
package/src/lib/plan.js
CHANGED
|
@@ -10,6 +10,9 @@ const agents_skills_1 = require("./targets/agents-skills");
|
|
|
10
10
|
const claude_hooks_1 = require("./targets/claude-hooks");
|
|
11
11
|
const claude_1 = require("./targets/claude");
|
|
12
12
|
const codex_1 = require("./targets/codex");
|
|
13
|
+
const codex_hooks_1 = require("./targets/codex-hooks");
|
|
14
|
+
const git_hooks_1 = require("./targets/git-hooks");
|
|
15
|
+
const hooks_shared_1 = require("./targets/hooks-shared");
|
|
13
16
|
const copilot_1 = require("./targets/copilot");
|
|
14
17
|
const cursor_1 = require("./targets/cursor");
|
|
15
18
|
const SKILL_LINK_PATTERN = /\{%\s*skill:([a-zA-Z0-9_.-]+)\s*%\}/g;
|
|
@@ -64,7 +67,7 @@ const collectLocalConfigWarnings = (root) => {
|
|
|
64
67
|
}
|
|
65
68
|
const warnings = [];
|
|
66
69
|
if (local.unknownKeys.length > 0) {
|
|
67
|
-
warnings.push(`${config_1.LOCAL_CONFIG_FILE_NAME} contains unsupported key(s): ${local.unknownKeys.join(', ')} — the local file supports "disableHooks", "disableAutoHandoffSave" and "
|
|
70
|
+
warnings.push(`${config_1.LOCAL_CONFIG_FILE_NAME} contains unsupported key(s): ${local.unknownKeys.join(', ')} — the local file supports "disableHooks", "disableAutoHandoffSave", "sdkSourcePath" and "jira"; it never changes what sync writes.`);
|
|
68
71
|
}
|
|
69
72
|
warnings.push(...describeSdkSourcePath({ root, value: local.config.sdkSourcePath }));
|
|
70
73
|
const disable = local.config.disableHooks;
|
|
@@ -72,9 +75,9 @@ const collectLocalConfigWarnings = (root) => {
|
|
|
72
75
|
warnings.push(`${config_1.LOCAL_CONFIG_FILE_NAME} has an invalid "disableHooks" value — use true or an array of hook names; hooks stay enabled.`);
|
|
73
76
|
}
|
|
74
77
|
if (Array.isArray(disable)) {
|
|
75
|
-
const unknown = disable.filter((name) => !(name in
|
|
78
|
+
const unknown = disable.filter((name) => !(name in hooks_shared_1.KNOWN_HOOKS));
|
|
76
79
|
if (unknown.length > 0) {
|
|
77
|
-
warnings.push(`${config_1.LOCAL_CONFIG_FILE_NAME} disables unknown hook(s): ${unknown.join(', ')}. Known hooks: ${Object.keys(
|
|
80
|
+
warnings.push(`${config_1.LOCAL_CONFIG_FILE_NAME} disables unknown hook(s): ${unknown.join(', ')}. Known hooks: ${Object.keys(hooks_shared_1.KNOWN_HOOKS).join(', ')}.`);
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
83
|
const disableAutoHandoffSave = local.config.disableAutoHandoffSave;
|
|
@@ -83,8 +86,19 @@ const collectLocalConfigWarnings = (root) => {
|
|
|
83
86
|
}
|
|
84
87
|
return warnings;
|
|
85
88
|
};
|
|
89
|
+
/**
|
|
90
|
+
* Only `.husky/` is written into, never `.git/hooks/`: the generated files are committed and CI's
|
|
91
|
+
* `check` diffs them, so a hook that lives outside the working tree could never be in sync.
|
|
92
|
+
*/
|
|
93
|
+
const collectGitHookWarnings = (config) => {
|
|
94
|
+
if (config.gitHooks.length === 0 || (0, fs_1.existsSync)((0, path_1.join)(config.root, git_hooks_1.HUSKY_DIR)))
|
|
95
|
+
return [];
|
|
96
|
+
return [
|
|
97
|
+
`gitHooks is set to ${config.gitHooks.join(', ')} but there is no ${git_hooks_1.HUSKY_DIR}/ directory — nothing was written. Install husky, or run \`npx ethlete-agents git-flow check\` from your own hooks.`,
|
|
98
|
+
];
|
|
99
|
+
};
|
|
86
100
|
const collectWarnings = (config) => {
|
|
87
|
-
const warnings = collectLocalConfigWarnings(config.root);
|
|
101
|
+
const warnings = [...collectLocalConfigWarnings(config.root), ...collectGitHookWarnings(config)];
|
|
88
102
|
if (!config.claudeMdImportsAgentsMd)
|
|
89
103
|
return warnings;
|
|
90
104
|
if (!config.targets.includes('codex')) {
|
|
@@ -101,7 +115,8 @@ const collectWarnings = (config) => {
|
|
|
101
115
|
*/
|
|
102
116
|
const buildPlan = (options) => {
|
|
103
117
|
const { config, version } = options;
|
|
104
|
-
(0,
|
|
118
|
+
(0, hooks_shared_1.assertKnownHooks)(config.hooks);
|
|
119
|
+
(0, git_hooks_1.assertKnownGitHooks)(config.gitHooks);
|
|
105
120
|
const { kept, skipped } = (0, filter_1.filterContent)((0, load_content_1.loadContent)(), config);
|
|
106
121
|
const skills = kept.filter((item) => item.frontmatter.kind === 'skill');
|
|
107
122
|
const emittedSkills = new Set(skills.map((item) => item.frontmatter.name));
|
|
@@ -133,6 +148,15 @@ const buildPlan = (options) => {
|
|
|
133
148
|
context,
|
|
134
149
|
claudeTarget: config.targets.includes('claude'),
|
|
135
150
|
existingSettings: readExisting(config.root, claude_hooks_1.CLAUDE_SETTINGS_FILE),
|
|
151
|
+
}), ...(0, codex_hooks_1.emitCodexHooks)({
|
|
152
|
+
context,
|
|
153
|
+
codexTarget: config.targets.includes('codex'),
|
|
154
|
+
existingHooks: readExisting(config.root, codex_hooks_1.CODEX_HOOKS_FILE),
|
|
155
|
+
}), ...(0, git_hooks_1.emitGitHooks)({
|
|
156
|
+
gitHooks: config.gitHooks,
|
|
157
|
+
version,
|
|
158
|
+
huskyExists: (0, fs_1.existsSync)((0, path_1.join)(config.root, git_hooks_1.HUSKY_DIR)),
|
|
159
|
+
existing: Object.fromEntries(Object.keys(git_hooks_1.KNOWN_GIT_HOOKS).map((name) => [name, readExisting(config.root, (0, git_hooks_1.huskyHookPath)(name))])),
|
|
136
160
|
}));
|
|
137
161
|
return { files, skipped, danglingLinks: findDanglingLinks(kept, emittedSkills), warnings: collectWarnings(config) };
|
|
138
162
|
};
|
package/src/lib/plan.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/plan.ts"],"names":[],"mappings":";;;AAAA,2BAAuE;AACvE,+BAAqC;AACrC,qCAA+E;AAC/E,qCAAsD;AACtD,iDAA0D;AAC1D,2DAA2D;AAC3D,yDAA+
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.confirm = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const promises_1 = require("readline/promises");
|
|
6
|
+
/**
|
|
7
|
+
* Without a TTY there is nobody to ask, so an unattended run must pass `--yes` explicitly rather
|
|
8
|
+
* than have silence read as consent.
|
|
9
|
+
*/
|
|
10
|
+
const confirm = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
11
|
+
if (options.assumeYes)
|
|
12
|
+
return true;
|
|
13
|
+
if (!process.stdin.isTTY) {
|
|
14
|
+
console.error('Nothing to prompt on (no TTY). Re-run with --yes to proceed unattended.');
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const readline = (0, promises_1.createInterface)({ input: process.stdin, output: process.stdout });
|
|
18
|
+
try {
|
|
19
|
+
const answer = yield readline.question(`${options.question} [y/N] `);
|
|
20
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
readline.close();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
exports.confirm = confirm;
|
|
27
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/prompt.ts"],"names":[],"mappings":";;;;AAAA,gDAAoD;AAEpD;;;GAGG;AACI,MAAM,OAAO,GAAG,CAAO,OAAiD,EAAE,EAAE;IACjF,IAAI,OAAO,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAEnC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;QAEzF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,IAAA,0BAAe,EAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEnF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,QAAQ,SAAS,CAAC,CAAC;QAErE,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;YAAS,CAAC;QACT,QAAQ,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;AACH,CAAC,CAAA,CAAC;AAlBW,QAAA,OAAO,WAkBlB"}
|
package/src/lib/render.d.ts
CHANGED
|
@@ -31,9 +31,20 @@ export declare const renderDescription: (options: {
|
|
|
31
31
|
}) => string;
|
|
32
32
|
/**
|
|
33
33
|
* Rewrites the block between the markers, leaving everything a repo wrote around it untouched.
|
|
34
|
-
* A file without markers gets the block appended.
|
|
34
|
+
* A file without markers gets the block appended. Shell files pass their own `#` markers.
|
|
35
35
|
*/
|
|
36
36
|
export declare const replaceMarkedBlock: (options: {
|
|
37
37
|
existing: string;
|
|
38
38
|
block: string;
|
|
39
|
+
startMarker?: string;
|
|
40
|
+
endMarker?: string;
|
|
41
|
+
}) => string;
|
|
42
|
+
/**
|
|
43
|
+
* Takes the block back out, so switching a generated block off in the config removes it instead of
|
|
44
|
+
* leaving it behind — `sync`'s file-level pruning cannot reach inside a file the repo also owns.
|
|
45
|
+
*/
|
|
46
|
+
export declare const removeMarkedBlock: (options: {
|
|
47
|
+
existing: string;
|
|
48
|
+
startMarker: string;
|
|
49
|
+
endMarker: string;
|
|
39
50
|
}) => string;
|
package/src/lib/render.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.replaceMarkedBlock = exports.renderDescription = exports.substituteVars = exports.renderBody = exports.buildBanner = exports.END_MARKER = exports.START_MARKER = void 0;
|
|
3
|
+
exports.removeMarkedBlock = exports.replaceMarkedBlock = exports.renderDescription = exports.substituteVars = exports.renderBody = exports.buildBanner = exports.END_MARKER = exports.START_MARKER = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* `{% … %}`, not `{{ … }}`: content bodies routinely quote Angular templates, and an example
|
|
6
6
|
* containing `{{ count() }}` must not be mistaken for a template token.
|
|
@@ -56,18 +56,35 @@ const renderDescription = (options) => (0, exports.substituteVars)({
|
|
|
56
56
|
exports.renderDescription = renderDescription;
|
|
57
57
|
/**
|
|
58
58
|
* Rewrites the block between the markers, leaving everything a repo wrote around it untouched.
|
|
59
|
-
* A file without markers gets the block appended.
|
|
59
|
+
* A file without markers gets the block appended. Shell files pass their own `#` markers.
|
|
60
60
|
*/
|
|
61
61
|
const replaceMarkedBlock = (options) => {
|
|
62
|
+
var _a, _b;
|
|
62
63
|
const { existing, block } = options;
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
const
|
|
64
|
+
const startMarker = (_a = options.startMarker) !== null && _a !== void 0 ? _a : exports.START_MARKER;
|
|
65
|
+
const endMarker = (_b = options.endMarker) !== null && _b !== void 0 ? _b : exports.END_MARKER;
|
|
66
|
+
const wrapped = `${startMarker}\n${block}\n${endMarker}`;
|
|
67
|
+
const start = existing.indexOf(startMarker);
|
|
68
|
+
const end = existing.indexOf(endMarker);
|
|
66
69
|
if (start === -1 || end === -1 || end < start) {
|
|
67
70
|
const separator = existing.trim().length > 0 ? `${existing.trimEnd()}\n\n` : '';
|
|
68
71
|
return `${separator}${wrapped}\n`;
|
|
69
72
|
}
|
|
70
|
-
return `${existing.slice(0, start)}${wrapped}${existing.slice(end +
|
|
73
|
+
return `${existing.slice(0, start)}${wrapped}${existing.slice(end + endMarker.length)}`;
|
|
71
74
|
};
|
|
72
75
|
exports.replaceMarkedBlock = replaceMarkedBlock;
|
|
76
|
+
/**
|
|
77
|
+
* Takes the block back out, so switching a generated block off in the config removes it instead of
|
|
78
|
+
* leaving it behind — `sync`'s file-level pruning cannot reach inside a file the repo also owns.
|
|
79
|
+
*/
|
|
80
|
+
const removeMarkedBlock = (options) => {
|
|
81
|
+
const { existing, startMarker, endMarker } = options;
|
|
82
|
+
const start = existing.indexOf(startMarker);
|
|
83
|
+
const end = existing.indexOf(endMarker);
|
|
84
|
+
if (start === -1 || end === -1 || end < start)
|
|
85
|
+
return existing;
|
|
86
|
+
const kept = `${existing.slice(0, start).trimEnd()}\n${existing.slice(end + endMarker.length).trimStart()}`;
|
|
87
|
+
return kept.trim().length > 0 ? kept : '';
|
|
88
|
+
};
|
|
89
|
+
exports.removeMarkedBlock = removeMarkedBlock;
|
|
73
90
|
//# sourceMappingURL=render.js.map
|
package/src/lib/render.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/render.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,33 +1,11 @@
|
|
|
1
1
|
import { EmitContext, EmittedFile } from './shared';
|
|
2
2
|
export declare const CLAUDE_SETTINGS_FILE = ".claude/settings.json";
|
|
3
|
-
type HookDefinition = {
|
|
4
|
-
event: string;
|
|
5
|
-
file: string;
|
|
6
|
-
timeout: number;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Hooks a repo can opt into via the config's `hooks` array. Hooks run arbitrary commands on the
|
|
10
|
-
* developer's machine, so unlike rules and skills they are never emitted by default.
|
|
11
|
-
*/
|
|
12
|
-
export declare const CLAUDE_HOOKS: Record<string, HookDefinition>;
|
|
13
|
-
export declare const assertKnownHooks: (hooks: string[]) => void;
|
|
14
|
-
/**
|
|
15
|
-
* Rewrites the generated entries in `.claude/settings.json` declaratively: every entry pointing
|
|
16
|
-
* into `.claude/hooks/ethlete/` is dropped and the currently enabled hooks are re-added, so
|
|
17
|
-
* disabling a hook in the config also unregisters it. Everything else in the file is untouched.
|
|
18
|
-
*/
|
|
19
|
-
export declare const mergeClaudeSettings: (options: {
|
|
20
|
-
existing: string;
|
|
21
|
-
hooks: string[];
|
|
22
|
-
}) => string;
|
|
23
3
|
/**
|
|
24
4
|
* The hook scripts plus the settings registration. Runs even when the claude target is off so a
|
|
25
|
-
* repo that drops the target also gets its stale registrations removed
|
|
26
|
-
* only planned when its parsed content actually changes, and an unparseable file is left alone.
|
|
5
|
+
* repo that drops the target also gets its stale registrations removed.
|
|
27
6
|
*/
|
|
28
7
|
export declare const emitClaudeHooks: (options: {
|
|
29
8
|
context: EmitContext;
|
|
30
9
|
claudeTarget: boolean;
|
|
31
10
|
existingSettings: string;
|
|
32
11
|
}) => EmittedFile[];
|
|
33
|
-
export {};
|
|
@@ -1,97 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.emitClaudeHooks = exports.
|
|
4
|
-
const
|
|
5
|
-
const path_1 = require("path");
|
|
6
|
-
const load_content_1 = require("../load-content");
|
|
3
|
+
exports.emitClaudeHooks = exports.CLAUDE_SETTINGS_FILE = void 0;
|
|
4
|
+
const hooks_shared_1 = require("./hooks-shared");
|
|
7
5
|
exports.CLAUDE_SETTINGS_FILE = '.claude/settings.json';
|
|
8
6
|
const HOOKS_DIR = '.claude/hooks/ethlete';
|
|
9
|
-
|
|
10
|
-
* Hooks a repo can opt into via the config's `hooks` array. Hooks run arbitrary commands on the
|
|
11
|
-
* developer's machine, so unlike rules and skills they are never emitted by default.
|
|
12
|
-
*/
|
|
13
|
-
exports.CLAUDE_HOOKS = {
|
|
14
|
-
'context-warning': { event: 'UserPromptSubmit', file: 'context-warning.py', timeout: 10 },
|
|
15
|
-
};
|
|
16
|
-
const assertKnownHooks = (hooks) => {
|
|
17
|
-
const unknown = hooks.filter((name) => !(name in exports.CLAUDE_HOOKS));
|
|
18
|
-
if (unknown.length > 0) {
|
|
19
|
-
throw new Error(`Unknown hook(s): ${unknown.join(', ')}. Known hooks: ${Object.keys(exports.CLAUDE_HOOKS).join(', ')}.`);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
exports.assertKnownHooks = assertKnownHooks;
|
|
23
|
-
const commandFor = (file) => `python3 "$CLAUDE_PROJECT_DIR/${HOOKS_DIR}/${file}"`;
|
|
24
|
-
/** `#` comment instead of the HTML banner, placed after the shebang so the file stays runnable. */
|
|
25
|
-
const withBanner = (raw, version) => {
|
|
26
|
-
var _a;
|
|
27
|
-
const banner = `# Generated by @ethlete/agent-rules v${version} — DO NOT EDIT. Run \`npx ethlete-agents sync\`.`;
|
|
28
|
-
const lines = raw.split('\n');
|
|
29
|
-
if ((_a = lines[0]) === null || _a === void 0 ? void 0 : _a.startsWith('#!'))
|
|
30
|
-
return [lines[0], banner, ...lines.slice(1)].join('\n');
|
|
31
|
-
return `${banner}\n${raw}`;
|
|
32
|
-
};
|
|
33
|
-
const isGenerated = (hook) => { var _a; return ((_a = hook.command) !== null && _a !== void 0 ? _a : '').includes(HOOKS_DIR); };
|
|
34
|
-
/**
|
|
35
|
-
* Rewrites the generated entries in `.claude/settings.json` declaratively: every entry pointing
|
|
36
|
-
* into `.claude/hooks/ethlete/` is dropped and the currently enabled hooks are re-added, so
|
|
37
|
-
* disabling a hook in the config also unregisters it. Everything else in the file is untouched.
|
|
38
|
-
*/
|
|
39
|
-
const mergeClaudeSettings = (options) => {
|
|
40
|
-
var _a, _b;
|
|
41
|
-
const { existing, hooks } = options;
|
|
42
|
-
const settings = JSON.parse(existing.trim() || '{}');
|
|
43
|
-
const events = Object.assign({}, ((_a = settings.hooks) !== null && _a !== void 0 ? _a : {}));
|
|
44
|
-
for (const [event, groups] of Object.entries(events)) {
|
|
45
|
-
const kept = groups
|
|
46
|
-
.map((group) => { var _a; return (Object.assign(Object.assign({}, group), { hooks: ((_a = group.hooks) !== null && _a !== void 0 ? _a : []).filter((hook) => !isGenerated(hook)) })); })
|
|
47
|
-
.filter((group) => group.hooks.length > 0);
|
|
48
|
-
if (kept.length > 0)
|
|
49
|
-
events[event] = kept;
|
|
50
|
-
else
|
|
51
|
-
delete events[event];
|
|
52
|
-
}
|
|
53
|
-
for (const name of hooks) {
|
|
54
|
-
const definition = exports.CLAUDE_HOOKS[name];
|
|
55
|
-
if (!definition)
|
|
56
|
-
continue;
|
|
57
|
-
events[definition.event] = [
|
|
58
|
-
...((_b = events[definition.event]) !== null && _b !== void 0 ? _b : []),
|
|
59
|
-
{ hooks: [{ type: 'command', command: commandFor(definition.file), timeout: definition.timeout }] },
|
|
60
|
-
];
|
|
61
|
-
}
|
|
62
|
-
if (Object.keys(events).length > 0)
|
|
63
|
-
settings.hooks = events;
|
|
64
|
-
else
|
|
65
|
-
delete settings.hooks;
|
|
66
|
-
return `${JSON.stringify(settings, null, 2)}\n`;
|
|
67
|
-
};
|
|
68
|
-
exports.mergeClaudeSettings = mergeClaudeSettings;
|
|
7
|
+
const commandFor = (file) => `python3 "$CLAUDE_PROJECT_DIR/${HOOKS_DIR}/${file}" --agent claude`;
|
|
69
8
|
/**
|
|
70
9
|
* The hook scripts plus the settings registration. Runs even when the claude target is off so a
|
|
71
|
-
* repo that drops the target also gets its stale registrations removed
|
|
72
|
-
* only planned when its parsed content actually changes, and an unparseable file is left alone.
|
|
10
|
+
* repo that drops the target also gets its stale registrations removed.
|
|
73
11
|
*/
|
|
74
12
|
const emitClaudeHooks = (options) => {
|
|
75
13
|
const { context, claudeTarget, existingSettings } = options;
|
|
76
14
|
const hooks = claudeTarget ? context.hooks : [];
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
files.push({ path: exports.CLAUDE_SETTINGS_FILE, contents: merged });
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
catch (_a) {
|
|
92
|
-
// Unparseable settings.json — never clobber a file the repo owns.
|
|
93
|
-
}
|
|
94
|
-
return files;
|
|
15
|
+
return [
|
|
16
|
+
...(0, hooks_shared_1.emitHookScripts)({ hooks, hooksDir: HOOKS_DIR, version: context.version }),
|
|
17
|
+
...(0, hooks_shared_1.emitHookSettings)({
|
|
18
|
+
path: exports.CLAUDE_SETTINGS_FILE,
|
|
19
|
+
existing: existingSettings,
|
|
20
|
+
hooks,
|
|
21
|
+
hooksDir: HOOKS_DIR,
|
|
22
|
+
commandFor,
|
|
23
|
+
createWhenEmpty: true,
|
|
24
|
+
}),
|
|
25
|
+
];
|
|
95
26
|
};
|
|
96
27
|
exports.emitClaudeHooks = emitClaudeHooks;
|
|
97
28
|
//# sourceMappingURL=claude-hooks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-hooks.js","sourceRoot":"","sources":["../../../../../../libs/agent-rules/src/lib/targets/claude-hooks.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"claude-hooks.js","sourceRoot":"","sources":["../../../../../../libs/agent-rules/src/lib/targets/claude-hooks.ts"],"names":[],"mappings":";;;AACA,iDAAmE;AAEtD,QAAA,oBAAoB,GAAG,uBAAuB,CAAC;AAE5D,MAAM,SAAS,GAAG,uBAAuB,CAAC;AAE1C,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,gCAAgC,SAAS,IAAI,IAAI,kBAAkB,CAAC;AAEzG;;;GAGG;AACI,MAAM,eAAe,GAAG,CAAC,OAI/B,EAAiB,EAAE;IAClB,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC;IAC5D,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhD,OAAO;QACL,GAAG,IAAA,8BAAe,EAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;QAC5E,GAAG,IAAA,+BAAgB,EAAC;YAClB,IAAI,EAAE,4BAAoB;YAC1B,QAAQ,EAAE,gBAAgB;YAC1B,KAAK;YACL,QAAQ,EAAE,SAAS;YACnB,UAAU;YACV,eAAe,EAAE,IAAI;SACtB,CAAC;KACH,CAAC;AACJ,CAAC,CAAC;AAnBW,QAAA,eAAe,mBAmB1B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { EmitContext, EmittedFile } from './shared';
|
|
2
|
+
export declare const CODEX_HOOKS_FILE = ".codex/hooks.json";
|
|
3
|
+
/**
|
|
4
|
+
* The hook scripts plus the `.codex/hooks.json` registration. Runs even when the codex target is
|
|
5
|
+
* off so a repo that drops the target also gets its stale registrations removed — but an absent
|
|
6
|
+
* file stays absent rather than being created empty.
|
|
7
|
+
*/
|
|
8
|
+
export declare const emitCodexHooks: (options: {
|
|
9
|
+
context: EmitContext;
|
|
10
|
+
codexTarget: boolean;
|
|
11
|
+
existingHooks: string;
|
|
12
|
+
}) => EmittedFile[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.emitCodexHooks = exports.CODEX_HOOKS_FILE = void 0;
|
|
4
|
+
const hooks_shared_1 = require("./hooks-shared");
|
|
5
|
+
exports.CODEX_HOOKS_FILE = '.codex/hooks.json';
|
|
6
|
+
const HOOKS_DIR = '.codex/hooks/ethlete';
|
|
7
|
+
/**
|
|
8
|
+
* Codex exposes no project-dir variable, so the path is resolved the way Codex's own hook docs
|
|
9
|
+
* resolve it — the command string is evaluated by a shell.
|
|
10
|
+
*/
|
|
11
|
+
const commandFor = (file) => `python3 "$(git rev-parse --show-toplevel)/${HOOKS_DIR}/${file}" --agent codex`;
|
|
12
|
+
/**
|
|
13
|
+
* The hook scripts plus the `.codex/hooks.json` registration. Runs even when the codex target is
|
|
14
|
+
* off so a repo that drops the target also gets its stale registrations removed — but an absent
|
|
15
|
+
* file stays absent rather than being created empty.
|
|
16
|
+
*/
|
|
17
|
+
const emitCodexHooks = (options) => {
|
|
18
|
+
const { context, codexTarget, existingHooks } = options;
|
|
19
|
+
const hooks = codexTarget ? context.hooks : [];
|
|
20
|
+
return [
|
|
21
|
+
...(0, hooks_shared_1.emitHookScripts)({ hooks, hooksDir: HOOKS_DIR, version: context.version }),
|
|
22
|
+
...(0, hooks_shared_1.emitHookSettings)({
|
|
23
|
+
path: exports.CODEX_HOOKS_FILE,
|
|
24
|
+
existing: existingHooks,
|
|
25
|
+
hooks,
|
|
26
|
+
hooksDir: HOOKS_DIR,
|
|
27
|
+
commandFor,
|
|
28
|
+
createWhenEmpty: false,
|
|
29
|
+
}),
|
|
30
|
+
];
|
|
31
|
+
};
|
|
32
|
+
exports.emitCodexHooks = emitCodexHooks;
|
|
33
|
+
//# sourceMappingURL=codex-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-hooks.js","sourceRoot":"","sources":["../../../../../../libs/agent-rules/src/lib/targets/codex-hooks.ts"],"names":[],"mappings":";;;AACA,iDAAmE;AAEtD,QAAA,gBAAgB,GAAG,mBAAmB,CAAC;AAEpD,MAAM,SAAS,GAAG,sBAAsB,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,6CAA6C,SAAS,IAAI,IAAI,iBAAiB,CAAC;AAErH;;;;GAIG;AACI,MAAM,cAAc,GAAG,CAAC,OAI9B,EAAiB,EAAE;IAClB,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IACxD,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAE/C,OAAO;QACL,GAAG,IAAA,8BAAe,EAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;QAC5E,GAAG,IAAA,+BAAgB,EAAC;YAClB,IAAI,EAAE,wBAAgB;YACtB,QAAQ,EAAE,aAAa;YACvB,KAAK;YACL,QAAQ,EAAE,SAAS;YACnB,UAAU;YACV,eAAe,EAAE,KAAK;SACvB,CAAC;KACH,CAAC;AACJ,CAAC,CAAC;AAnBW,QAAA,cAAc,kBAmBzB"}
|