@ryuenn3123/agentic-senior-core 2.0.19 → 2.0.21

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.
@@ -0,0 +1,181 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "Benchmark Before-vs-After Comparison",
4
+ "description": "Schema for comparing benchmark results across releases or configuration changes. Each entry captures quality, bug signal, runtime, and token metrics for a before and after snapshot.",
5
+ "type": "object",
6
+ "required": ["schemaVersion", "comparisonId", "generatedAt", "before", "after", "delta"],
7
+ "properties": {
8
+ "schemaVersion": {
9
+ "type": "string",
10
+ "const": "1.0.0"
11
+ },
12
+ "comparisonId": {
13
+ "type": "string",
14
+ "description": "Unique identifier for this comparison run."
15
+ },
16
+ "generatedAt": {
17
+ "type": "string",
18
+ "format": "date-time"
19
+ },
20
+ "baselineVersion": {
21
+ "type": "string",
22
+ "description": "Package version of the before snapshot."
23
+ },
24
+ "candidateVersion": {
25
+ "type": "string",
26
+ "description": "Package version of the after snapshot."
27
+ },
28
+ "comparisonType": {
29
+ "type": "string",
30
+ "enum": ["release-to-release", "config-change", "model-swap", "manual"],
31
+ "description": "What triggered this comparison."
32
+ },
33
+ "before": { "$ref": "#/$defs/snapshot" },
34
+ "after": { "$ref": "#/$defs/snapshot" },
35
+ "delta": { "$ref": "#/$defs/deltaReport" },
36
+ "verdict": {
37
+ "type": "string",
38
+ "enum": ["pass", "warn", "fail"],
39
+ "description": "Overall comparison verdict based on threshold policy."
40
+ },
41
+ "verdictReason": {
42
+ "type": "string",
43
+ "description": "Human-readable explanation of the verdict."
44
+ }
45
+ },
46
+ "$defs": {
47
+ "snapshot": {
48
+ "type": "object",
49
+ "required": ["capturedAt", "quality", "runtime"],
50
+ "properties": {
51
+ "capturedAt": {
52
+ "type": "string",
53
+ "format": "date-time"
54
+ },
55
+ "packageVersion": {
56
+ "type": "string"
57
+ },
58
+ "quality": {
59
+ "type": "object",
60
+ "properties": {
61
+ "top1Accuracy": {
62
+ "type": "number",
63
+ "minimum": 0,
64
+ "maximum": 1,
65
+ "description": "Fraction of scenarios where the top-ranked output was correct."
66
+ },
67
+ "manualCorrectionRate": {
68
+ "type": "number",
69
+ "minimum": 0,
70
+ "maximum": 1,
71
+ "description": "Fraction of outputs requiring human correction."
72
+ },
73
+ "averageJudgeScore": {
74
+ "type": "number",
75
+ "minimum": 0,
76
+ "maximum": 10,
77
+ "description": "Mean score across all judge dimensions."
78
+ },
79
+ "scenarioCount": {
80
+ "type": "integer",
81
+ "minimum": 1
82
+ }
83
+ }
84
+ },
85
+ "bugSignal": {
86
+ "type": "object",
87
+ "properties": {
88
+ "validationFailures": {
89
+ "type": "integer",
90
+ "minimum": 0,
91
+ "description": "Number of validation check failures."
92
+ },
93
+ "securityWarnings": {
94
+ "type": "integer",
95
+ "minimum": 0
96
+ },
97
+ "deprecationWarnings": {
98
+ "type": "integer",
99
+ "minimum": 0
100
+ }
101
+ }
102
+ },
103
+ "runtime": {
104
+ "type": "object",
105
+ "properties": {
106
+ "totalDurationMs": {
107
+ "type": "number",
108
+ "description": "Total benchmark suite execution time in milliseconds."
109
+ },
110
+ "averageScenarioDurationMs": {
111
+ "type": "number"
112
+ },
113
+ "peakMemoryMb": {
114
+ "type": "number"
115
+ }
116
+ }
117
+ },
118
+ "token": {
119
+ "type": "object",
120
+ "properties": {
121
+ "nativeSavingsPercent": {
122
+ "type": "number",
123
+ "description": "Token savings from native optimization."
124
+ },
125
+ "proxySavingsPercent": {
126
+ "type": "number",
127
+ "description": "Token savings from external proxy optimization."
128
+ },
129
+ "totalInputTokens": {
130
+ "type": "integer"
131
+ },
132
+ "totalOutputTokens": {
133
+ "type": "integer"
134
+ }
135
+ }
136
+ }
137
+ }
138
+ },
139
+ "deltaReport": {
140
+ "type": "object",
141
+ "properties": {
142
+ "top1AccuracyChange": {
143
+ "type": "number",
144
+ "description": "After minus before. Positive means improvement."
145
+ },
146
+ "manualCorrectionRateChange": {
147
+ "type": "number",
148
+ "description": "After minus before. Negative means improvement."
149
+ },
150
+ "averageJudgeScoreChange": {
151
+ "type": "number"
152
+ },
153
+ "validationFailureChange": {
154
+ "type": "integer"
155
+ },
156
+ "totalDurationMsChange": {
157
+ "type": "number"
158
+ },
159
+ "nativeSavingsChange": {
160
+ "type": "number"
161
+ },
162
+ "regressionDetected": {
163
+ "type": "boolean",
164
+ "description": "True if any metric crossed a threshold in the wrong direction."
165
+ },
166
+ "regressionDetails": {
167
+ "type": "array",
168
+ "items": {
169
+ "type": "object",
170
+ "properties": {
171
+ "metric": { "type": "string" },
172
+ "threshold": { "type": "number" },
173
+ "actual": { "type": "number" },
174
+ "direction": { "type": "string", "enum": ["increase", "decrease"] }
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+ }
181
+ }
package/.cursorrules CHANGED
@@ -1,6 +1,6 @@
1
1
  # AGENTIC-SENIOR-CORE DYNAMIC GOVERNANCE RULESET
2
2
 
3
- Generated by Agentic-Senior-Core CLI v2.0.19
3
+ Generated by Agentic-Senior-Core CLI v2.0.21
4
4
  Timestamp: 2026-04-15T00:14:51.184Z
5
5
  Selected profile: beginner
6
6
  Selected policy file: .agent-context/policies/llm-judge-threshold.json
@@ -2,7 +2,7 @@
2
2
 
3
3
  Adapter Mode: thin
4
4
  Adapter Source: .instructions.md
5
- Canonical Snapshot SHA256: 08994f6e228b32d415dcc2024f31f0a076119a3cf87a4cd2fd2e78e86e5fbd3e
5
+ Canonical Snapshot SHA256: 2a2a036b4fb90f9e668163b83614f2339044c0d021a6eaf2f380e626dfe72de0
6
6
 
7
7
  Canonical policy source: [.instructions.md](../.instructions.md).
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Adapter Mode: thin
4
4
  Adapter Source: .instructions.md
5
- Canonical Snapshot SHA256: 08994f6e228b32d415dcc2024f31f0a076119a3cf87a4cd2fd2e78e86e5fbd3e
5
+ Canonical Snapshot SHA256: 2a2a036b4fb90f9e668163b83614f2339044c0d021a6eaf2f380e626dfe72de0
6
6
 
7
7
  The canonical policy source for this repository is [.instructions.md](../.instructions.md).
8
8
 
package/.windsurfrules CHANGED
@@ -1,6 +1,6 @@
1
1
  # AGENTIC-SENIOR-CORE DYNAMIC GOVERNANCE RULESET
2
2
 
3
- Generated by Agentic-Senior-Core CLI v2.0.19
3
+ Generated by Agentic-Senior-Core CLI v2.0.21
4
4
  Timestamp: 2026-04-15T00:14:51.184Z
5
5
  Selected profile: beginner
6
6
  Selected policy file: .agent-context/policies/llm-judge-threshold.json
package/AGENTS.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Adapter Mode: thin
4
4
  Adapter Source: .instructions.md
5
- Canonical Snapshot SHA256: 08994f6e228b32d415dcc2024f31f0a076119a3cf87a4cd2fd2e78e86e5fbd3e
5
+ Canonical Snapshot SHA256: 2a2a036b4fb90f9e668163b83614f2339044c0d021a6eaf2f380e626dfe72de0
6
6
 
7
7
  This file is an adapter entrypoint for agent discovery.
8
8
  The canonical policy source is [.instructions.md](.instructions.md).
@@ -34,6 +34,14 @@ import { detectProjectContext, buildDetectionSummary, formatDetectionCandidates
34
34
  import { compileDynamicContext, writeSelectedPolicy, writeOnboardingReport } from '../compiler.mjs';
35
35
  import { runPreflightChecks } from '../preflight.mjs';
36
36
  import { createBackup } from '../backup.mjs';
37
+ import {
38
+ runProjectDiscovery,
39
+ generateProjectDocumentation,
40
+ isDirectoryEffectivelyEmpty,
41
+ hasExistingProjectDocs,
42
+ loadProjectConfig,
43
+ normalizeDocsLanguage,
44
+ } from '../project-scaffolder.mjs';
37
45
  import { performRollback } from '../rollback.mjs';
38
46
  import {
39
47
  createTokenOptimizationState,
@@ -58,6 +66,10 @@ export function parseInitArguments(commandArguments) {
58
66
  tokenOptimize: true,
59
67
  tokenAgent: 'copilot',
60
68
  includeMcpTemplate: false,
69
+ scaffoldDocs: undefined,
70
+ docsLang: 'en',
71
+ docsLangProvided: false,
72
+ projectConfig: undefined,
61
73
  };
62
74
 
63
75
  for (let argumentIndex = 0; argumentIndex < commandArguments.length; argumentIndex++) {
@@ -166,6 +178,40 @@ export function parseInitArguments(commandArguments) {
166
178
  continue;
167
179
  }
168
180
 
181
+ if (currentArgument === '--scaffold-docs') {
182
+ parsedInitOptions.scaffoldDocs = true;
183
+ continue;
184
+ }
185
+
186
+ if (currentArgument === '--no-scaffold-docs') {
187
+ parsedInitOptions.scaffoldDocs = false;
188
+ continue;
189
+ }
190
+
191
+ if (currentArgument === '--docs-lang') {
192
+ parsedInitOptions.docsLang = commandArguments[argumentIndex + 1] || 'en';
193
+ parsedInitOptions.docsLangProvided = true;
194
+ argumentIndex += 1;
195
+ continue;
196
+ }
197
+
198
+ if (currentArgument.startsWith('--docs-lang=')) {
199
+ parsedInitOptions.docsLang = currentArgument.split('=')[1] || 'en';
200
+ parsedInitOptions.docsLangProvided = true;
201
+ continue;
202
+ }
203
+
204
+ if (currentArgument === '--project-config') {
205
+ parsedInitOptions.projectConfig = commandArguments[argumentIndex + 1];
206
+ argumentIndex += 1;
207
+ continue;
208
+ }
209
+
210
+ if (currentArgument.startsWith('--project-config=')) {
211
+ parsedInitOptions.projectConfig = currentArgument.split('=')[1];
212
+ continue;
213
+ }
214
+
169
215
  throw new Error(`Unknown option: ${currentArgument}`);
170
216
  }
171
217
 
@@ -173,6 +219,12 @@ export function parseInitArguments(commandArguments) {
173
219
  throw new Error('--newbie can only be combined with --profile beginner');
174
220
  }
175
221
 
222
+ const normalizedDocsLanguage = normalizeDocsLanguage(parsedInitOptions.docsLang || 'en');
223
+ if (!normalizedDocsLanguage) {
224
+ throw new Error('--docs-lang must be one of: en, id');
225
+ }
226
+
227
+ parsedInitOptions.docsLang = normalizedDocsLanguage;
176
228
  parsedInitOptions.tokenAgent = normalizeAgentName(parsedInitOptions.tokenAgent);
177
229
 
178
230
  return parsedInitOptions;
@@ -185,6 +237,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
185
237
  : true;
186
238
  const shouldIncludeMcpTemplate = initOptions.includeMcpTemplate === true;
187
239
  const selectedTokenAgentName = normalizeAgentName(initOptions.tokenAgent || 'copilot');
240
+ const isInteractiveSession = Boolean(stdin.isTTY && stdout.isTTY);
188
241
 
189
242
  if (resolvedTargetDirectoryPath.toLowerCase() === 'c:\\windows' || resolvedTargetDirectoryPath.toLowerCase() === 'c:\\windows\\system32') {
190
243
  console.error('\n[FATAL] Target directory resolved to a Windows system folder (C:\\Windows).');
@@ -203,6 +256,9 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
203
256
  throw new Error('Preflight checks failed.');
204
257
  }
205
258
 
259
+ const wasDirectoryEffectivelyEmpty = await isDirectoryEffectivelyEmpty(resolvedTargetDirectoryPath);
260
+ const hadExistingProjectDocsBeforeInit = await hasExistingProjectDocs(resolvedTargetDirectoryPath);
261
+
206
262
  const backup = await createBackup(resolvedTargetDirectoryPath);
207
263
 
208
264
  const userInterface = createInterface({ input: stdin, output: stdout });
@@ -386,6 +442,66 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
386
442
  console.log('Installation will continue, but review these warnings before production use.');
387
443
  }
388
444
 
445
+ // --- Project Documentation Scaffolding ---
446
+ let scaffoldingResult = null;
447
+ const isFreshProjectTarget = wasDirectoryEffectivelyEmpty && !hadExistingProjectDocsBeforeInit;
448
+ const shouldOfferScaffolding = initOptions.scaffoldDocs === true
449
+ || Boolean(initOptions.projectConfig)
450
+ || (initOptions.scaffoldDocs !== false && isFreshProjectTarget);
451
+
452
+ if (shouldOfferScaffolding) {
453
+ if (initOptions.scaffoldDocs === true && !initOptions.projectConfig && !isInteractiveSession) {
454
+ throw new Error('Non-interactive scaffolding requires --project-config when --scaffold-docs is enabled.');
455
+ }
456
+
457
+ const userWantsScaffolding = initOptions.scaffoldDocs === true
458
+ || initOptions.projectConfig
459
+ || (!isInteractiveSession
460
+ ? false
461
+ : await askYesNo(
462
+ 'This is a fresh project. Want me to scaffold project documentation (architecture, database, API contract, flow)?',
463
+ userInterface,
464
+ true
465
+ ));
466
+
467
+ if (userWantsScaffolding) {
468
+ let discoveryAnswers;
469
+
470
+ if (initOptions.projectConfig) {
471
+ discoveryAnswers = await loadProjectConfig(initOptions.projectConfig);
472
+ console.log(`\nLoaded project configuration from: ${initOptions.projectConfig}`);
473
+ } else {
474
+ discoveryAnswers = await runProjectDiscovery(userInterface);
475
+ }
476
+
477
+ const normalizedConfigDocsLanguage = normalizeDocsLanguage(discoveryAnswers.docsLang || '');
478
+ if (discoveryAnswers.docsLang && !normalizedConfigDocsLanguage) {
479
+ throw new Error(`Unsupported docs language in project config: ${discoveryAnswers.docsLang}. Supported values: en, id`);
480
+ }
481
+
482
+ const selectedDocsLanguage = (!initOptions.docsLangProvided && normalizedConfigDocsLanguage)
483
+ ? normalizedConfigDocsLanguage
484
+ : initOptions.docsLang;
485
+
486
+ scaffoldingResult = await generateProjectDocumentation(
487
+ resolvedTargetDirectoryPath,
488
+ discoveryAnswers,
489
+ {
490
+ stackFileName: selectedResolvedStackFileName,
491
+ blueprintFileName: selectedResolvedBlueprintFileName,
492
+ },
493
+ {
494
+ docsLanguage: selectedDocsLanguage,
495
+ }
496
+ );
497
+
498
+ console.log(`\nProject documentation generated in docs/:`);
499
+ for (const generatedFileName of scaffoldingResult.generatedFileNames) {
500
+ console.log(` - docs/${generatedFileName}`);
501
+ }
502
+ }
503
+ }
504
+
389
505
  await compileDynamicContext({
390
506
  targetDirectoryPath: resolvedTargetDirectoryPath,
391
507
  selectedProfileName,
@@ -428,6 +544,10 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
428
544
  console.log(`- Blocking severities: ${formatBlockingSeverities(selectedProfile.blockingSeverities)}`);
429
545
  console.log(`- Setup time: ${formatDuration(setupDurationMs)}`);
430
546
  console.log('- Generated files: .cursorrules, .windsurfrules, and .agent-context/state/onboarding-report.json');
547
+ if (scaffoldingResult) {
548
+ console.log(`- Project docs: ${scaffoldingResult.generatedFileNames.length} files generated in docs/`);
549
+ console.log(`- Project docs language: ${scaffoldingResult.docsLanguage}`);
550
+ }
431
551
  console.log(`- Repository workflows copied: no (workflows remain source-repo assets)`);
432
552
  console.log(`- MCP template file: ${shouldIncludeMcpTemplate ? 'created (.vscode/mcp.json)' : 'not created by default (use --mcp-template)'}`);
433
553
  if (isTokenOptimizationEnabled) {
@@ -437,6 +557,9 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
437
557
  }
438
558
  console.log('\nPlain-language summary:');
439
559
  console.log(`I prepared a ${selectedProfile.displayName.toLowerCase()} governance pack for a ${toTitleCase(selectedResolvedStackFileName)} project using the ${toTitleCase(selectedResolvedBlueprintFileName)} blueprint.`);
560
+ if (scaffoldingResult) {
561
+ console.log(`I also generated project documentation (${scaffoldingResult.docsLanguage}) based on your project description. AI agents will use docs/ as project context.`);
562
+ }
440
563
  console.log('Your AI tools will now receive one compiled rulebook plus the original source rules, and your review threshold is stored in .agent-context/policies/llm-judge-threshold.json.');
441
564
  console.log('MCP server registration is manual inside your IDE settings, even when mcp.json exists.');
442
565
  } catch (error) {
@@ -37,6 +37,7 @@ import { createBackup } from '../backup.mjs';
37
37
  import { performRollback } from '../rollback.mjs';
38
38
  import { inferSkillDomainNamesFromSelection } from '../skill-selector.mjs';
39
39
  import { evaluateSkillDomainCompatibility } from '../compatibility.mjs';
40
+ import { detectProjectDocTemplateStaleness } from '../project-scaffolder.mjs';
40
41
 
41
42
  export function parseUpgradeArguments(commandArguments) {
42
43
  const parsedUpgradeOptions = {
@@ -134,6 +135,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
134
135
  resolvedTargetDirectoryPath,
135
136
  selectedSkillDomainNames
136
137
  );
138
+ const projectDocStalenessReport = await detectProjectDocTemplateStaleness(resolvedTargetDirectoryPath);
137
139
 
138
140
  if (compatibilityWarnings.length > 0) {
139
141
  console.log('\n[WARN] Compatibility checks reported potential issues for this environment:');
@@ -169,6 +171,20 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
169
171
  console.log(`- Existing rules lines: ${currentRuleLineCount}`);
170
172
  console.log(`- Planned rules lines: ${plannedRuleLineCount}`);
171
173
  console.log(`- Rules changed: ${isRulesContentChanged ? 'yes' : 'no'}`);
174
+ if (projectDocStalenessReport.hasProjectDocs) {
175
+ console.log(`- Project docs detected: ${projectDocStalenessReport.checkedFileNames.length}`);
176
+ console.log(`- Project docs expected template version: ${projectDocStalenessReport.expectedTemplateVersion}`);
177
+ console.log(`- Project docs stale files: ${projectDocStalenessReport.staleFiles.length}`);
178
+ }
179
+
180
+ if (projectDocStalenessReport.staleFiles.length > 0) {
181
+ console.log('\n[WARN] Some project docs were generated from older template versions:');
182
+ for (const staleDoc of projectDocStalenessReport.staleFiles) {
183
+ const detectedVersionLabel = staleDoc.detectedTemplateVersion || 'missing';
184
+ console.log(`- docs/${staleDoc.fileName} (detected: ${detectedVersionLabel}, expected: ${projectDocStalenessReport.expectedTemplateVersion})`);
185
+ }
186
+ console.log('Recommendation: regenerate docs with init --scaffold-docs or update the files manually to match the latest template version.');
187
+ }
172
188
 
173
189
  if (upgradeOptions.dryRun) {
174
190
  console.log('\nDry run enabled. No files were modified.');
@@ -236,6 +236,37 @@ export async function buildCompiledRulesContent({
236
236
  ].join('\n')
237
237
  );
238
238
 
239
+ const projectBriefPath = path.join(resolvedTargetDirectoryPath, 'docs', 'project-brief.md');
240
+ if (await pathExists(projectBriefPath)) {
241
+ const projectDocsEntries = ['project-brief.md'];
242
+ const candidateDocFileNames = [
243
+ 'architecture-decision-record.md',
244
+ 'database-schema.md',
245
+ 'api-contract.md',
246
+ 'flow-overview.md',
247
+ ];
248
+
249
+ for (const candidateFileName of candidateDocFileNames) {
250
+ const candidateFilePath = path.join(resolvedTargetDirectoryPath, 'docs', candidateFileName);
251
+ if (await pathExists(candidateFilePath)) {
252
+ projectDocsEntries.push(candidateFileName);
253
+ }
254
+ }
255
+
256
+ contextBlocks.push(
257
+ [
258
+ '## LAYER 9: PROJECT CONTEXT (MANDATORY)',
259
+ 'These documents describe the specific project being built.',
260
+ 'Read them before writing any application code:',
261
+ ...projectDocsEntries.map((docFileName, docIndex) => `${docIndex + 1}. docs/${docFileName}`),
262
+ '',
263
+ 'These docs were generated during project initialization and reflect the architecture,',
264
+ 'database design, API contracts, and application flows chosen for this project.',
265
+ 'Update them as the project evolves. They are living references, not frozen specs.',
266
+ ].join('\n')
267
+ );
268
+ }
269
+
239
270
  return [
240
271
  '# AGENTIC-SENIOR-CORE DYNAMIC GOVERNANCE RULESET',
241
272
  '',