@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 +1 -1
- package/.windsurfrules +1 -1
- package/lib/cli/commands/init.mjs +69 -34
- package/lib/cli/commands/upgrade.mjs +16 -0
- package/lib/cli/project-scaffolder.mjs +92 -5
- package/lib/cli/templates/api-contract.md.id.tmpl +143 -0
- package/lib/cli/templates/api-contract.md.tmpl +1 -1
- package/lib/cli/templates/architecture-decision-record.md.id.tmpl +106 -0
- package/lib/cli/templates/architecture-decision-record.md.tmpl +1 -1
- package/lib/cli/templates/database-schema.md.id.tmpl +74 -0
- package/lib/cli/templates/database-schema.md.tmpl +1 -1
- package/lib/cli/templates/flow-overview.md.id.tmpl +118 -0
- package/lib/cli/templates/flow-overview.md.tmpl +1 -1
- package/lib/cli/templates/project-brief.md.id.tmpl +53 -0
- package/lib/cli/templates/project-brief.md.tmpl +1 -1
- package/package.json +1 -1
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.
|
|
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.
|
|
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.
|
|
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
|
-
||
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
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,
|
|
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 =
|
|
318
|
+
const templateFilePath = await resolveTemplateFilePath(
|
|
319
|
+
documentEntry.templateFileName,
|
|
320
|
+
normalizedDocsLanguage
|
|
321
|
+
);
|
|
273
322
|
|
|
274
|
-
if (!
|
|
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:
|
|
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.
|
|
@@ -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.
|
|
@@ -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.
|
|
@@ -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.
|
|
@@ -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.
|