@ryuenn3123/agentic-senior-core 6.11.0 → 6.12.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.
@@ -42,7 +42,11 @@ Grounded in: WCAG 2.2 AA (accessibility), Fowler's Money Pattern (monetary types
42
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.
43
43
  - UI Component Reusability: Primitive UI elements (buttons, inputs, cards, dialogs, badges) must have a single source of truth in the shared component directory (`components/` or `ui/`). Never recreate ad-hoc variants or duplicate JSX structures across individual pages. Extend existing components with props or variants instead of cloning.
44
44
  - Design Consistency: Consume shared design tokens, CSS variables, or theme configuration for colors, spacing, and border-radius. Do not hardcode arbitrary raw color hexes or inconsistent spacing that causes visual design drift between pages.
45
- - Data-fetching components must explicitly handle 3 states: loading, error (with user-facing toast/notification and retry option), and data. Never leave an unhandled error state.
45
+ - Action Feedback & Mutations: Any user-initiated mutation (form submit, delete, upload, toggle) must provide immediate pending feedback (disabled button, inline spinner) and a visible completion notification (toast or alert banner with retry). Never silently swallow mutation errors.
46
+ - Form Validation: Render field errors inline directly next to the affected input with `aria-describedby` and `aria-invalid="true"`. Never use floating toasts for individual form input validation.
47
+ - Data-Fetching State Quad: Data components must explicitly handle 4 states — loading skeleton/spinner, empty state (friendly message + call to action), error fallback (clear message + retry button), and populated data.
48
+ - Component Error Boundaries: Wrap major widgets, dashboards, and routes in localized Error Boundaries with fallback UI cards to prevent a single rendering crash from taking down the entire page.
49
+ - Accessible Notifications: Toast and status messages must use ARIA live regions (`role="status"`, `aria-live="polite"` for non-urgent feedback; `role="alert"` for critical errors). Never steal keyboard focus for toasts.
46
50
  - WCAG 2.2 AA accessibility floor. Responsive by default.
47
51
  - No placeholder, lorem, or TODO content in production UI.
48
52
 
@@ -54,9 +58,15 @@ Grounded in: WCAG 2.2 AA (accessibility), Fowler's Money Pattern (monetary types
54
58
 
55
59
  ## Resilience
56
60
 
57
- - Every outbound network call has a strict timeout.
61
+ - Every outbound network call has a strict timeout (client and server).
58
62
  - Retries use exponential backoff with jitter and max attempt limits.
59
- - Only retry idempotent operations.
60
- - Circuit breakers for unhealthy dependencies.
61
- - Graceful degradation on non-critical dependency failure.
63
+ - Only retry idempotent operations (GET, PUT, DELETE, or requests with `Idempotency-Key`).
64
+ - Dependency Fallback Strategy (Hard vs Soft):
65
+ - Hard dependencies (core workflow blocks without them): Fail fast, roll back transactions, return structured RFC 9457 error with actionable explanation.
66
+ - Soft dependencies (non-critical enhancements): Provide graceful fallbacks:
67
+ - *Static Fallback*: Return safe default values, static placeholders, or empty collections alih-alih melempar exception.
68
+ - *Stale Cache Fallback*: Serve last-known-good cached state (`stale-while-revalidate`) with an offline/stale indicator.
69
+ - *Degraded Mode*: Isolate and disable the failing peripheral widget while preserving core user journeys.
70
+ - Circuit breakers for unhealthy dependencies to fail fast and prevent thread/resource exhaustion.
71
+ - Offline Detection: Detect offline network status and notify users before initiating network requests that are guaranteed to fail.
62
72
 
@@ -21,10 +21,11 @@ Grounded in: OWASP Risk Rating Methodology, Google Engineering Practices (code r
21
21
  ## Finding Priority Order
22
22
 
23
23
  1. Correctness, data loss, security, privacy, auth, and permission risks.
24
- 2. Public contract drift: APIs, events, CLI behavior, data model, UI contract, docs.
25
- 3. Missing tests for changed behavior.
26
- 4. Architecture boundary drift and maintainability risk.
27
- 5. Performance and accessibility issues with concrete impact.
24
+ 2. Action feedback & resilience: silent mutation failures, missing toasts/banners, hanging spinners, missing fallbacks on remote calls, or missing error boundaries.
25
+ 3. Public contract drift: APIs, events, CLI behavior, data model, UI contract, docs.
26
+ 4. Missing tests for changed behavior.
27
+ 5. Architecture boundary drift and maintainability risk.
28
+ 6. Performance and accessibility issues with concrete impact.
28
29
 
29
30
  ## For Every Finding
30
31
 
@@ -37,7 +38,9 @@ Grounded in: OWASP Risk Rating Methodology, Google Engineering Practices (code r
37
38
  ### Correctness
38
39
  - Changed behavior matches the user request.
39
40
  - Existing behavior preserved unless user approved a change.
40
- - Edge cases, empty states, error paths handled.
41
+ - Edge cases, empty states, error paths, and fallbacks handled.
42
+ - Action feedback: mutations (forms, buttons, mutations) have visible pending indicators and clear completion notifications (toast or banner with retry). No silent failures or hanging spinners.
43
+ - Dependency resilience: remote calls have strict timeouts and soft dependencies have graceful fallbacks (static default, stale cache, or degraded mode). Component crashes are contained by error boundaries.
41
44
 
42
45
  ### Security
43
46
  - External input validated at trust boundaries.
@@ -8,7 +8,6 @@
8
8
  * uninstall Remove ASC adapter files from the current project
9
9
  * clean Remove v4 per-project artifacts (.agent-context/, bridge files)
10
10
  * status Show detected IDEs and install hints
11
- * mcp Start MCP stdio server
12
11
  */
13
12
  import { exit } from 'node:process';
14
13
  import { readFileSync } from 'node:fs';
@@ -37,7 +36,6 @@ function printUsage() {
37
36
  console.log(' uninstall Remove ASC adapter files and git hooks from this project');
38
37
  console.log(' clean Remove v4 per-project artifacts');
39
38
  console.log(' status Show detected IDEs and install hints');
40
- console.log(' mcp Start MCP stdio server');
41
39
  console.log(' --version Show version');
42
40
  console.log(' --help Show this help');
43
41
  }
@@ -92,12 +90,6 @@ async function main() {
92
90
  return;
93
91
  }
94
92
 
95
- if (commandArgument === 'mcp') {
96
- const { runMcpServerCommand } = await import('../lib/cli/commands/mcp.mjs');
97
- await runMcpServerCommand();
98
- return;
99
- }
100
-
101
93
  console.error(`Unknown command: ${commandArgument}`);
102
94
  printUsage();
103
95
  exit(1);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
- "version": "6.11.0",
3
+ "version": "6.12.0",
4
4
  "description": "Universal AI coding rules. Write code like a staff engineer.",
5
5
  "author": "fatidaprilian",
6
6
  "license": "MIT",
@@ -470,6 +470,13 @@ export function installGlobalGitPreCommitHook({ homeDir = os.homedir() } = {}) {
470
470
  fs.mkdirSync(globalHooksDir, { recursive: true });
471
471
  }
472
472
 
473
+ // Generate standalone universal runner in global directory for fallback
474
+ const globalRunnerPath = path.join(globalHooksDir, 'pre-commit-runner.cjs');
475
+ const runnerScriptContent = generatePreCommitRunnerScript();
476
+ fs.writeFileSync(globalRunnerPath, runnerScriptContent, { encoding: 'utf8', mode: 0o755 });
477
+
478
+ const globalRunnerPosix = globalRunnerPath.replace(/\\/g, '/');
479
+
473
480
  const hookPath = path.join(globalHooksDir, 'pre-commit');
474
481
  const dispatcherContent = `#!/bin/sh
475
482
  ${ASC_HOOK_HEADER} -- Global Smart Dispatcher
@@ -504,13 +511,16 @@ if [ -n "$LOCAL_HOOK" ]; then
504
511
  fi
505
512
  fi
506
513
 
507
- # 3. Run ASC workspace pre-commit runner if present
514
+ # 3. Run ASC workspace pre-commit runner if present, or fallback to global runner
508
515
  if [ -n "$GIT_ROOT" ] && [ -f "$GIT_ROOT/.asc/hooks/pre-commit-runner.cjs" ]; then
509
516
  node "$GIT_ROOT/.asc/hooks/pre-commit-runner.cjs" "$@"
510
517
  exit $?
511
518
  elif [ -f ".asc/hooks/pre-commit-runner.cjs" ]; then
512
519
  node .asc/hooks/pre-commit-runner.cjs "$@"
513
520
  exit $?
521
+ elif [ -f "${globalRunnerPosix}" ]; then
522
+ node "${globalRunnerPosix}" "$@"
523
+ exit $?
514
524
  fi
515
525
 
516
526
  exit 0
@@ -525,6 +535,6 @@ exit 0
525
535
  return { installed: false, hookPath, reason: 'Could not set git config --global core.hooksPath' };
526
536
  }
527
537
 
528
- return { installed: true, hookPath, global: true };
538
+ return { installed: true, hookPath, runnerPath: globalRunnerPath, global: true };
529
539
  }
530
540
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuenn3123/agentic-senior-core",
3
- "version": "6.11.0",
3
+ "version": "6.12.0",
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": {
@@ -16,8 +16,6 @@
16
16
  "gemini-extension.json",
17
17
  "plugin.yaml",
18
18
  "__init__.py",
19
- "scripts/mcp-server.mjs",
20
- "scripts/mcp-server/",
21
19
  "scripts/uninstall.js",
22
20
  "README.md",
23
21
  "LICENSE",
package/plugin.yaml CHANGED
@@ -1,5 +1,5 @@
1
1
  name: agentic-senior-core
2
- version: 6.11.0
2
+ version: 6.12.0
3
3
  description: Universal AI coding rules. Write code like a staff engineer.
4
4
  author: fatidaprilian
5
5
  provides_hooks:
@@ -1,3 +0,0 @@
1
- export async function runMcpServerCommand() {
2
- await import('../../../scripts/mcp-server.mjs');
3
- }
@@ -1,57 +0,0 @@
1
- // @ts-check
2
-
3
- import { existsSync, readFileSync } from 'node:fs';
4
- import { dirname, resolve } from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
-
7
- const SCRIPT_FILE_PATH = fileURLToPath(import.meta.url);
8
- export const REPOSITORY_ROOT = resolve(dirname(SCRIPT_FILE_PATH), '..', '..');
9
- export const STATE_DIRECTORY = resolve(REPOSITORY_ROOT, '.agent-context', 'state');
10
- export const DEFAULT_PROTOCOL_VERSION = '2024-11-05';
11
- export const DEFAULT_FETCH_TIMEOUT_MS = 15000;
12
- export const DEFAULT_FETCH_MAX_CHARS = 6000;
13
- export const MAX_FETCH_MAX_CHARS = 20000;
14
- export const DEFAULT_TREND_WINDOW_DAYS = 90;
15
- export const MAX_TREND_PACKAGES = 10;
16
- export const FALLBACK_PACKAGE_VERSION = '0.0.0-local';
17
-
18
- // IMPORTANT: This version extraction logic is intentionally duplicated from lib/cli/constants.mjs.
19
- // The MCP server is designed to be copied directly into target user workspaces where
20
- // the original package.json may not exist in the parent tree. This try/catch fallback
21
- // ensures the server can still run standalone without crashing if package.json is missing.
22
- function resolvePackageVersion() {
23
- try {
24
- const parsedPackageManifest = JSON.parse(
25
- readFileSync(resolve(REPOSITORY_ROOT, 'package.json'), 'utf8')
26
- );
27
- const rawVersion = typeof parsedPackageManifest?.version === 'string'
28
- ? parsedPackageManifest.version.trim()
29
- : '';
30
-
31
- return rawVersion || FALLBACK_PACKAGE_VERSION;
32
- } catch {
33
- return FALLBACK_PACKAGE_VERSION;
34
- }
35
- }
36
-
37
- export const PACKAGE_VERSION = resolvePackageVersion();
38
-
39
- export const TEST_SUITE_ARGS = {
40
- adapter: ['--test', './tests/adapter.test.mjs'],
41
- };
42
-
43
- export const INTERNAL_SCRIPT_PATHS = {};
44
-
45
- function getAvailableTestSuites() {
46
- return Object.entries(TEST_SUITE_ARGS)
47
- .filter(([, commandArguments]) => (
48
- Array.isArray(commandArguments)
49
- && commandArguments.length > 1
50
- && commandArguments
51
- .slice(1)
52
- .every((relativeTestPath) => existsSync(resolve(REPOSITORY_ROOT, relativeTestPath)))
53
- ))
54
- .map(([suiteName]) => suiteName);
55
- }
56
-
57
- export const AVAILABLE_TEST_SUITES = getAvailableTestSuites();
@@ -1,204 +0,0 @@
1
- // @ts-check
2
-
3
- import { existsSync } from 'node:fs';
4
- import { AVAILABLE_TEST_SUITES, INTERNAL_SCRIPT_PATHS } from './constants.mjs';
5
-
6
- export function buildToolDefinitions() {
7
- const toolDefinitions = [];
8
-
9
- if (existsSync(INTERNAL_SCRIPT_PATHS.validate)) {
10
- toolDefinitions.push({
11
- name: 'validate',
12
- description: 'Run repository validation checks.',
13
- inputSchema: {
14
- type: 'object',
15
- properties: {},
16
- additionalProperties: false,
17
- },
18
- });
19
- }
20
-
21
- if (AVAILABLE_TEST_SUITES.length > 0) {
22
- toolDefinitions.push({
23
- name: 'test',
24
- description: 'Run test suites (full or targeted).',
25
- inputSchema: {
26
- type: 'object',
27
- properties: {
28
- suite: {
29
- type: 'string',
30
- enum: AVAILABLE_TEST_SUITES,
31
- description: 'Target test suite. Defaults to the first available suite.',
32
- },
33
- },
34
- additionalProperties: false,
35
- },
36
- });
37
- }
38
-
39
- if (existsSync(INTERNAL_SCRIPT_PATHS.release_gate)) {
40
- toolDefinitions.push({
41
- name: 'release_gate',
42
- description: 'Run release gate checks.',
43
- inputSchema: {
44
- type: 'object',
45
- properties: {},
46
- additionalProperties: false,
47
- },
48
- });
49
- }
50
-
51
- if (existsSync(INTERNAL_SCRIPT_PATHS.forbidden_content_check)) {
52
- toolDefinitions.push({
53
- name: 'forbidden_content_check',
54
- description: 'Run forbidden content scan used by publish gate.',
55
- inputSchema: {
56
- type: 'object',
57
- properties: {},
58
- additionalProperties: false,
59
- },
60
- });
61
- }
62
-
63
- toolDefinitions.push(
64
- {
65
- name: 'lookup_rule',
66
- description: 'Look up a canonical .agent-context rule section by stable rule ID.',
67
- inputSchema: {
68
- type: 'object',
69
- properties: {
70
- ruleId: {
71
- type: 'string',
72
- description: 'Stable rule section ID, such as ARCH-003 or API-001.',
73
- },
74
- },
75
- required: ['ruleId'],
76
- additionalProperties: false,
77
- },
78
- },
79
- {
80
- name: 'validate_against_rules',
81
- description: 'Validate that cited rule IDs resolve to canonical rule sections.',
82
- inputSchema: {
83
- type: 'object',
84
- properties: {
85
- ruleIds: {
86
- type: 'array',
87
- items: { type: 'string' },
88
- description: 'Rule IDs cited by a response, plan, or review.',
89
- },
90
- summary: {
91
- type: 'string',
92
- description: 'Optional one-line context for the validation request.',
93
- },
94
- },
95
- required: ['ruleIds'],
96
- additionalProperties: false,
97
- },
98
- },
99
- {
100
- name: 'audit_compliance',
101
- description: 'Run a lightweight compliance audit over cited rule IDs and scope labels.',
102
- inputSchema: {
103
- type: 'object',
104
- properties: {
105
- ruleIds: {
106
- type: 'array',
107
- items: { type: 'string' },
108
- description: 'Rule IDs used as the compliance basis.',
109
- },
110
- scope: {
111
- type: 'string',
112
- description: 'Optional changed scope label, such as api, security, testing, architecture, ui, or release.',
113
- },
114
- },
115
- required: ['ruleIds'],
116
- additionalProperties: false,
117
- },
118
- },
119
- {
120
- name: 'research_fetch',
121
- description: 'Fetch external documentation/news content and return query-focused excerpts with citation metadata.',
122
- inputSchema: {
123
- type: 'object',
124
- properties: {
125
- url: {
126
- type: 'string',
127
- description: 'Absolute HTTP/HTTPS URL to fetch.',
128
- },
129
- query: {
130
- type: 'string',
131
- description: 'Optional search query used to extract focused excerpts.',
132
- },
133
- maxChars: {
134
- type: 'integer',
135
- description: 'Maximum characters to return when query is not provided (default 6000, max 20000).',
136
- },
137
- },
138
- required: ['url'],
139
- additionalProperties: false,
140
- },
141
- },
142
- {
143
- name: 'trend_snapshot',
144
- description: 'Generate ecosystem trend snapshot from npm registry metadata with source timestamps.',
145
- inputSchema: {
146
- type: 'object',
147
- properties: {
148
- packages: {
149
- type: 'array',
150
- items: { type: 'string' },
151
- description: 'Package names to inspect (max 10).',
152
- },
153
- windowDays: {
154
- type: 'integer',
155
- description: 'Release activity window in days (default 90).',
156
- },
157
- },
158
- required: ['packages'],
159
- additionalProperties: false,
160
- },
161
- },
162
- {
163
- name: 'state_read',
164
- description: 'Read a file from .agent-context/state for cross-session continuity.',
165
- inputSchema: {
166
- type: 'object',
167
- properties: {
168
- path: {
169
- type: 'string',
170
- description: 'Path relative to .agent-context/state, such as memory-continuity-benchmark.json.',
171
- },
172
- },
173
- required: ['path'],
174
- additionalProperties: false,
175
- },
176
- },
177
- {
178
- name: 'state_write',
179
- description: 'Write a file under .agent-context/state for cross-session continuity updates.',
180
- inputSchema: {
181
- type: 'object',
182
- properties: {
183
- path: {
184
- type: 'string',
185
- description: 'Path relative to .agent-context/state.',
186
- },
187
- content: {
188
- type: 'string',
189
- description: 'UTF-8 content to write.',
190
- },
191
- mode: {
192
- type: 'string',
193
- enum: ['overwrite', 'append'],
194
- description: 'Write mode. Defaults to overwrite.',
195
- },
196
- },
197
- required: ['path', 'content'],
198
- additionalProperties: false,
199
- },
200
- },
201
- );
202
-
203
- return toolDefinitions;
204
- }