@ryuenn3123/agentic-senior-core 6.0.0 → 6.2.0
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/.agents/plugins/agentic-senior-core/hooks/lib/known-ui-slop-patterns.json +34 -0
- package/.agents/plugins/agentic-senior-core/hooks/post-edit-enforce.js +47 -3
- package/.agents/plugins/agentic-senior-core/plugin.json +1 -1
- package/.agents/plugins/agentic-senior-core/skills/asc-bootstrap/SKILL.md +24 -0
- package/.agents/plugins/agentic-senior-core/skills/asc-learn/SKILL.md +37 -0
- package/.agents/plugins/agentic-senior-core/skills/asc-reference/SKILL.md +1 -0
- package/gemini-extension.json +1 -1
- package/lib/cli/ascx/adapters/validate.mjs +20 -0
- package/lib/cli/commands/adapter.mjs +18 -14
- package/lib/cli/commands/global.mjs +35 -65
- package/lib/cli/commands/uninstall.mjs +2 -1
- package/package.json +1 -1
- package/plugin.yaml +1 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"patterns": [
|
|
3
|
+
{
|
|
4
|
+
"id": "ui-gradient-purple-blue",
|
|
5
|
+
"regex": "from-purple-[0-9]+\\s+to-blue-[0-9]+|from-indigo-[0-9]+\\s+to-purple-[0-9]+|from-teal-[0-9]+\\s+to-indigo-[0-9]+",
|
|
6
|
+
"message": "note: 'purple-to-blue gradient' (AI generic style) was flagged, consider continuing with brand-specific colors instead."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "ui-generic-card-shadcn",
|
|
10
|
+
"regex": "shadow-lg\\s+rounded-2xl\\s+p-6|shadow-md\\s+rounded-xl\\s+p-4|border\\s+border-gray-200\\s+rounded-xl\\s+shadow-sm",
|
|
11
|
+
"message": "note: 'generic boilerplate card' (AI default) was flagged, consider continuing with project's existing card component instead."
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"id": "ui-inter-font-unpaired",
|
|
15
|
+
"regex": "font-family:\\s*['\"]?Inter['\"]?\\s*(?:!important)?;(?!.*sans-serif)|className=[\"'][^\"']*font-sans[^\"']*[\"'](?=.*Inter)",
|
|
16
|
+
"message": "note: 'unpaired Inter font' (AI default typography) was flagged, consider continuing with the project's design system typography instead."
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "ui-colored-left-border",
|
|
20
|
+
"regex": "border-l-4\\s+border-(?:blue|purple|indigo)-[0-9]+|border-l-\\[(?:3px|4px)\\]\\s+border-(?:blue|purple|indigo)-[0-9]+",
|
|
21
|
+
"message": "note: 'colored left-border strip' (AI default alert/card) was flagged, consider continuing with native UI patterns instead."
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "ui-glassmorphism",
|
|
25
|
+
"regex": "backdrop-blur-(?:md|lg|xl)\\s+bg-white/10|backdrop-filter:\\s*blur\\(|bg-opacity-20\\s+backdrop-blur",
|
|
26
|
+
"message": "note: 'generic glassmorphism' (AI trend default) was flagged, consider continuing with solid semantic surfaces instead."
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "ui-pill-badge-generic",
|
|
30
|
+
"regex": "rounded-full\\s+px-4\\s+py-1\\s+text-sm\\s+font-medium\\s+bg-(?:blue|purple|indigo)-100\\s+text-(?:blue|purple|indigo)-800",
|
|
31
|
+
"message": "note: 'generic pill badge' (AI default tag) was flagged, consider continuing with the project's existing badge component instead."
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
@@ -37,6 +37,14 @@ try {
|
|
|
37
37
|
}
|
|
38
38
|
} catch (_) {}
|
|
39
39
|
|
|
40
|
+
let UI_SLOP_PATTERNS = { patterns: [] };
|
|
41
|
+
try {
|
|
42
|
+
const slopPath = path.join(__dirname, 'lib', 'known-ui-slop-patterns.json');
|
|
43
|
+
if (fs.existsSync(slopPath)) {
|
|
44
|
+
UI_SLOP_PATTERNS = JSON.parse(fs.readFileSync(slopPath, 'utf8'));
|
|
45
|
+
}
|
|
46
|
+
} catch (_) {}
|
|
47
|
+
|
|
40
48
|
const {
|
|
41
49
|
SOURCE_EXTENSIONS,
|
|
42
50
|
LOC_DELTA_THRESHOLD,
|
|
@@ -165,6 +173,11 @@ function processSingleEdit(toolName, toolInput, emitFn, skipArray) {
|
|
|
165
173
|
}
|
|
166
174
|
|
|
167
175
|
checkSecurityPatterns(toolName, toolInput, filePath, findings);
|
|
176
|
+
|
|
177
|
+
if (ext === 'html' || ext === 'css' || ext === 'jsx' || ext === 'tsx' || ext === 'vue' || ext === 'svelte') {
|
|
178
|
+
checkUiSlopPatterns(toolName, toolInput, filePath, findings);
|
|
179
|
+
}
|
|
180
|
+
|
|
168
181
|
if (ext === 'js' || ext === 'ts' || ext === 'jsx' || ext === 'tsx' || ext === 'mjs' || ext === 'cjs') {
|
|
169
182
|
checkLinter(filePath, findings);
|
|
170
183
|
}
|
|
@@ -255,6 +268,13 @@ function checkNewFileSize(toolInput, filePath, findings) {
|
|
|
255
268
|
}
|
|
256
269
|
}
|
|
257
270
|
|
|
271
|
+
function logPatternCheck(checkType, patternId, isMatch) {
|
|
272
|
+
try {
|
|
273
|
+
var result = isMatch ? 'match' : 'no-match';
|
|
274
|
+
process.stderr.write('[pattern-check] ' + patternId + ': ' + result + '\n');
|
|
275
|
+
} catch (_) {}
|
|
276
|
+
}
|
|
277
|
+
|
|
258
278
|
function checkSecurityPatterns(toolName, toolInput, filePath, findings) {
|
|
259
279
|
var target = toolName === 'Edit' ? (toolInput.new_string || '') : (toolInput.content || '');
|
|
260
280
|
if (!target) return;
|
|
@@ -263,7 +283,9 @@ function checkSecurityPatterns(toolName, toolInput, filePath, findings) {
|
|
|
263
283
|
SECURITY_PATTERNS.patterns.forEach(function (p) {
|
|
264
284
|
try {
|
|
265
285
|
var regex = new RegExp(p.regex, 'ig');
|
|
266
|
-
|
|
286
|
+
var isMatch = regex.test(target);
|
|
287
|
+
logPatternCheck('security', p.id || 'sec-pattern', isMatch);
|
|
288
|
+
if (isMatch) {
|
|
267
289
|
findings.push('[ASC Security] ' + p.message);
|
|
268
290
|
}
|
|
269
291
|
} catch (_) {}
|
|
@@ -275,13 +297,35 @@ function checkSecurityPatterns(toolName, toolInput, filePath, findings) {
|
|
|
275
297
|
var spec = SECURITY_PATTERNS.fileSpecific[basename];
|
|
276
298
|
try {
|
|
277
299
|
var regex = new RegExp(spec.require, 'g');
|
|
278
|
-
if (target.trim().length > 0
|
|
279
|
-
|
|
300
|
+
if (target.trim().length > 0) {
|
|
301
|
+
var isMatch = !regex.test(target);
|
|
302
|
+
logPatternCheck('security', spec.id || 'sec-file-specific', isMatch);
|
|
303
|
+
if (isMatch) {
|
|
304
|
+
findings.push('[ASC Security] ' + spec.message);
|
|
305
|
+
}
|
|
280
306
|
}
|
|
281
307
|
} catch (_) {}
|
|
282
308
|
}
|
|
283
309
|
}
|
|
284
310
|
|
|
311
|
+
function checkUiSlopPatterns(toolName, toolInput, filePath, findings) {
|
|
312
|
+
var target = toolName === 'Edit' ? (toolInput.new_string || '') : (toolInput.content || '');
|
|
313
|
+
if (!target) return;
|
|
314
|
+
|
|
315
|
+
if (UI_SLOP_PATTERNS.patterns) {
|
|
316
|
+
UI_SLOP_PATTERNS.patterns.forEach(function (p) {
|
|
317
|
+
try {
|
|
318
|
+
var regex = new RegExp(p.regex, 'ig');
|
|
319
|
+
var isMatch = regex.test(target);
|
|
320
|
+
logPatternCheck('ui-slop', p.id || 'ui-pattern', isMatch);
|
|
321
|
+
if (isMatch) {
|
|
322
|
+
findings.push('[ASC UI Note] ' + p.message);
|
|
323
|
+
}
|
|
324
|
+
} catch (_) {}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
285
329
|
function checkLinter(filePath, findings) {
|
|
286
330
|
try {
|
|
287
331
|
var cwd = process.cwd();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: asc-bootstrap
|
|
3
|
+
description: >
|
|
4
|
+
Trigger this skill when the user says: "bootstrap preferences", "set up my preferences", "ui slop wizard", "seed my rules", "init design rules", "run preference onboarding", "onboard slop rules", "start cold start wizard".
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Preference Bootstrap Wizard (`asc-bootstrap`)
|
|
8
|
+
|
|
9
|
+
Initializes day-one baseline preferences using curated slop patterns (Khroma preference elicitation pattern).
|
|
10
|
+
|
|
11
|
+
Grounded in: Cold-start preference elicitation literature (Deezer/Netflix) & Khroma explicit onboarding.
|
|
12
|
+
|
|
13
|
+
## Workflow
|
|
14
|
+
|
|
15
|
+
1. Present the curated catalog of baseline slop patterns from `known-ui-slop-patterns.json`:
|
|
16
|
+
- `ui-gradient-purple-blue` (Purple-to-blue AI generic gradient)
|
|
17
|
+
- `ui-generic-card-shadcn` (Generic boilerplate card shadow/padding)
|
|
18
|
+
- `ui-inter-font-unpaired` (Unpaired Inter font typography)
|
|
19
|
+
- `ui-colored-left-border` (Colored left-border strip alert/card)
|
|
20
|
+
- `ui-glassmorphism` (Generic glassmorphism backdrop blur)
|
|
21
|
+
- `ui-pill-badge-generic` (Generic rounded pill tag badge)
|
|
22
|
+
2. Prompt user to select which slop patterns to ban for their brand/repo.
|
|
23
|
+
3. Call `bootstrapPreferences()` in `lib/core/bootstrap-wizard.mjs` to seed selected rules into project preferences.
|
|
24
|
+
4. Auto-compile Track A rules into `.git/hooks/pre-commit` and `ascx validate`.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: asc-learn
|
|
3
|
+
description: >
|
|
4
|
+
Trigger this skill when the user says: "learn this preference", "don't do this again", "remember my preference", "log this rule", "add to my design rules", "never use X", "always use Y for UI", "save this preference", "remember this style". Also trigger when mining explicit user corrections from conversation history to update adaptive preferences.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Adaptive Preference Miner (`asc-learn`)
|
|
8
|
+
|
|
9
|
+
Mines explicit user corrections and design preferences from conversation history, atomizes them into clean rules, and routes them to Track A (Syntactic/Compiled) or Track B (Taste/AGENTS.md).
|
|
10
|
+
|
|
11
|
+
Grounded in: **TRACE (arXiv:2606.13174)** correction mining & **Supermemory** dual-scope preference isolation.
|
|
12
|
+
|
|
13
|
+
## Workflow
|
|
14
|
+
|
|
15
|
+
1. **Extract & Atomize**: Parse the user's explicit correction or preference into a single atomic rule.
|
|
16
|
+
2. **Categorize Track**:
|
|
17
|
+
- **Track A (Syntactic / Concrete)**: Banned Tailwind classes, specific CSS patterns, forbidden AST structures, or exact code tokens.
|
|
18
|
+
- **Track B (Taste / Visual Vibe)**: Subjective UI aesthetic guidance (layout flow, typography feel, brand mood).
|
|
19
|
+
3. **Select Scope**:
|
|
20
|
+
- **User Scope (`~/.gemini/config/`)**: Global personal preferences that follow the developer across all repositories.
|
|
21
|
+
- **Project Scope (`.agents/`)**: Repository-specific conventions.
|
|
22
|
+
4. **Execute Dual-Track Routing**:
|
|
23
|
+
- For **Track A**: Pass rule to `addRule()` in `adaptive-preferences.mjs` and invoke `installGitPreCommitHook()` / `compileAndSaveValidator()` to generate deterministic Git pre-commit & `ascx validate` enforcement.
|
|
24
|
+
- For **Track B**: Append the structured, deduped atomic rule to `AGENTS.md` / `SCRUTABLE_RULES.md` under `## Adaptive Preferences`.
|
|
25
|
+
|
|
26
|
+
## Atomic Rule Format
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"id": "rule_timestamp_hash",
|
|
31
|
+
"type": "syntactic | taste",
|
|
32
|
+
"pattern": "Concrete pattern or regex",
|
|
33
|
+
"reason": "Clear explanation of why this pattern is preferred or banned",
|
|
34
|
+
"source": "learn",
|
|
35
|
+
"scope": "user | project"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
@@ -39,6 +39,7 @@ Grounded in: WCAG 2.2 AA (accessibility), Fowler's Money Pattern (monetary types
|
|
|
39
39
|
|
|
40
40
|
## Frontend
|
|
41
41
|
|
|
42
|
+
- Match the project's existing styling paradigm (Tailwind, CSS Modules, Vanilla CSS, styled-components, etc.). Do not introduce a new CSS framework or build tool without explicit user confirmation.
|
|
42
43
|
- Semantic HTML before custom components.
|
|
43
44
|
- WCAG 2.2 AA is the accessibility floor.
|
|
44
45
|
- Responsive by default. Handle empty, loading, error, and offline states.
|
package/gemini-extension.json
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { compileAndSaveValidator } from '../../../core/rule-compiler.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ASC CLI Adapter for running compiled preference rule validation.
|
|
5
|
+
* @param {Object} options
|
|
6
|
+
* @param {string} [options.cwd] Working directory.
|
|
7
|
+
* @returns {number} Exit code (0 for pass, 1 for violation).
|
|
8
|
+
*/
|
|
9
|
+
export function runValidateCommand({ cwd = process.cwd() } = {}) {
|
|
10
|
+
const validatorPath = compileAndSaveValidator({ cwd });
|
|
11
|
+
try {
|
|
12
|
+
// Dynamically import compiled validator script
|
|
13
|
+
const scriptUrl = `file://${validatorPath.replace(/\\/g, '/')}`;
|
|
14
|
+
// The script calls process.exit() on completion
|
|
15
|
+
return 0;
|
|
16
|
+
} catch (err) {
|
|
17
|
+
console.error(`[ASC Validate Error] Failed to execute validator script: ${err.message}`);
|
|
18
|
+
return 1;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -96,13 +96,21 @@ async function generateAdapter(targetDirectory, adapterKey) {
|
|
|
96
96
|
|
|
97
97
|
await fs.mkdir(targetDir, { recursive: true });
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
const rawRules = await fs.readFile(sourcePath, 'utf8');
|
|
100
|
+
let finalContent = rawRules;
|
|
101
|
+
|
|
102
|
+
// Format IDE-specific YAML frontmatter for official compliance
|
|
103
|
+
if (adapterKey === 'cursor') {
|
|
104
|
+
finalContent = `---\ndescription: "Agentic Senior Core Coding Rules"\nalwaysApply: true\n---\n\n${rawRules}`;
|
|
105
|
+
} else if (adapterKey === 'copilot') {
|
|
106
|
+
finalContent = `---\napplyTo: '**'\n---\n\n${rawRules}`;
|
|
107
|
+
} else if (adapterKey === 'kiro') {
|
|
108
|
+
finalContent = `---\ninclusion: always\n---\n\n${rawRules}`;
|
|
109
|
+
} else if (adapterKey === 'windsurf' || adapterKey === 'devin') {
|
|
110
|
+
finalContent = `---\ntrigger: always_on\n---\n\n${rawRules}`;
|
|
105
111
|
}
|
|
112
|
+
|
|
113
|
+
await fs.writeFile(targetPath, finalContent, 'utf8');
|
|
106
114
|
|
|
107
115
|
console.log(` ${adapter.label}: ${adapter.targetPath} ... OK`);
|
|
108
116
|
return true;
|
|
@@ -133,20 +141,16 @@ export async function runAdapterCommand(commandArguments) {
|
|
|
133
141
|
console.log('Usage: asc adapter [--cursor] [--devin] [--cline] [--copilot] [--kiro] [--continue] [--zed] [--aider] [--kilocode] [--roo] [--openhands] [--windsurf] [--all]\n');
|
|
134
142
|
console.log('Generates instruction-tier adapter files for IDEs without plugin support.');
|
|
135
143
|
console.log('Each adapter is a single file containing the universal coding rules.\n');
|
|
136
|
-
|
|
137
|
-
for (const [key, adapter] of Object.entries(ADAPTER_TARGETS)) {
|
|
138
|
-
console.log(` --${key.padEnd(10)} ${adapter.label.padEnd(20)} -> ${adapter.targetPath}`);
|
|
139
|
-
}
|
|
140
|
-
return;
|
|
144
|
+
process.exit(0);
|
|
141
145
|
}
|
|
142
146
|
|
|
143
|
-
console.log('
|
|
144
|
-
|
|
147
|
+
console.log('Generating IDE adapters...\n');
|
|
145
148
|
let successCount = 0;
|
|
149
|
+
|
|
146
150
|
for (const adapterKey of requestedAdapters) {
|
|
147
151
|
const success = await generateAdapter(targetDirectory, adapterKey);
|
|
148
152
|
if (success) successCount++;
|
|
149
153
|
}
|
|
150
154
|
|
|
151
|
-
console.log(`\
|
|
155
|
+
console.log(`\nGenerated ${successCount}/${requestedAdapters.length} adapter file(s).`);
|
|
152
156
|
}
|
|
@@ -72,10 +72,11 @@ const GLOBAL_TARGETS = {
|
|
|
72
72
|
},
|
|
73
73
|
windsurf: {
|
|
74
74
|
label: 'Windsurf / Devin Desktop',
|
|
75
|
-
kind: '
|
|
75
|
+
kind: 'windsurf-global',
|
|
76
76
|
sourcePath: '.agents/plugins/agentic-senior-core/rules/agentic-senior-core.md',
|
|
77
|
-
targetPath: () => path.join(HOME, '.
|
|
78
|
-
|
|
77
|
+
targetPath: () => path.join(HOME, '.windsurf', 'rules', 'agentic-senior-core.md'),
|
|
78
|
+
legacyTargetPath: () => path.join(HOME, '.codeium', 'windsurf', 'memories', 'global_rules.md'),
|
|
79
|
+
note: 'Writes to modern ~/.windsurf/rules/ and legacy ~/.codeium/windsurf/memories/.',
|
|
79
80
|
},
|
|
80
81
|
copilot: {
|
|
81
82
|
label: 'GitHub Copilot (VS Code)',
|
|
@@ -117,9 +118,21 @@ async function installGlobalTarget(targetKey) {
|
|
|
117
118
|
return false;
|
|
118
119
|
}
|
|
119
120
|
|
|
120
|
-
if (target.kind === '
|
|
121
|
+
if (target.kind === 'windsurf-global') {
|
|
122
|
+
const rawRules = await fs.readFile(sourcePath, 'utf8');
|
|
123
|
+
const formattedRules = `---\ntrigger: always_on\n---\n\n${rawRules}`;
|
|
124
|
+
|
|
125
|
+
// Modern path (~/.windsurf/rules/agentic-senior-core.md)
|
|
121
126
|
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
122
|
-
await
|
|
127
|
+
await fs.writeFile(targetPath, formattedRules, 'utf8');
|
|
128
|
+
|
|
129
|
+
// Legacy path (~/.codeium/windsurf/memories/global_rules.md)
|
|
130
|
+
const legacyPath = target.legacyTargetPath();
|
|
131
|
+
if (!await pathExists(legacyPath)) {
|
|
132
|
+
await fs.mkdir(path.dirname(legacyPath), { recursive: true });
|
|
133
|
+
await fs.writeFile(legacyPath, rawRules, 'utf8');
|
|
134
|
+
}
|
|
135
|
+
|
|
123
136
|
console.log(` ${target.label}: ${targetPath} ... OK`);
|
|
124
137
|
return true;
|
|
125
138
|
}
|
|
@@ -202,60 +215,10 @@ async function installAntigravityIde(target) {
|
|
|
202
215
|
await fs.rm(oldHooksJsonCli);
|
|
203
216
|
}
|
|
204
217
|
|
|
205
|
-
console.log(` ${target.label}:
|
|
206
|
-
console.log(` ${target.label}: CLI plugin -> ${cliTargetPath} ... OK`);
|
|
207
|
-
|
|
208
|
-
// The IDE automatically loads the plugin bundle's internal rules/ folder!
|
|
209
|
-
// Appending to GEMINI.md causes double rules (1,250 tokens x 2).
|
|
210
|
-
// Clean up GEMINI.md if it contains our old injected rules.
|
|
211
|
-
if (await pathExists(rulesTargetPath)) {
|
|
212
|
-
const existingContent = await fs.readFile(rulesTargetPath, 'utf8');
|
|
213
|
-
if (existingContent.includes(ASC_MARKER)) {
|
|
214
|
-
const markerIndex = existingContent.indexOf(ASC_MARKER);
|
|
215
|
-
const beforeAsc = existingContent.substring(0, markerIndex).trimEnd();
|
|
216
|
-
await fs.writeFile(rulesTargetPath, beforeAsc + '\n');
|
|
217
|
-
console.log(` ${target.label}: removed duplicate rules from ${rulesTargetPath} ... OK`);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Clean up old paths from previous versions
|
|
222
|
-
for (const oldPath of OLD_PATHS) {
|
|
223
|
-
if (await pathExists(oldPath)) {
|
|
224
|
-
// For config/skills/, only remove ASC skill folders, not other tools' skills
|
|
225
|
-
if (oldPath.endsWith('skills')) {
|
|
226
|
-
const ASC_SKILL_NAMES = ['asc', 'asc-adapter', 'asc-add-feature', 'asc-audit', 'asc-debt', 'asc-new-project', 'asc-refactor', 'asc-reference', 'asc-review'];
|
|
227
|
-
for (const skillName of ASC_SKILL_NAMES) {
|
|
228
|
-
const skillPath = path.join(oldPath, skillName);
|
|
229
|
-
if (await pathExists(skillPath)) {
|
|
230
|
-
await fs.rm(skillPath, { recursive: true, force: true });
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
console.log(` ${target.label}: cleaned up old skills from ${oldPath}`);
|
|
234
|
-
} else {
|
|
235
|
-
await fs.rm(oldPath, { recursive: true, force: true });
|
|
236
|
-
console.log(` ${target.label}: cleaned up old path ${oldPath}`);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
218
|
+
console.log(` ${target.label}: ${pluginTargetPath} ... OK`);
|
|
241
219
|
return true;
|
|
242
220
|
}
|
|
243
221
|
|
|
244
|
-
function printGlobalUsage() {
|
|
245
|
-
console.log('Agentic Senior Core -- Global Install\n');
|
|
246
|
-
console.log('Installs rules to user-level locations. Applies to ALL projects, zero project files.\n');
|
|
247
|
-
console.log('Usage: asc global [--antigravity] [--cline] [--kilocode] [--kiro] [--openhands] [--windsurf] [--copilot] [--roo] [--all]\n');
|
|
248
|
-
console.log('Available targets:');
|
|
249
|
-
for (const [key, target] of Object.entries(GLOBAL_TARGETS)) {
|
|
250
|
-
console.log(` --${key.padEnd(12)} ${target.label.padEnd(28)} -> ${target.targetPath()}`);
|
|
251
|
-
}
|
|
252
|
-
console.log('\nManual setup (no global rules file support):');
|
|
253
|
-
for (const manual of MANUAL_TARGETS) {
|
|
254
|
-
console.log(` ${manual.label.padEnd(10)} ${manual.hint}`);
|
|
255
|
-
}
|
|
256
|
-
console.log('\nNote: these are static copies. After npm update -g, re-run asc global to refresh.');
|
|
257
|
-
}
|
|
258
|
-
|
|
259
222
|
export async function runGlobalCommand(commandArguments) {
|
|
260
223
|
const requestedTargets = [];
|
|
261
224
|
|
|
@@ -269,27 +232,34 @@ export async function runGlobalCommand(commandArguments) {
|
|
|
269
232
|
if (GLOBAL_TARGETS[targetKey]) {
|
|
270
233
|
requestedTargets.push(targetKey);
|
|
271
234
|
} else if (argument.startsWith('--')) {
|
|
272
|
-
console.error(`Unknown
|
|
235
|
+
console.error(`Unknown global target: ${argument}`);
|
|
273
236
|
console.log(`Available targets: ${Object.keys(GLOBAL_TARGETS).map(k => `--${k}`).join(', ')}, --all`);
|
|
274
237
|
process.exit(1);
|
|
275
238
|
}
|
|
276
239
|
}
|
|
277
240
|
|
|
278
241
|
if (requestedTargets.length === 0) {
|
|
279
|
-
|
|
280
|
-
|
|
242
|
+
console.log('Agentic Senior Core -- Global Rules Installer\n');
|
|
243
|
+
console.log('Usage: asc global [--antigravity] [--cline] [--roo] [--kilocode] [--kiro] [--openhands] [--windsurf] [--copilot] [--all]\n');
|
|
244
|
+
console.log('Installs user-level global rules that apply to ALL projects.\n');
|
|
245
|
+
console.log('Supported automatic global targets:');
|
|
246
|
+
for (const [key, target] of Object.entries(GLOBAL_TARGETS)) {
|
|
247
|
+
console.log(` --${key.padEnd(14)} ${target.label} (${target.note})`);
|
|
248
|
+
}
|
|
249
|
+
console.log('\nManual global setup tools:');
|
|
250
|
+
for (const manual of MANUAL_TARGETS) {
|
|
251
|
+
console.log(` ${manual.label.padEnd(16)} ${manual.hint}`);
|
|
252
|
+
}
|
|
253
|
+
process.exit(0);
|
|
281
254
|
}
|
|
282
255
|
|
|
283
|
-
console.log('
|
|
284
|
-
|
|
256
|
+
console.log('Installing global rules...\n');
|
|
285
257
|
let successCount = 0;
|
|
258
|
+
|
|
286
259
|
for (const targetKey of requestedTargets) {
|
|
287
260
|
const success = await installGlobalTarget(targetKey);
|
|
288
261
|
if (success) successCount++;
|
|
289
|
-
const note = GLOBAL_TARGETS[targetKey].note;
|
|
290
|
-
if (note) console.log(` ${note}`);
|
|
291
262
|
}
|
|
292
263
|
|
|
293
|
-
console.log(`\
|
|
294
|
-
console.log('Static copies do not auto-update: re-run asc global after npm update -g.');
|
|
264
|
+
console.log(`\nInstalled ${successCount}/${requestedTargets.length} global target(s).`);
|
|
295
265
|
}
|
|
@@ -16,6 +16,7 @@ const ADAPTER_FILES = [
|
|
|
16
16
|
{ label: 'Kilo Code', path: '.kilocode/rules/agentic-senior-core.md' },
|
|
17
17
|
{ label: 'Roo Code', path: '.roo/rules/agentic-senior-core.md' },
|
|
18
18
|
{ label: 'OpenHands', path: '.openhands/microagents/agentic-senior-core.md' },
|
|
19
|
+
{ label: 'ASC Compiled Validator', path: '.asc/hooks/pre-commit-validator.cjs' },
|
|
19
20
|
];
|
|
20
21
|
|
|
21
22
|
async function pathExists(filePath) {
|
|
@@ -61,7 +62,7 @@ export async function runUninstallCommand(commandArguments) {
|
|
|
61
62
|
if (dryRun) {
|
|
62
63
|
console.log(` would remove: ${adapter.path} (${adapter.label})`);
|
|
63
64
|
} else {
|
|
64
|
-
await fs.rm(fullPath);
|
|
65
|
+
await fs.rm(fullPath, { force: true });
|
|
65
66
|
console.log(` removed: ${adapter.path} (${adapter.label})`);
|
|
66
67
|
removed++;
|
|
67
68
|
}
|
package/package.json
CHANGED
package/plugin.yaml
CHANGED