@ryuenn3123/agentic-senior-core 6.4.0 → 6.4.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.
package/README.md
CHANGED
|
@@ -111,6 +111,20 @@ If you need to override these defaults (e.g., to whitelist a specific dependency
|
|
|
111
111
|
ASC provides powerful commands to steer your agents (e.g. `/asc-refactor`, `/asc-audit`).
|
|
112
112
|
It also provides a CLI to manage your local setup (e.g. `asc adapter --all`, `asc global --all`).
|
|
113
113
|
|
|
114
|
+
### Git Pre-Commit Hook
|
|
115
|
+
|
|
116
|
+
ASC automatically installs a native Git pre-commit hook when you run `asc adapter`. This hook runs via Git's own hook system — independent of any AI host's plugin runtime — so it works on **every** host, including adapter-only hosts (Cursor, Cline, Copilot IDE extension, etc.) and hosts where agent lifecycle hooks are unreliable.
|
|
117
|
+
|
|
118
|
+
The hook:
|
|
119
|
+
- Runs `jscpd` on directories containing staged files, using policy from `.asc/dedup-config.json`
|
|
120
|
+
- Auto-fixes ESLint issues (including `no-confusing-void-expression`) and re-stages, if the target project has a typed ESLint config
|
|
121
|
+
- Blocks the commit if a staged file duplicates existing code, with a clear message citing the match
|
|
122
|
+
- Bypass with `git commit --no-verify` when duplication is intentional
|
|
123
|
+
|
|
124
|
+
Supports both `.husky/` (appends without overwriting) and `.git/hooks/` (direct install). Remove with `asc uninstall`. To install the hook standalone without generating adapter files: `asc install-git-hook`.
|
|
125
|
+
|
|
126
|
+
> **Known limitation — Antigravity IDE hooks**: Agent lifecycle hooks (`hooks.json`) are documented but do not execute on Antigravity IDE's chat surface as of August 2026. The git pre-commit hook is the recommended primary enforcement mechanism for Antigravity users.
|
|
127
|
+
|
|
114
128
|
**[See all available CLI Options and Agent Commands](docs/INSTALLATION.md#commands--cli)**
|
|
115
129
|
|
|
116
130
|
---
|
package/gemini-extension.json
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
3
4
|
import { compileAndSaveValidator } from '../../core/rule-compiler.mjs';
|
|
4
5
|
|
|
6
|
+
// Single source of truth: import extension list from constants.cjs
|
|
7
|
+
const require_ = createRequire(import.meta.url);
|
|
8
|
+
const { SOURCE_EXTENSIONS } = require_('../../../.agents/plugins/agentic-senior-core/hooks/constants.cjs');
|
|
9
|
+
|
|
5
10
|
export const ASC_HOOK_HEADER = '# Agentic Senior Core Git Pre-Commit Hook';
|
|
6
11
|
export const ASC_HOOK_RUNNER_REL_PATH = path.join('.asc', 'hooks', 'pre-commit-runner.cjs').replace(/\\/g, '/');
|
|
7
12
|
|
|
8
13
|
export function generatePreCommitRunnerScript() {
|
|
14
|
+
// Serialize SOURCE_EXTENSIONS from constants.cjs into the generated script
|
|
15
|
+
const extensionsList = Array.from(SOURCE_EXTENSIONS).map(e => `'${e}'`).join(', ');
|
|
16
|
+
|
|
9
17
|
return `#!/usr/bin/env node
|
|
10
18
|
// # Agentic Senior Core -- Git Pre-Commit Dedup & Quality Gate
|
|
11
19
|
// Auto-generated by Agentic Senior Core (ASC). DO NOT EDIT DIRECTLY.
|
|
@@ -15,10 +23,7 @@ const path = require('path');
|
|
|
15
23
|
const os = require('os');
|
|
16
24
|
const { execSync } = require('child_process');
|
|
17
25
|
|
|
18
|
-
const SOURCE_EXTENSIONS = new Set([
|
|
19
|
-
'js', 'ts', 'mjs', 'cjs', 'jsx', 'tsx',
|
|
20
|
-
'py', 'rb', 'go', 'rs', 'java', 'kt', 'swift', 'cs',
|
|
21
|
-
]);
|
|
26
|
+
const SOURCE_EXTENSIONS = new Set([${extensionsList}]);
|
|
22
27
|
|
|
23
28
|
const JSCPD_TIMEOUT_MS = 10000;
|
|
24
29
|
|
|
@@ -219,10 +219,115 @@ async function installAntigravityIde(target) {
|
|
|
219
219
|
await fs.mkdir(path.dirname(cliTargetPath), { recursive: true });
|
|
220
220
|
await copyDirRecursive(pluginSource, cliTargetPath, ['.codex-plugin', '.app.json']);
|
|
221
221
|
|
|
222
|
-
|
|
222
|
+
// Antigravity CLI enforces strict plugin.json schema (additionalProperties: false).
|
|
223
|
+
// Only name, description, $schema are valid. Extra fields (version, rules, skills, hooks)
|
|
224
|
+
// cause the CLI to reject the entire plugin — hooks.json never loads.
|
|
225
|
+
// Overwrite CLI copy with minimal manifest; IDE copy keeps the full one.
|
|
226
|
+
const cliManifest = {
|
|
227
|
+
$schema: 'https://antigravity.google/schemas/v1/plugin.json',
|
|
228
|
+
name: 'agentic-senior-core',
|
|
229
|
+
description: 'Universal AI coding rules. Write code like a staff engineer.',
|
|
230
|
+
};
|
|
231
|
+
await fs.writeFile(
|
|
232
|
+
path.join(cliTargetPath, 'plugin.json'),
|
|
233
|
+
JSON.stringify(cliManifest, null, 2) + '\n',
|
|
234
|
+
'utf8'
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
// Antigravity CLI also uses a different hooks.json schema:
|
|
238
|
+
// IDE format: { "hooks": { "PreToolUse": [...] } }
|
|
239
|
+
// CLI format: { "hook-name": { "PreToolUse": [...] } }
|
|
240
|
+
// Convert and add CLI plugin path to command fallback chains.
|
|
241
|
+
await convertHooksForCli(cliTargetPath);
|
|
242
|
+
|
|
243
|
+
console.log(` ${target.label}: ${pluginTargetPath} + ${cliTargetPath} ... OK`);
|
|
223
244
|
return true;
|
|
224
245
|
}
|
|
225
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Convert IDE-format hooks.json to Antigravity CLI format.
|
|
249
|
+
* IDE wraps everything under a "hooks" key; CLI uses named hook keys.
|
|
250
|
+
* Also strips commandWindows (not used on Linux/WSL) and patches
|
|
251
|
+
* command fallback chains to include the CLI plugin path.
|
|
252
|
+
*/
|
|
253
|
+
async function convertHooksForCli(cliPluginDir) {
|
|
254
|
+
const hooksPath = path.join(cliPluginDir, 'hooks.json');
|
|
255
|
+
if (!(await pathExists(hooksPath))) return;
|
|
256
|
+
|
|
257
|
+
const raw = JSON.parse(await fs.readFile(hooksPath, 'utf8'));
|
|
258
|
+
const ideHooks = raw.hooks || raw;
|
|
259
|
+
|
|
260
|
+
// CLI path for the hook script fallback chain
|
|
261
|
+
const cliHooksBase = path.join(HOME, '.gemini', 'antigravity-cli', 'plugins', 'agentic-senior-core', 'hooks');
|
|
262
|
+
|
|
263
|
+
const cliHooks = {};
|
|
264
|
+
let hookIndex = 0;
|
|
265
|
+
|
|
266
|
+
for (const [eventName, eventEntries] of Object.entries(ideHooks)) {
|
|
267
|
+
const entries = Array.isArray(eventEntries) ? eventEntries : [eventEntries];
|
|
268
|
+
|
|
269
|
+
for (const entry of entries) {
|
|
270
|
+
hookIndex++;
|
|
271
|
+
const hookName = `asc-${eventName.toLowerCase()}-${hookIndex}`;
|
|
272
|
+
|
|
273
|
+
// Entry might be a hook config directly or a matcher+hooks wrapper
|
|
274
|
+
const hookItems = entry.hooks || [entry];
|
|
275
|
+
const convertedItems = hookItems.map(item => {
|
|
276
|
+
const converted = { type: item.type || 'command', timeout: item.timeout || 10 };
|
|
277
|
+
if (item.statusMessage) {
|
|
278
|
+
converted.statusMessage = item.statusMessage;
|
|
279
|
+
}
|
|
280
|
+
// Patch command to include CLI plugin path in fallback chain
|
|
281
|
+
if (item.command) {
|
|
282
|
+
converted.command = patchCommandForCliPath(item.command, cliHooksBase);
|
|
283
|
+
}
|
|
284
|
+
return converted;
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
const cliEntry = { [eventName]: [{ hooks: convertedItems }] };
|
|
288
|
+
if (entry.matcher) {
|
|
289
|
+
cliEntry[eventName][0].matcher = entry.matcher;
|
|
290
|
+
}
|
|
291
|
+
if (entry.if) {
|
|
292
|
+
cliEntry[eventName][0].if = entry.if;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
cliHooks[hookName] = cliEntry;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
await fs.writeFile(hooksPath, JSON.stringify(cliHooks, null, 2) + '\n', 'utf8');
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Add ~/.gemini/antigravity-cli/plugins/agentic-senior-core/hooks/ to the
|
|
304
|
+
* require() fallback chain in hook commands. The original commands only check
|
|
305
|
+
* local .agents/, ~/.agents/, and ~/.gemini/config/ paths — CLI path is missing.
|
|
306
|
+
*/
|
|
307
|
+
function patchCommandForCliPath(command, cliHooksBase) {
|
|
308
|
+
// The hook commands use a pattern like:
|
|
309
|
+
// const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','<script>');
|
|
310
|
+
// require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:g2));
|
|
311
|
+
//
|
|
312
|
+
// Add g3 for CLI path after g2:
|
|
313
|
+
const g2Pattern = /const g2=p\.join\(os\.homedir\(\),'\.gemini','config','plugins','agentic-senior-core','hooks','([^']+)'\);/;
|
|
314
|
+
const match = command.match(g2Pattern);
|
|
315
|
+
if (!match) return command;
|
|
316
|
+
|
|
317
|
+
const scriptName = match[1];
|
|
318
|
+
const cliPathNormalized = cliHooksBase.replace(/\\/g, '/');
|
|
319
|
+
|
|
320
|
+
// Add g3 variable and update require chain
|
|
321
|
+
const g3Def = `const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','${scriptName}');`;
|
|
322
|
+
const patched = command
|
|
323
|
+
.replace(
|
|
324
|
+
`require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:g2));`,
|
|
325
|
+
`${g3Def}require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));`
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
return patched;
|
|
329
|
+
}
|
|
330
|
+
|
|
226
331
|
async function installGlobalTarget(targetKey) {
|
|
227
332
|
const target = GLOBAL_TARGETS[targetKey];
|
|
228
333
|
|
package/package.json
CHANGED
package/plugin.yaml
CHANGED