@ryuenn3123/agentic-senior-core 2.0.20 → 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.
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.20
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/.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.20
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
@@ -40,6 +40,7 @@ import {
40
40
  isDirectoryEffectivelyEmpty,
41
41
  hasExistingProjectDocs,
42
42
  loadProjectConfig,
43
+ normalizeDocsLanguage,
43
44
  } from '../project-scaffolder.mjs';
44
45
  import { performRollback } from '../rollback.mjs';
45
46
  import {
@@ -67,6 +68,7 @@ export function parseInitArguments(commandArguments) {
67
68
  includeMcpTemplate: false,
68
69
  scaffoldDocs: undefined,
69
70
  docsLang: 'en',
71
+ docsLangProvided: false,
70
72
  projectConfig: undefined,
71
73
  };
72
74
 
@@ -188,12 +190,14 @@ export function parseInitArguments(commandArguments) {
188
190
 
189
191
  if (currentArgument === '--docs-lang') {
190
192
  parsedInitOptions.docsLang = commandArguments[argumentIndex + 1] || 'en';
193
+ parsedInitOptions.docsLangProvided = true;
191
194
  argumentIndex += 1;
192
195
  continue;
193
196
  }
194
197
 
195
198
  if (currentArgument.startsWith('--docs-lang=')) {
196
199
  parsedInitOptions.docsLang = currentArgument.split('=')[1] || 'en';
200
+ parsedInitOptions.docsLangProvided = true;
197
201
  continue;
198
202
  }
199
203
 
@@ -215,6 +219,12 @@ export function parseInitArguments(commandArguments) {
215
219
  throw new Error('--newbie can only be combined with --profile beginner');
216
220
  }
217
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;
218
228
  parsedInitOptions.tokenAgent = normalizeAgentName(parsedInitOptions.tokenAgent);
219
229
 
220
230
  return parsedInitOptions;
@@ -227,6 +237,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
227
237
  : true;
228
238
  const shouldIncludeMcpTemplate = initOptions.includeMcpTemplate === true;
229
239
  const selectedTokenAgentName = normalizeAgentName(initOptions.tokenAgent || 'copilot');
240
+ const isInteractiveSession = Boolean(stdin.isTTY && stdout.isTTY);
230
241
 
231
242
  if (resolvedTargetDirectoryPath.toLowerCase() === 'c:\\windows' || resolvedTargetDirectoryPath.toLowerCase() === 'c:\\windows\\system32') {
232
243
  console.error('\n[FATAL] Target directory resolved to a Windows system folder (C:\\Windows).');
@@ -245,6 +256,9 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
245
256
  throw new Error('Preflight checks failed.');
246
257
  }
247
258
 
259
+ const wasDirectoryEffectivelyEmpty = await isDirectoryEffectivelyEmpty(resolvedTargetDirectoryPath);
260
+ const hadExistingProjectDocsBeforeInit = await hasExistingProjectDocs(resolvedTargetDirectoryPath);
261
+
248
262
  const backup = await createBackup(resolvedTargetDirectoryPath);
249
263
 
250
264
  const userInterface = createInterface({ input: stdin, output: stdout });
@@ -428,46 +442,27 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
428
442
  console.log('Installation will continue, but review these warnings before production use.');
429
443
  }
430
444
 
431
- await compileDynamicContext({
432
- targetDirectoryPath: resolvedTargetDirectoryPath,
433
- selectedProfileName,
434
- selectedProfilePack,
435
- selectedStackFileName: selectedResolvedStackFileName,
436
- selectedBlueprintFileName: selectedResolvedBlueprintFileName,
437
- includeCiGuardrails,
438
- });
439
-
440
- await writeSelectedPolicy(resolvedTargetDirectoryPath, selectedProfileName);
441
-
442
- const setupDurationMs = Date.now() - setupStartedAt;
443
- await writeOnboardingReport({
444
- targetDirectoryPath: resolvedTargetDirectoryPath,
445
- selectedProfileName,
446
- selectedProfilePack,
447
- selectedPreset: initOptions.preset || null,
448
- selectedStackFileName: selectedResolvedStackFileName,
449
- selectedBlueprintFileName: selectedResolvedBlueprintFileName,
450
- includeCiGuardrails,
451
- setupDurationMs,
452
- projectDetection,
453
- selectedSkillDomains: selectedSkillDomainNames,
454
- compatibilityWarnings,
455
- operationMode: 'init',
456
- });
457
-
458
445
  // --- Project Documentation Scaffolding ---
459
446
  let scaffoldingResult = null;
447
+ const isFreshProjectTarget = wasDirectoryEffectivelyEmpty && !hadExistingProjectDocsBeforeInit;
460
448
  const shouldOfferScaffolding = initOptions.scaffoldDocs === true
461
- || (initOptions.scaffoldDocs !== false && await isDirectoryEffectivelyEmpty(resolvedTargetDirectoryPath) && !(await hasExistingProjectDocs(resolvedTargetDirectoryPath)));
449
+ || Boolean(initOptions.projectConfig)
450
+ || (initOptions.scaffoldDocs !== false && isFreshProjectTarget);
462
451
 
463
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
+
464
457
  const userWantsScaffolding = initOptions.scaffoldDocs === true
465
458
  || initOptions.projectConfig
466
- || await askYesNo(
467
- 'This is a fresh project. Want me to scaffold project documentation (architecture, database, API contract, flow)?',
468
- userInterface,
469
- true
470
- );
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
+ ));
471
466
 
472
467
  if (userWantsScaffolding) {
473
468
  let discoveryAnswers;
@@ -479,12 +474,24 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
479
474
  discoveryAnswers = await runProjectDiscovery(userInterface);
480
475
  }
481
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
+
482
486
  scaffoldingResult = await generateProjectDocumentation(
483
487
  resolvedTargetDirectoryPath,
484
488
  discoveryAnswers,
485
489
  {
486
490
  stackFileName: selectedResolvedStackFileName,
487
491
  blueprintFileName: selectedResolvedBlueprintFileName,
492
+ },
493
+ {
494
+ docsLanguage: selectedDocsLanguage,
488
495
  }
489
496
  );
490
497
 
@@ -495,6 +502,33 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
495
502
  }
496
503
  }
497
504
 
505
+ await compileDynamicContext({
506
+ targetDirectoryPath: resolvedTargetDirectoryPath,
507
+ selectedProfileName,
508
+ selectedProfilePack,
509
+ selectedStackFileName: selectedResolvedStackFileName,
510
+ selectedBlueprintFileName: selectedResolvedBlueprintFileName,
511
+ includeCiGuardrails,
512
+ });
513
+
514
+ await writeSelectedPolicy(resolvedTargetDirectoryPath, selectedProfileName);
515
+
516
+ const setupDurationMs = Date.now() - setupStartedAt;
517
+ await writeOnboardingReport({
518
+ targetDirectoryPath: resolvedTargetDirectoryPath,
519
+ selectedProfileName,
520
+ selectedProfilePack,
521
+ selectedPreset: initOptions.preset || null,
522
+ selectedStackFileName: selectedResolvedStackFileName,
523
+ selectedBlueprintFileName: selectedResolvedBlueprintFileName,
524
+ includeCiGuardrails,
525
+ setupDurationMs,
526
+ projectDetection,
527
+ selectedSkillDomains: selectedSkillDomainNames,
528
+ compatibilityWarnings,
529
+ operationMode: 'init',
530
+ });
531
+
498
532
  console.log('\nInitialization complete.');
499
533
  console.log(`- Target directory: ${resolvedTargetDirectoryPath}`);
500
534
  console.log(`- Profile: ${selectedProfile.displayName}`);
@@ -512,6 +546,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
512
546
  console.log('- Generated files: .cursorrules, .windsurfrules, and .agent-context/state/onboarding-report.json');
513
547
  if (scaffoldingResult) {
514
548
  console.log(`- Project docs: ${scaffoldingResult.generatedFileNames.length} files generated in docs/`);
549
+ console.log(`- Project docs language: ${scaffoldingResult.docsLanguage}`);
515
550
  }
516
551
  console.log(`- Repository workflows copied: no (workflows remain source-repo assets)`);
517
552
  console.log(`- MCP template file: ${shouldIncludeMcpTemplate ? 'created (.vscode/mcp.json)' : 'not created by default (use --mcp-template)'}`);
@@ -523,7 +558,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
523
558
  console.log('\nPlain-language summary:');
524
559
  console.log(`I prepared a ${selectedProfile.displayName.toLowerCase()} governance pack for a ${toTitleCase(selectedResolvedStackFileName)} project using the ${toTitleCase(selectedResolvedBlueprintFileName)} blueprint.`);
525
560
  if (scaffoldingResult) {
526
- console.log(`I also generated project documentation based on your project description. AI agents will use docs/ as project context.`);
561
+ console.log(`I also generated project documentation (${scaffoldingResult.docsLanguage}) based on your project description. AI agents will use docs/ as project context.`);
527
562
  }
528
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.');
529
564
  console.log('MCP server registration is manual inside your IDE settings, even when mcp.json exists.');
@@ -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.');
@@ -8,11 +8,21 @@ import path from 'node:path';
8
8
  import { fileURLToPath } from 'node:url';
9
9
 
10
10
  import { CLI_VERSION } from './constants.mjs';
11
- import { ensureDirectory, askChoice, askYesNo, toTitleCase, pathExists } from './utils.mjs';
11
+ import { ensureDirectory, askChoice, toTitleCase, pathExists } from './utils.mjs';
12
12
 
13
13
  const CURRENT_FILE_PATH = fileURLToPath(import.meta.url);
14
14
  const CURRENT_DIRECTORY_PATH = path.dirname(CURRENT_FILE_PATH);
15
15
  const TEMPLATES_DIRECTORY_PATH = path.join(CURRENT_DIRECTORY_PATH, 'templates');
16
+ const SUPPORTED_DOC_LANGUAGES = new Set(['en', 'id']);
17
+ const PROJECT_DOC_FILE_NAMES = [
18
+ 'project-brief.md',
19
+ 'architecture-decision-record.md',
20
+ 'database-schema.md',
21
+ 'api-contract.md',
22
+ 'flow-overview.md',
23
+ ];
24
+
25
+ export const PROJECT_DOC_TEMPLATE_VERSION = '1.1.0';
16
26
 
17
27
  const DOMAIN_CHOICES = [
18
28
  'API service',
@@ -40,6 +50,35 @@ const AUTH_CHOICES = [
40
50
  'Other',
41
51
  ];
42
52
 
53
+ export function normalizeDocsLanguage(rawDocsLanguage = 'en') {
54
+ const normalizedDocsLanguage = String(rawDocsLanguage || 'en').trim().toLowerCase();
55
+ return SUPPORTED_DOC_LANGUAGES.has(normalizedDocsLanguage) ? normalizedDocsLanguage : null;
56
+ }
57
+
58
+ function resolveLocalizedTemplateFileName(templateFileName, docsLanguage) {
59
+ if (docsLanguage === 'en') {
60
+ return templateFileName;
61
+ }
62
+
63
+ return templateFileName.replace(/\.md\.tmpl$/i, `.md.${docsLanguage}.tmpl`);
64
+ }
65
+
66
+ async function resolveTemplateFilePath(templateFileName, docsLanguage) {
67
+ const localizedTemplateFileName = resolveLocalizedTemplateFileName(templateFileName, docsLanguage);
68
+ const localizedTemplateFilePath = path.join(TEMPLATES_DIRECTORY_PATH, localizedTemplateFileName);
69
+
70
+ if (await pathExists(localizedTemplateFilePath)) {
71
+ return localizedTemplateFilePath;
72
+ }
73
+
74
+ const defaultTemplateFilePath = path.join(TEMPLATES_DIRECTORY_PATH, templateFileName);
75
+ if (await pathExists(defaultTemplateFilePath)) {
76
+ return defaultTemplateFilePath;
77
+ }
78
+
79
+ return null;
80
+ }
81
+
43
82
  /**
44
83
  * Run the project discovery interview.
45
84
  * Returns a structured object with all user responses.
@@ -189,6 +228,7 @@ export function buildTemplateContext(discoveryAnswers, initContext) {
189
228
  blueprintFileName: initContext.blueprintFileName,
190
229
  blueprintDisplayName: toTitleCase(initContext.blueprintFileName),
191
230
  cliVersion: CLI_VERSION,
231
+ templateVersion: PROJECT_DOC_TEMPLATE_VERSION,
192
232
  generatedAt: new Date().toISOString(),
193
233
  generatedDate: new Date().toISOString().split('T')[0],
194
234
  hasDatabase,
@@ -259,8 +299,14 @@ export function renderTemplate(templateContent, templateContext) {
259
299
  export async function generateProjectDocumentation(
260
300
  targetDirectoryPath,
261
301
  discoveryAnswers,
262
- initContext
302
+ initContext,
303
+ options = {}
263
304
  ) {
305
+ const normalizedDocsLanguage = normalizeDocsLanguage(options.docsLanguage || 'en');
306
+ if (!normalizedDocsLanguage) {
307
+ throw new Error(`Unsupported docs language: ${options.docsLanguage}. Supported values: en, id`);
308
+ }
309
+
264
310
  const docsDirectoryPath = path.join(targetDirectoryPath, 'docs');
265
311
  await ensureDirectory(docsDirectoryPath);
266
312
 
@@ -269,9 +315,12 @@ export async function generateProjectDocumentation(
269
315
  const generatedFileNames = [];
270
316
 
271
317
  for (const documentEntry of documentManifest) {
272
- const templateFilePath = path.join(TEMPLATES_DIRECTORY_PATH, documentEntry.templateFileName);
318
+ const templateFilePath = await resolveTemplateFilePath(
319
+ documentEntry.templateFileName,
320
+ normalizedDocsLanguage
321
+ );
273
322
 
274
- if (!(await pathExists(templateFilePath))) {
323
+ if (!templateFilePath) {
275
324
  console.log(`[WARN] Template not found: ${documentEntry.templateFileName}, skipping.`);
276
325
  continue;
277
326
  }
@@ -287,7 +336,8 @@ export async function generateProjectDocumentation(
287
336
  return {
288
337
  docsDirectoryPath,
289
338
  generatedFileNames,
290
- templateVersion: '1.0.0',
339
+ templateVersion: PROJECT_DOC_TEMPLATE_VERSION,
340
+ docsLanguage: normalizedDocsLanguage,
291
341
  discoveryAnswers,
292
342
  };
293
343
  }
@@ -316,6 +366,42 @@ export async function hasExistingProjectDocs(targetDirectoryPath) {
316
366
  return pathExists(projectBriefPath);
317
367
  }
318
368
 
369
+ function extractTemplateVersion(documentContent) {
370
+ const templateVersionMatch = documentContent.match(/^(?:Template version|Versi template):\s*(.+)$/im);
371
+ return templateVersionMatch ? templateVersionMatch[1].trim() : null;
372
+ }
373
+
374
+ export async function detectProjectDocTemplateStaleness(targetDirectoryPath) {
375
+ const docsDirectoryPath = path.join(targetDirectoryPath, 'docs');
376
+ const checkedFileNames = [];
377
+ const staleFiles = [];
378
+
379
+ for (const projectDocFileName of PROJECT_DOC_FILE_NAMES) {
380
+ const projectDocFilePath = path.join(docsDirectoryPath, projectDocFileName);
381
+ if (!(await pathExists(projectDocFilePath))) {
382
+ continue;
383
+ }
384
+
385
+ checkedFileNames.push(projectDocFileName);
386
+ const projectDocContent = await fs.readFile(projectDocFilePath, 'utf8');
387
+ const detectedTemplateVersion = extractTemplateVersion(projectDocContent);
388
+
389
+ if (!detectedTemplateVersion || detectedTemplateVersion !== PROJECT_DOC_TEMPLATE_VERSION) {
390
+ staleFiles.push({
391
+ fileName: projectDocFileName,
392
+ detectedTemplateVersion,
393
+ });
394
+ }
395
+ }
396
+
397
+ return {
398
+ hasProjectDocs: checkedFileNames.length > 0,
399
+ expectedTemplateVersion: PROJECT_DOC_TEMPLATE_VERSION,
400
+ checkedFileNames,
401
+ staleFiles,
402
+ };
403
+ }
404
+
319
405
  /**
320
406
  * Load project config from a YAML-like file for non-interactive mode.
321
407
  * Uses a simple key: value format (one per line) for zero-dependency parsing.
@@ -374,5 +460,6 @@ export async function loadProjectConfig(configFilePath) {
374
460
  authStrategy: configEntries.authStrategy || configEntries.auth || 'None (public service)',
375
461
  features: Array.isArray(configEntries.features) ? configEntries.features : [],
376
462
  additionalContext: configEntries.additionalContext || configEntries.context || 'No additional context provided.',
463
+ docsLang: configEntries.docsLang || configEntries.docsLanguage || 'en',
377
464
  };
378
465
  }
@@ -0,0 +1,143 @@
1
+ # Kontrak API: {{projectName}}
2
+
3
+ Dibuat oleh Agentic-Senior-Core CLI v{{cliVersion}}
4
+ Dibuat pada: {{generatedAt}}
5
+ Versi template: {{templateVersion}}
6
+
7
+ ---
8
+
9
+ ## Prinsip Desain API
10
+
11
+ Mengacu ke `.agent-context/rules/api-docs.md`:
12
+ - OpenAPI 3.1 wajib untuk semua HTTP API.
13
+ - Setiap endpoint harus mendokumentasikan skema request/response.
14
+ - Error response harus pakai error code terstruktur, bukan string mentah.
15
+ - Validasi input wajib di semua endpoint.
16
+
17
+ ## Base URL
18
+
19
+ ```
20
+ {{baseUrl}}
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Endpoint
26
+
27
+ ### Health Check
28
+
29
+ ```
30
+ GET /health
31
+ ```
32
+
33
+ Response `200`:
34
+ ```json
35
+ {
36
+ "status": "ok",
37
+ "version": "1.0.0",
38
+ "timestamp": "2026-01-01T00:00:00Z"
39
+ }
40
+ ```
41
+
42
+ {{#if hasAuth}}
43
+ ### Autentikasi
44
+
45
+ ```
46
+ POST /auth/register
47
+ ```
48
+ Request:
49
+ ```json
50
+ {
51
+ "email": "user@example.com",
52
+ "password": "secure-password",
53
+ "displayName": "User Name"
54
+ }
55
+ ```
56
+
57
+ ```
58
+ POST /auth/login
59
+ ```
60
+ Request:
61
+ ```json
62
+ {
63
+ "email": "user@example.com",
64
+ "password": "secure-password"
65
+ }
66
+ ```
67
+ Response `200`:
68
+ ```json
69
+ {
70
+ "token": "jwt-token-here",
71
+ "expiresIn": 3600
72
+ }
73
+ ```
74
+
75
+ {{/if}}
76
+ ### Endpoint Fitur
77
+
78
+ Berdasarkan fitur proyek, rencanakan grup endpoint berikut:
79
+
80
+ {{#each features}}
81
+ #### {{this}}
82
+
83
+ ```
84
+ GET /api/[resource] - List
85
+ GET /api/[resource]/:id - Detail
86
+ POST /api/[resource] - Create
87
+ PUT /api/[resource]/:id - Update
88
+ DELETE /api/[resource]/:id - Delete
89
+ ```
90
+
91
+ {{/each}}
92
+
93
+ ---
94
+
95
+ ## Format Error Response
96
+
97
+ Semua error response mengikuti struktur ini:
98
+
99
+ ```json
100
+ {
101
+ "error": {
102
+ "code": "VALIDATION_ERROR",
103
+ "message": "Deskripsi yang bisa dibaca manusia",
104
+ "details": []
105
+ }
106
+ }
107
+ ```
108
+
109
+ Kode error standar:
110
+ - `VALIDATION_ERROR` (400)
111
+ - `UNAUTHORIZED` (401)
112
+ - `FORBIDDEN` (403)
113
+ - `NOT_FOUND` (404)
114
+ - `CONFLICT` (409)
115
+ - `INTERNAL_ERROR` (500)
116
+
117
+ ---
118
+
119
+ ## Pagination
120
+
121
+ Endpoint list menggunakan cursor-based atau offset-based pagination:
122
+
123
+ ```
124
+ GET /api/[resource]?page=1&limit=20
125
+ ```
126
+
127
+ Response mencakup:
128
+ ```json
129
+ {
130
+ "data": [],
131
+ "pagination": {
132
+ "page": 1,
133
+ "limit": 20,
134
+ "total": 100,
135
+ "totalPages": 5
136
+ }
137
+ }
138
+ ```
139
+
140
+ ---
141
+
142
+ Dokumen ini adalah referensi hidup. Perbarui saat endpoint API diimplementasikan.
143
+ Jaga file OpenAPI 3.1 tetap sinkron dengan dokumen ini.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Generated by Agentic-Senior-Core CLI v{{cliVersion}}
4
4
  Generated at: {{generatedAt}}
5
- Template version: 1.0.0
5
+ Template version: {{templateVersion}}
6
6
 
7
7
  ---
8
8
 
@@ -0,0 +1,106 @@
1
+ # Catatan Keputusan Arsitektur: {{projectName}}
2
+
3
+ Dibuat oleh Agentic-Senior-Core CLI v{{cliVersion}}
4
+ Dibuat pada: {{generatedAt}}
5
+ Versi template: {{templateVersion}}
6
+
7
+ ---
8
+
9
+ ## ADR-001: Pemilihan Stack Teknologi
10
+
11
+ **Status**: Disetujui
12
+ **Tanggal**: {{generatedDate}}
13
+
14
+ ### Konteks
15
+
16
+ Proyek ini membutuhkan solusi {{primaryDomain}}. Tim mengevaluasi profil stack dan blueprint dari repository governance Agentic-Senior-Core.
17
+
18
+ ### Keputusan
19
+
20
+ - **Bahasa/Runtime**: {{stackDisplayName}} (sumber: `.agent-context/stacks/{{stackFileName}}`)
21
+ - **Blueprint arsitektur**: {{blueprintDisplayName}} (sumber: `.agent-context/blueprints/{{blueprintFileName}}`)
22
+ - **Database**: {{databaseChoice}}
23
+ - **Autentikasi**: {{authStrategy}}
24
+
25
+ ### Alasan
26
+
27
+ Stack {{stackDisplayName}} dipilih karena:
28
+ - Selaras dengan domain proyek ({{primaryDomain}}).
29
+ - Repository governance menyediakan blueprint tervalidasi untuk stack ini.
30
+ - Tim memiliki skill pack yang relevan untuk teknologi ini.
31
+
32
+ ### Konsekuensi
33
+
34
+ - Semua kode harus mengikuti konvensi di `.agent-context/stacks/{{stackFileName}}`.
35
+ - Batas modul harus mengikuti `.agent-context/blueprints/{{blueprintFileName}}`.
36
+ - Akses database harus mengikuti `.agent-context/rules/database-design.md`.
37
+ - Kontrak API harus mengikuti `.agent-context/rules/api-docs.md`.
38
+
39
+ ---
40
+
41
+ ## ADR-002: Pola Arsitektur
42
+
43
+ **Status**: Disetujui
44
+ **Tanggal**: {{generatedDate}}
45
+
46
+ ### Konteks
47
+
48
+ Proyek membutuhkan pemisahan concern yang jelas agar tetap mudah dirawat saat skala bertambah.
49
+
50
+ ### Keputusan
51
+
52
+ Gunakan arsitektur berlapis **Transport - Service - Repository** seperti di `.agent-context/rules/architecture.md`.
53
+
54
+ {{#if hasDatabase}}
55
+ ### Lapisan Database
56
+
57
+ - Database utama: {{databaseChoice}}
58
+ - Strategi ORM/query: ikuti konvensi stack yang dipilih.
59
+ - Strategi migrasi: migrasi aman dan reversible sesuai `.agent-context/rules/database-design.md`.
60
+ {{/if}}
61
+
62
+ {{#if hasAuth}}
63
+ ### Lapisan Autentikasi
64
+
65
+ - Strategi: {{authStrategy}}
66
+ - Manajemen secret: tidak boleh hardcoded sesuai `.agent-context/rules/security.md`.
67
+ - Validasi input: wajib di semua endpoint auth sesuai `.agent-context/rules/security.md`.
68
+ {{/if}}
69
+
70
+ ### Konsekuensi
71
+
72
+ - Setiap modul harus menjaga pemisahan tiga lapis.
73
+ - Import lintas lapis dilarang (transport tidak boleh akses repository langsung).
74
+ - Logic bersama dipindah ke modul shared, bukan di handler transport.
75
+
76
+ ---
77
+
78
+ ## ADR-003: Struktur Proyek
79
+
80
+ **Status**: Disetujui
81
+ **Tanggal**: {{generatedDate}}
82
+
83
+ ### Keputusan
84
+
85
+ Struktur direktori proyek mengikuti blueprint terpilih (`{{blueprintDisplayName}}`). Direktori utama:
86
+
87
+ ```
88
+ {{projectName}}/
89
+ src/
90
+ modules/ - modul fitur (masing-masing berisi transport, service, repository)
91
+ shared/ - utilitas, tipe, konstanta bersama
92
+ config/ - konfigurasi environment dan aplikasi
93
+ docs/ - dokumentasi proyek (direktori ini)
94
+ tests/ - test suites
95
+ .agent-context/ - aturan dan kebijakan governance
96
+ ```
97
+
98
+ ### Konsekuensi
99
+
100
+ - Fitur baru ditambahkan sebagai modul mandiri.
101
+ - Kode shared diekstrak jika dipakai oleh dua modul atau lebih.
102
+ - Konfigurasi dipusatkan dan divalidasi saat startup.
103
+
104
+ ---
105
+
106
+ Tambahkan ADR baru di bawah ini saat ada keputusan arsitektur baru.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Generated by Agentic-Senior-Core CLI v{{cliVersion}}
4
4
  Generated at: {{generatedAt}}
5
- Template version: 1.0.0
5
+ Template version: {{templateVersion}}
6
6
 
7
7
  ---
8
8
 
@@ -0,0 +1,74 @@
1
+ # Skema Database: {{projectName}}
2
+
3
+ Dibuat oleh Agentic-Senior-Core CLI v{{cliVersion}}
4
+ Dibuat pada: {{generatedAt}}
5
+ Versi template: {{templateVersion}}
6
+
7
+ ---
8
+
9
+ ## Teknologi Database
10
+
11
+ **Tipe**: {{databaseChoice}}
12
+ **Strategi autentikasi**: {{authStrategy}}
13
+
14
+ ## Prinsip Desain Skema
15
+
16
+ Mengacu ke `.agent-context/rules/database-design.md`:
17
+ - Gunakan Third Normal Form (3NF) sebagai default kecuali ada bukti performa untuk denormalisasi.
18
+ - Gunakan migrasi aman dan reversible untuk setiap perubahan skema.
19
+ - Jangan gunakan raw SQL tanpa parameterized query.
20
+ - Tambahkan index berdasarkan pola query terukur, bukan asumsi.
21
+
22
+ ---
23
+
24
+ ## Tabel Inti
25
+
26
+ {{#if hasAuth}}
27
+ ### users
28
+
29
+ | Kolom | Tipe | Constraint | Catatan |
30
+ |------|------|------------|---------|
31
+ | id | UUID / BIGINT | PK, NOT NULL | Identifier utama |
32
+ | email | VARCHAR(255) | UNIQUE, NOT NULL | Kredensial login |
33
+ | password_hash | VARCHAR(255) | NOT NULL | Hash bcrypt/argon2 |
34
+ | display_name | VARCHAR(100) | NOT NULL | Nama tampilan |
35
+ | role | VARCHAR(50) | NOT NULL, DEFAULT 'user' | Role akses |
36
+ | created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | Waktu buat |
37
+ | updated_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | Waktu ubah |
38
+
39
+ {{/if}}
40
+ ### [Definisikan tabel domain Anda di sini]
41
+
42
+ Berdasarkan fitur proyek:
43
+ {{#each features}}
44
+ - **{{this}}** - tentukan data apa yang perlu disimpan, dibaca, dan di-query.
45
+ {{/each}}
46
+
47
+ | Kolom | Tipe | Constraint | Catatan |
48
+ |------|------|------------|---------|
49
+ | id | UUID / BIGINT | PK, NOT NULL | Identifier utama |
50
+ | ... | ... | ... | Definisikan sesuai kebutuhan fitur |
51
+ | created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | Waktu buat |
52
+ | updated_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | Waktu ubah |
53
+
54
+ ---
55
+
56
+ ## Strategi Migrasi
57
+
58
+ 1. **Create**: buat file migrasi baru untuk setiap perubahan skema.
59
+ 2. **Test**: uji migrasi di lokal/staging sebelum produksi.
60
+ 3. **Rollback**: setiap migrasi wajib punya script down/rollback.
61
+ 4. **Review**: perubahan skema wajib review sesuai `.agent-context/review-checklists/pr-checklist.md`.
62
+
63
+ ## Index
64
+
65
+ Tambahkan index berdasarkan pola query yang benar-benar muncul selama development:
66
+
67
+ | Tabel | Kolom | Tipe | Alasan |
68
+ |-------|-------|------|--------|
69
+ | users | email | UNIQUE | Lookup login |
70
+ | ... | ... | ... | Tambahkan saat pola query muncul |
71
+
72
+ ---
73
+
74
+ Dokumen ini adalah referensi hidup. Perbarui saat model data berkembang.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Generated by Agentic-Senior-Core CLI v{{cliVersion}}
4
4
  Generated at: {{generatedAt}}
5
- Template version: 1.0.0
5
+ Template version: {{templateVersion}}
6
6
 
7
7
  ---
8
8
 
@@ -0,0 +1,118 @@
1
+ # Ikhtisar Flow: {{projectName}}
2
+
3
+ Dibuat oleh Agentic-Senior-Core CLI v{{cliVersion}}
4
+ Dibuat pada: {{generatedAt}}
5
+ Versi template: {{templateVersion}}
6
+
7
+ ---
8
+
9
+ ## Ikhtisar Sistem
10
+
11
+ **Proyek**: {{projectName}}
12
+ **Domain**: {{primaryDomain}}
13
+ **Stack**: {{stackDisplayName}}
14
+ **Blueprint**: {{blueprintDisplayName}}
15
+
16
+ ## Arsitektur Tingkat Tinggi
17
+
18
+ ```
19
+ +-------------+ +--------------+ +--------------+
20
+ | Client |---->| Transport |---->| Service |
21
+ | (Browser/ |<----| Layer |<----| Layer |
22
+ | Mobile/CLI) | | (Routes/ | | (Business |
23
+ | | | Handlers) | | Logic) |
24
+ +-------------+ +--------------+ +------+-------+
25
+ |
26
+ +------+-------+
27
+ | Repository |
28
+ | Layer |
29
+ | (Data Access)|
30
+ +------+-------+
31
+ |
32
+ +------+-------+
33
+ | Database |
34
+ | {{databaseChoice}} |
35
+ +--------------+
36
+ ```
37
+
38
+ ## Flow Request
39
+
40
+ ### Siklus Request Standar
41
+
42
+ 1. **Client** mengirim HTTP request (atau input CLI, atau event trigger).
43
+ 2. **Transport layer** menerima request, memvalidasi format input, lalu routing ke handler yang tepat.
44
+ 3. **Service layer** menerapkan business logic, orkestrasi operasi domain, dan enforcement aturan.
45
+ 4. **Repository layer** melakukan akses data (read/write ke database atau layanan eksternal).
46
+ 5. **Response** kembali dari Service ke Transport lalu ke Client.
47
+
48
+ ### Tanggung Jawab Layer
49
+
50
+ | Layer | Melakukan | Tidak melakukan |
51
+ |-------|-----------|-----------------|
52
+ | Transport | Parse input, validasi shape, routing, format response | Business logic, akses database |
53
+ | Service | Business rules, orkestrasi, validasi domain | Parse HTTP, format response, menjalankan SQL |
54
+ | Repository | Akses data, query, caching | Business logic, validasi input |
55
+
56
+ {{#if hasAuth}}
57
+ ## Flow Autentikasi
58
+
59
+ ```
60
+ +--------+ +-----------+ +-----------+ +-----------+
61
+ | Client |---->| Auth |---->| Token |---->| Protected |
62
+ | | | Endpoint | | Verify | | Resource |
63
+ | |<----| |<----| ({{authStrategy}}) |<----| |
64
+ +--------+ +-----------+ +-----------+ +-----------+
65
+ ```
66
+
67
+ 1. Client mengirim kredensial ke endpoint auth.
68
+ 2. Service memvalidasi kredensial terhadap data tersimpan.
69
+ 3. Jika sukses, service mengeluarkan token {{authStrategy}}.
70
+ 4. Client menyertakan token di request berikutnya.
71
+ 5. Middleware memverifikasi token sebelum request diteruskan ke handler terproteksi.
72
+
73
+ {{/if}}
74
+ ## Flow Fitur
75
+
76
+ Untuk setiap fitur kunci, definisikan flow data dan kontrol:
77
+
78
+ {{#each features}}
79
+ ### {{this}}
80
+
81
+ **Aktor**: [siapa yang memulai flow ini]
82
+ **Trigger**: [apa yang memulai flow ini]
83
+ **Langkah**:
84
+ 1. [Langkah 1]
85
+ 2. [Langkah 2]
86
+ 3. [Langkah 3]
87
+
88
+ **Hasil sukses**: [apa yang terjadi saat flow selesai]
89
+ **Penanganan error**: [apa yang terjadi jika gagal]
90
+
91
+ ---
92
+
93
+ {{/each}}
94
+
95
+ ## Diagram Aliran Data
96
+
97
+ ```
98
+ Input Data Proses Output
99
+ ---------- ----------- ----------
100
+ +--------------------+
101
+ User Input ----->| Validation |
102
+ | (Transport) |
103
+ +---------+----------+
104
+ |
105
+ +---------v----------+
106
+ | Business Logic |
107
+ | (Service) |
108
+ +---------+----------+
109
+ |
110
+ +---------v----------+
111
+ | Data Persist |-------> Stored Data
112
+ | (Repository) |
113
+ +--------------------+
114
+ ```
115
+
116
+ ---
117
+
118
+ Dokumen ini adalah referensi hidup. Perbarui flow saat fitur diimplementasikan dan disempurnakan.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Generated by Agentic-Senior-Core CLI v{{cliVersion}}
4
4
  Generated at: {{generatedAt}}
5
- Template version: 1.0.0
5
+ Template version: {{templateVersion}}
6
6
 
7
7
  ---
8
8
 
@@ -0,0 +1,53 @@
1
+ # Ringkasan Proyek: {{projectName}}
2
+
3
+ Dibuat oleh Agentic-Senior-Core CLI v{{cliVersion}}
4
+ Dibuat pada: {{generatedAt}}
5
+ Versi template: {{templateVersion}}
6
+
7
+ ---
8
+
9
+ ## Ikhtisar
10
+
11
+ **Nama proyek**: {{projectName}}
12
+ **Deskripsi**: {{projectDescription}}
13
+ **Domain utama**: {{primaryDomain}}
14
+
15
+ ## Keputusan Teknologi
16
+
17
+ **Stack**: {{stackDisplayName}}
18
+ **Blueprint**: {{blueprintDisplayName}}
19
+ **Database**: {{databaseChoice}}
20
+ **Strategi autentikasi**: {{authStrategy}}
21
+
22
+ ## Fitur Kunci
23
+
24
+ {{#each features}}
25
+ - {{this}}
26
+ {{/each}}
27
+
28
+ ## Konteks Tambahan
29
+
30
+ {{additionalContext}}
31
+
32
+ ## Batasan dan Asumsi
33
+
34
+ - Proyek ini mengikuti aturan governance di `.agent-context/rules/`.
35
+ - Konvensi stack mengacu ke `.agent-context/stacks/{{stackFileName}}`.
36
+ - Pola arsitektur mengacu ke `.agent-context/blueprints/{{blueprintFileName}}`.
37
+ - Semua kode harus lolos checklist di `.agent-context/review-checklists/pr-checklist.md`.
38
+
39
+ ## Tujuan
40
+
41
+ 1. Mengirimkan {{primaryDomain}} yang berjalan dengan stack {{stackDisplayName}}.
42
+ 2. Menjaga standar engineering production-grade sejak awal.
43
+ 3. Menjaga keputusan arsitektur tetap terdokumentasi dan bisa ditelusuri.
44
+
45
+ ## Non-Tujuan (Ruang Lingkup Awal)
46
+
47
+ - Optimasi performa di luar baseline yang wajar.
48
+ - Deployment multi-region.
49
+ - Analitik atau pelaporan tingkat lanjut.
50
+
51
+ ---
52
+
53
+ Dokumen ini adalah referensi hidup. Perbarui saat ruang lingkup proyek berkembang.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Generated by Agentic-Senior-Core CLI v{{cliVersion}}
4
4
  Generated at: {{generatedAt}}
5
- Template version: 1.0.0
5
+ Template version: {{templateVersion}}
6
6
 
7
7
  ---
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuenn3123/agentic-senior-core",
3
- "version": "2.0.20",
3
+ "version": "2.0.21",
4
4
  "type": "module",
5
5
  "description": "Force your AI Agent to code like a Staff Engineer, not a Junior.",
6
6
  "bin": {