@ryuenn3123/agentic-senior-core 6.16.3 → 6.16.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.
Files changed (84) hide show
  1. package/.agents/plugins/agentic-senior-core/.codex-plugin/plugin.json +1 -1
  2. package/.agents/plugins/agentic-senior-core/commands/asc-pentest.md +2 -0
  3. package/.agents/plugins/agentic-senior-core/commands/asc-pentest.toml +3 -0
  4. package/.agents/plugins/agentic-senior-core/commands/asc-test.md +1 -1
  5. package/.agents/plugins/agentic-senior-core/commands/asc-ui.md +1 -1
  6. package/.agents/plugins/agentic-senior-core/hooks/dedup-gate.js +137 -128
  7. package/.agents/plugins/agentic-senior-core/hooks/hooks.json +97 -0
  8. package/.agents/plugins/agentic-senior-core/hooks/ladder-pulse.js +53 -36
  9. package/.agents/plugins/agentic-senior-core/hooks/lib/known-ui-slop-patterns.json +5 -0
  10. package/.agents/plugins/agentic-senior-core/hooks/path-util.cjs +118 -4
  11. package/.agents/plugins/agentic-senior-core/hooks/post-edit-enforce.js +98 -81
  12. package/.agents/plugins/agentic-senior-core/hooks/pre-tool-dependency-gate.js +168 -191
  13. package/.agents/plugins/agentic-senior-core/hooks/session-pulse.js +48 -35
  14. package/.agents/plugins/agentic-senior-core/hooks/session-start.js +62 -11
  15. package/.agents/plugins/agentic-senior-core/hooks.json +4 -94
  16. package/.agents/plugins/agentic-senior-core/plugin.json +5 -13
  17. package/.agents/plugins/agentic-senior-core/rules/agentic-senior-core.md +3 -1
  18. package/.agents/plugins/agentic-senior-core/skills/asc/SKILL.md +5 -2
  19. package/.agents/plugins/agentic-senior-core/skills/asc/references/writing-skills.md +1 -1
  20. package/.agents/plugins/agentic-senior-core/skills/asc-develop/SKILL.md +2 -2
  21. package/.agents/plugins/agentic-senior-core/skills/asc-pentest/SKILL.md +97 -0
  22. package/.agents/plugins/agentic-senior-core/skills/asc-pentest/references/api-security-idor.md +105 -0
  23. package/.agents/plugins/agentic-senior-core/skills/asc-pentest/references/dast-baseline.md +78 -0
  24. package/.agents/plugins/agentic-senior-core/skills/asc-pentest/references/fuzzing-dsl.md +66 -0
  25. package/.agents/plugins/agentic-senior-core/skills/asc-pentest/references/pentest-task-tree.md +70 -0
  26. package/.agents/plugins/agentic-senior-core/skills/asc-review/SKILL.md +1 -1
  27. package/.agents/plugins/agentic-senior-core/skills/asc-test/SKILL.md +10 -3
  28. package/.agents/plugins/agentic-senior-core/skills/asc-test/references/mutation-testing.md +55 -0
  29. package/.agents/plugins/agentic-senior-core/skills/asc-test/references/performance-budgets.md +67 -0
  30. package/.agents/plugins/agentic-senior-core/skills/asc-test/references/property-testing.md +72 -0
  31. package/.agents/plugins/agentic-senior-core/skills/asc-test/references/regression-proof.md +2 -2
  32. package/.agents/plugins/agentic-senior-core/skills/asc-test/references/tdd-cycle.md +2 -2
  33. package/.agents/plugins/agentic-senior-core/skills/asc-test/references/uat.md +1 -1
  34. package/.agents/plugins/agentic-senior-core/skills/asc-ui/SKILL.md +31 -34
  35. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/accessibility.md +2 -2
  36. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/copy-i18n.md +24 -8
  37. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/craft/color-surfaces.md +32 -0
  38. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/craft/composition-patterns.md +299 -0
  39. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/craft/themes-catalog.md +199 -0
  40. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/divergence.md +65 -24
  41. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/modes/experience.md +4 -0
  42. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/modes/genre-calibration.md +93 -0
  43. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/modes/operate.md +31 -1
  44. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/modes/persuade.md +33 -23
  45. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/modes/read.md +4 -0
  46. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/redesign-audit.md +5 -10
  47. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/states-feedback.md +2 -2
  48. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-attio-dom.json +5 -0
  49. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-attio.png +0 -0
  50. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-cal-dom.json +5 -0
  51. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-cal.png +0 -0
  52. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-clerk-dom.json +5 -0
  53. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-clerk.png +0 -0
  54. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-dub-dom.json +5 -0
  55. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-dub.png +0 -0
  56. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-linear-dom.json +5 -0
  57. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-linear.png +0 -0
  58. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-marketplace-dom.json +5 -0
  59. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-marketplace.png +0 -0
  60. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-mintlify-dom.json +5 -0
  61. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-mintlify.png +0 -0
  62. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-raycast-dom.json +5 -0
  63. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-raycast.png +0 -0
  64. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-resend-dom.json +5 -0
  65. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-resend.png +0 -0
  66. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-stripe-dom.json +5 -0
  67. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-stripe.png +0 -0
  68. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-supabase-dom.json +5 -0
  69. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-supabase.png +0 -0
  70. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-tldraw-dom.json +5 -0
  71. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-tldraw.png +0 -0
  72. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-vercel-dom.json +5 -0
  73. package/.agents/plugins/agentic-senior-core/skills/asc-ui/references/visuals/real-vercel.png +0 -0
  74. package/bin/agentic-senior-core.js +19 -4
  75. package/gemini-extension.json +2 -2
  76. package/lib/cli/ascx/runtime.mjs +5 -27
  77. package/lib/cli/ascx/windows-spawn.mjs +348 -0
  78. package/lib/cli/commands/bootstrap.mjs +56 -0
  79. package/lib/cli/commands/dedup.mjs +500 -0
  80. package/lib/cli/commands/git-hook-generator.mjs +3 -2
  81. package/lib/cli/commands/global.mjs +109 -53
  82. package/lib/cli/commands/preview.mjs +34 -20
  83. package/package.json +1 -1
  84. package/plugin.yaml +3 -1
@@ -184,7 +184,7 @@ async function ensureCodexConfigEnabled() {
184
184
  async function installCodexGlobal(target) {
185
185
  const rulesSource = path.join(REPOSITORY_ROOT, target.rulesSourcePath);
186
186
  const pluginSource = path.join(REPOSITORY_ROOT, target.pluginSourcePath);
187
- const hooksSource = path.join(REPOSITORY_ROOT, '.agents', 'plugins', 'agentic-senior-core', 'hooks.json');
187
+ const hooksSource = path.join(REPOSITORY_ROOT, '.agents', 'plugins', 'agentic-senior-core', 'hooks', 'hooks.json');
188
188
  const singlePluginSource = path.join(REPOSITORY_ROOT, '.agents', 'plugins', 'agentic-senior-core');
189
189
  const rulesTarget = target.targetPath(); // ~/.codex/AGENTS.md
190
190
  const hooksTarget = path.join(HOME, '.codex', 'hooks.json');
@@ -372,9 +372,10 @@ async function installAntigravityIde(target) {
372
372
  'utf8'
373
373
  );
374
374
 
375
- // Safely update/merge "agentic-senior-core" group key into global hooks.json (~/.gemini/config/hooks.json)
376
- const masterHooksSource = path.join(REPOSITORY_ROOT, '.agents', 'plugins', 'agentic-senior-core', 'hooks.json');
377
- await updateGlobalAntigravityHooks(masterHooksSource);
375
+ // Remove legacy global hooks.json entries (~/.gemini/config/hooks.json & ~/.gemini/antigravity-cli/hooks.json)
376
+ // because Antigravity executes hooks with cwd set to the directory containing hooks.json, and automatically
377
+ // discovers hooks.json inside ~/.gemini/config/plugins/agentic-senior-core/hooks.json without duplicate firing.
378
+ await cleanupLegacyGlobalAntigravityHooks();
378
379
 
379
380
  // Automatically register the plugin with Antigravity CLI if agy binary is available
380
381
  try {
@@ -389,44 +390,29 @@ async function installAntigravityIde(target) {
389
390
  return true;
390
391
  }
391
392
 
392
- async function updateGlobalAntigravityHooks(hooksSource) {
393
- if (!(await pathExists(hooksSource))) return;
393
+ async function cleanupLegacyGlobalAntigravityHooks() {
394
+ const globalHooksPath = path.join(HOME, '.gemini', 'config', 'hooks.json');
395
+ const legacyCliHooksPath = path.join(HOME, '.gemini', 'antigravity-cli', 'hooks.json');
394
396
 
395
- try {
396
- const rawMaster = JSON.parse(await fs.readFile(hooksSource, 'utf8'));
397
- const masterHooks = rawMaster.hooks || rawMaster;
398
-
399
- const formattedAscHooks = {
400
- SessionStart: masterHooks.SessionStart || null,
401
- PreInvocation: masterHooks.PreInvocation || null,
402
- PostInvocation: masterHooks.PostInvocation || null,
403
- Stop: masterHooks.Stop || null,
404
- PreToolUse: masterHooks.PreToolUse || null,
405
- PostToolUse: masterHooks.PostToolUse || null,
406
- };
407
-
408
- const targetPaths = [
409
- path.join(HOME, '.gemini', 'config', 'hooks.json'),
410
- path.join(HOME, '.gemini', 'antigravity-cli', 'hooks.json'),
411
- ];
412
-
413
- for (const targetPath of targetPaths) {
414
- try {
415
- await fs.mkdir(path.dirname(targetPath), { recursive: true });
416
- let existingConfig = {};
417
- if (await pathExists(targetPath)) {
418
- try {
419
- existingConfig = JSON.parse(await fs.readFile(targetPath, 'utf8'));
420
- } catch (_) {}
421
- }
422
-
423
- // Safely merge "agentic-senior-core" key preserving other user keys (e.g. "well")
424
- existingConfig['agentic-senior-core'] = formattedAscHooks;
397
+ if (await pathExists(legacyCliHooksPath)) {
398
+ try {
399
+ await fs.rm(legacyCliHooksPath, { force: true });
400
+ } catch (_) {}
401
+ }
425
402
 
426
- await fs.writeFile(targetPath, JSON.stringify(existingConfig, null, 2) + '\n', 'utf8');
427
- } catch (_) {}
428
- }
429
- } catch (_) {}
403
+ if (await pathExists(globalHooksPath)) {
404
+ try {
405
+ const existingConfig = JSON.parse(await fs.readFile(globalHooksPath, 'utf8'));
406
+ if (existingConfig && typeof existingConfig === 'object' && 'agentic-senior-core' in existingConfig) {
407
+ delete existingConfig['agentic-senior-core'];
408
+ if (Object.keys(existingConfig).length === 0) {
409
+ await fs.rm(globalHooksPath, { force: true });
410
+ } else {
411
+ await fs.writeFile(globalHooksPath, JSON.stringify(existingConfig, null, 2) + '\n', 'utf8');
412
+ }
413
+ }
414
+ } catch (_) {}
415
+ }
430
416
  }
431
417
 
432
418
  async function findAgyBinaryPath() {
@@ -509,7 +495,78 @@ async function installGlobalTarget(targetKey) {
509
495
  return true;
510
496
  }
511
497
 
512
- export async function runGlobalCommand(commandArguments) {
498
+ export async function detectInstalledGlobalTargets() {
499
+ const isWin = process.platform === 'win32';
500
+ const { resolveWindowsExecutable } = await import('../ascx/windows-spawn.mjs');
501
+ const { execSync } = await import('node:child_process');
502
+
503
+ const hasBinary = (cmd) => {
504
+ if (isWin) {
505
+ return Boolean(resolveWindowsExecutable(cmd, process.env, process.cwd()));
506
+ }
507
+ try {
508
+ execSync(`command -v ${cmd}`, { stdio: 'ignore' });
509
+ return true;
510
+ } catch {
511
+ return false;
512
+ }
513
+ };
514
+
515
+ const checks = {
516
+ antigravity: async () => (await pathExists(path.join(HOME, '.gemini'))) || hasBinary('agy'),
517
+ codex: async () => (await pathExists(path.join(HOME, '.codex'))) || hasBinary('codex'),
518
+ opencode: async () => (await pathExists(path.join(HOME, '.config', 'opencode')))
519
+ || (await pathExists(path.join(HOME, '.opencode')))
520
+ || hasBinary('opencode'),
521
+ roo: async () => await pathExists(path.join(HOME, '.roo')),
522
+ kilocode: async () => (await pathExists(path.join(HOME, '.config', 'kilo')))
523
+ || (await pathExists(path.join(HOME, '.kilo')))
524
+ || (await pathExists(path.join(HOME, '.kilocode')))
525
+ || (process.env.APPDATA ? await pathExists(path.join(process.env.APPDATA, 'kilo')) : false)
526
+ || hasBinary('kilo'),
527
+ cline: async () => (await pathExists(path.join(HOME, '.cline')))
528
+ || (await pathExists(path.join(HOME, 'Documents', 'Cline'))),
529
+ kiro: async () => await pathExists(path.join(HOME, '.kiro')),
530
+ openhands: async () => (await pathExists(path.join(HOME, '.openhands'))) || hasBinary('openhands'),
531
+ windsurf: async () => (await pathExists(path.join(HOME, '.windsurf')))
532
+ || (await pathExists(path.join(HOME, '.codeium')))
533
+ || (isWin ? await pathExists(path.join(HOME, 'AppData', 'Roaming', 'Windsurf')) : false),
534
+ copilot: async () => (await pathExists(path.join(HOME, '.config', 'github-copilot')))
535
+ || (isWin ? await pathExists(path.join(HOME, 'AppData', 'Local', 'GitHub Copilot')) : false)
536
+ || (await pathExists(path.dirname(vscodeUserPromptsDirectory()))),
537
+ };
538
+
539
+ const detected = [];
540
+ for (const [key, check] of Object.entries(checks)) {
541
+ if (GLOBAL_TARGETS[key] && (await check())) {
542
+ detected.push(key);
543
+ }
544
+ }
545
+ return detected;
546
+ }
547
+
548
+ function printGlobalHelp() {
549
+ console.log('Agentic Senior Core -- Global Rules Installer\n');
550
+ console.log('Usage:');
551
+ console.log(' asc global Auto-detect installed AI tools and install globally');
552
+ console.log(' asc global --all Install to all supported global targets');
553
+ console.log(' asc global --<target> Install to specific target(s)\n');
554
+ console.log('Supported automatic global targets:');
555
+ for (const [key, target] of Object.entries(GLOBAL_TARGETS)) {
556
+ console.log(` --${key.padEnd(14)} ${target.label} (${target.note})`);
557
+ }
558
+ console.log('\nManual global setup tools:');
559
+ for (const manual of MANUAL_TARGETS) {
560
+ console.log(` ${manual.label.padEnd(16)} ${manual.hint}`);
561
+ }
562
+ }
563
+
564
+ export async function runGlobalCommand(commandArguments = []) {
565
+ if (commandArguments.includes('--help') || commandArguments.includes('-h')) {
566
+ printGlobalHelp();
567
+ return;
568
+ }
569
+
513
570
  const requestedTargets = [];
514
571
 
515
572
  for (const argument of commandArguments) {
@@ -521,7 +578,11 @@ export async function runGlobalCommand(commandArguments) {
521
578
  const targetKey = argument.replace(/^--/, '');
522
579
  if (GLOBAL_TARGETS[targetKey]) {
523
580
  requestedTargets.push(targetKey);
524
- } else if (argument.startsWith('--')) {
581
+ } else if (argument.startsWith('-')) {
582
+ console.error(`Unknown global target: ${argument}`);
583
+ console.log(`Available targets: ${Object.keys(GLOBAL_TARGETS).map(k => `--${k}`).join(', ')}, --all`);
584
+ process.exit(1);
585
+ } else {
525
586
  console.error(`Unknown global target: ${argument}`);
526
587
  console.log(`Available targets: ${Object.keys(GLOBAL_TARGETS).map(k => `--${k}`).join(', ')}, --all`);
527
588
  process.exit(1);
@@ -529,18 +590,13 @@ export async function runGlobalCommand(commandArguments) {
529
590
  }
530
591
 
531
592
  if (requestedTargets.length === 0) {
532
- console.log('Agentic Senior Core -- Global Rules Installer\n');
533
- console.log('Usage: asc global [--antigravity] [--codex] [--cline] [--roo] [--kilocode] [--opencode] [--kiro] [--openhands] [--windsurf] [--copilot] [--all]\n');
534
- console.log('Installs user-level global rules that apply to ALL projects.\n');
535
- console.log('Supported automatic global targets:');
536
- for (const [key, target] of Object.entries(GLOBAL_TARGETS)) {
537
- console.log(` --${key.padEnd(14)} ${target.label} (${target.note})`);
538
- }
539
- console.log('\nManual global setup tools:');
540
- for (const manual of MANUAL_TARGETS) {
541
- console.log(` ${manual.label.padEnd(16)} ${manual.hint}`);
593
+ const autoDetected = await detectInstalledGlobalTargets();
594
+ if (autoDetected.length === 0) {
595
+ printGlobalHelp();
596
+ return;
542
597
  }
543
- process.exit(0);
598
+ console.log(`Auto-detected ${autoDetected.length} installed AI host(s): ${autoDetected.join(', ')}\n`);
599
+ requestedTargets.push(...autoDetected);
544
600
  }
545
601
 
546
602
  console.log('Installing global rules...\n');
@@ -6,8 +6,19 @@
6
6
  import fs from 'node:fs';
7
7
  import path from 'node:path';
8
8
  import os from 'node:os';
9
+ import { pathToFileURL } from 'node:url';
9
10
  import { execSync } from 'node:child_process';
10
11
 
12
+ function openInDefaultBrowser(targetPath) {
13
+ if (process.platform === 'win32') {
14
+ execSync(`cmd.exe /d /s /c "start "" "${targetPath}""`, { stdio: 'ignore' });
15
+ } else if (process.platform === 'darwin') {
16
+ execSync(`open "${targetPath}"`, { stdio: 'ignore' });
17
+ } else {
18
+ execSync(`xdg-open "${targetPath}"`, { stdio: 'ignore' });
19
+ }
20
+ }
21
+
11
22
  export function getBrowserCandidates() {
12
23
  const platform = process.platform;
13
24
  const candidates = [];
@@ -139,32 +150,36 @@ export function findBrowserExecutable() {
139
150
  }
140
151
 
141
152
  export async function runPreviewCommand(args = []) {
142
- const targetFile = args.find(a => !a.startsWith('-'));
153
+ const target = args.find(a => !a.startsWith('-'));
143
154
  const shouldOpen = args.includes('--open');
144
- const width = 1280;
145
- const height = 800;
155
+ const isMobile = args.includes('--mobile');
156
+ const width = isMobile ? 390 : (args.includes('--desktop') ? 1440 : 1280);
157
+ const height = isMobile ? 844 : (args.includes('--desktop') ? 900 : 800);
146
158
 
147
- if (!targetFile) {
148
- console.error('Usage: asc preview <html-file> [--open]');
159
+ if (!target) {
160
+ console.error('Usage: asc preview <html-file-or-url> [--open] [--mobile] [--desktop]');
149
161
  process.exit(1);
150
162
  }
151
163
 
152
- const resolvedHtmlPath = path.resolve(process.cwd(), targetFile);
153
- if (!fs.existsSync(resolvedHtmlPath)) {
154
- console.error(`File not found: ${resolvedHtmlPath}`);
155
- process.exit(1);
164
+ const isHttpUrl = /^https?:\/\//i.test(target);
165
+ let resolvedTarget = target;
166
+ if (!isHttpUrl) {
167
+ resolvedTarget = path.resolve(process.cwd(), target);
168
+ if (!fs.existsSync(resolvedTarget)) {
169
+ console.error(`File not found: ${resolvedTarget}`);
170
+ process.exit(1);
171
+ }
156
172
  }
157
173
 
158
174
  // Single fixed reusable slot in OS temp directory
159
175
  const tempDir = os.tmpdir();
160
- const outputPng = path.join(tempDir, 'asc-preview-active.png');
176
+ const outputPng = path.join(tempDir, isMobile ? 'asc-preview-mobile.png' : 'asc-preview-active.png');
161
177
 
162
178
  // Open in default OS browser if requested
163
179
  if (shouldOpen) {
164
- const opener = process.platform === 'win32' ? 'start' : process.platform === 'darwin' ? 'open' : 'xdg-open';
165
180
  try {
166
- execSync(`${opener} "" "${resolvedHtmlPath}"`, { stdio: 'ignore' });
167
- console.log(`[asc preview] Opened in default browser: ${resolvedHtmlPath}`);
181
+ openInDefaultBrowser(resolvedTarget);
182
+ console.log(`[asc preview] Opened in default browser: ${resolvedTarget}`);
168
183
  return;
169
184
  } catch (err) {
170
185
  console.error(`Failed to open default browser: ${err.message}`);
@@ -175,20 +190,20 @@ export async function runPreviewCommand(args = []) {
175
190
  const browser = findBrowserExecutable();
176
191
  if (!browser) {
177
192
  console.warn('[asc preview] No supported headless browser detected (Brave, Edge, Chrome, Firefox). Falling back to OS opener.');
178
- const opener = process.platform === 'win32' ? 'start' : process.platform === 'darwin' ? 'open' : 'xdg-open';
179
- execSync(`${opener} "" "${resolvedHtmlPath}"`, { stdio: 'ignore' });
193
+ openInDefaultBrowser(resolvedTarget);
180
194
  return;
181
195
  }
182
196
 
183
197
  try {
198
+ const targetUrl = isHttpUrl ? target : pathToFileURL(resolvedTarget).href;
184
199
  let command;
185
200
  if (browser.family === 'chromium') {
186
- command = `"${browser.path}" --headless --disable-gpu --screenshot="${outputPng}" --window-size=${width},${height} "${resolvedHtmlPath}"`;
201
+ command = `"${browser.path}" --headless=new --disable-gpu --screenshot="${outputPng}" --window-size=${width},${height} "${targetUrl}"`;
187
202
  } else if (browser.family === 'firefox') {
188
- command = `"${browser.path}" -headless -screenshot "${outputPng}" -window-size ${width},${height} "${resolvedHtmlPath}"`;
203
+ command = `"${browser.path}" -headless -screenshot "${outputPng}" -window-size ${width},${height} "${targetUrl}"`;
189
204
  }
190
205
 
191
- execSync(command, { stdio: 'pipe' });
206
+ execSync(command, { stdio: 'pipe', timeout: 15000 });
192
207
 
193
208
  if (fs.existsSync(outputPng)) {
194
209
  const stat = fs.statSync(outputPng);
@@ -199,8 +214,7 @@ export async function runPreviewCommand(args = []) {
199
214
  }
200
215
  } catch (err) {
201
216
  console.warn(`[asc preview] Headless snapshot failed: ${err.message}. Falling back to OS opener.`);
202
- const opener = process.platform === 'win32' ? 'start' : process.platform === 'darwin' ? 'open' : 'xdg-open';
203
- execSync(`${opener} "" "${resolvedHtmlPath}"`, { stdio: 'ignore' });
217
+ openInDefaultBrowser(resolvedTarget);
204
218
  }
205
219
  }
206
220
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuenn3123/agentic-senior-core",
3
- "version": "6.16.3",
3
+ "version": "6.16.6",
4
4
  "type": "module",
5
5
  "description": "Agentic Senior Core: Universal AI coding rules and workflows. Write code like a staff engineer, not a junior.",
6
6
  "bin": {
package/plugin.yaml CHANGED
@@ -1,5 +1,5 @@
1
1
  name: agentic-senior-core
2
- version: 6.16.3
2
+ version: 6.16.6
3
3
  description: Universal AI coding rules. Write code like a staff engineer.
4
4
  author: fatidaprilian
5
5
  provides_hooks:
@@ -11,6 +11,7 @@ provides_commands:
11
11
  - asc-reference
12
12
  - asc-ui
13
13
  - asc-test
14
+ - asc-pentest
14
15
  provides_skills:
15
16
  - asc
16
17
  - asc-develop
@@ -18,3 +19,4 @@ provides_skills:
18
19
  - asc-review
19
20
  - asc-ui
20
21
  - asc-test
22
+ - asc-pentest