@ryuenn3123/agentic-senior-core 2.5.17 → 2.5.19
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/.agent-context/review-checklists/release-operations.md +4 -0
- package/.agent-context/state/memory-continuity-benchmark.json +1 -1
- package/.cursorrules +1 -1
- package/.windsurfrules +1 -1
- package/README.md +4 -1
- package/lib/cli/commands/init.mjs +150 -9
- package/lib/cli/commands/upgrade.mjs +64 -1
- package/lib/cli/compiler.mjs +2 -0
- package/package.json +1 -1
- package/scripts/validate.mjs +194 -0
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Use this checklist before promoting any release tag or package publish operation.
|
|
4
4
|
|
|
5
|
+
## 0) Terminology Boundary (Compliance and Audit)
|
|
6
|
+
- Compliance and audit artifacts keep the canonical enterprise term: `Federated Governance`.
|
|
7
|
+
- Developer-facing aliases are allowed outside compliance artifacts when first mention includes the canonical term in parentheses.
|
|
8
|
+
|
|
5
9
|
## 1) Versioning and Changelog Integrity
|
|
6
10
|
- `package.json` version is valid semantic version (`x.y.z`).
|
|
7
11
|
- `CHANGELOG.md` has a matching release header for the package version.
|
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.5.
|
|
3
|
+
Generated by Agentic-Senior-Core CLI v2.5.19
|
|
4
4
|
Timestamp: 2026-04-18T03:00:00.000Z
|
|
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.5.
|
|
3
|
+
Generated by Agentic-Senior-Core CLI v2.5.19
|
|
4
4
|
Timestamp: 2026-04-18T03:00:00.000Z
|
|
5
5
|
Selected profile: beginner
|
|
6
6
|
Selected policy file: .agent-context/policies/llm-judge-threshold.json
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](CONTRIBUTING.md)
|
|
9
9
|
|
|
10
|
-
**Production-grade
|
|
10
|
+
**Production-grade Rules Engine (Governance Engine) for AI coding agents.**
|
|
11
11
|
Works with Cursor, Windsurf, GitHub Copilot, Claude Code, Gemini, and other LLM-powered IDE workflows.
|
|
12
12
|
|
|
13
13
|
</div>
|
|
@@ -103,6 +103,8 @@ Use `--dry-run` first to preview changes safely, then apply with `--yes`.
|
|
|
103
103
|
|
|
104
104
|
Rule: on first mention in developer-facing docs, include canonical term in parentheses.
|
|
105
105
|
|
|
106
|
+
Full mapping reference: docs/terminology-mapping.md
|
|
107
|
+
|
|
106
108
|
---
|
|
107
109
|
|
|
108
110
|
## Reference Docs
|
|
@@ -115,6 +117,7 @@ Rule: on first mention in developer-facing docs, include canonical term in paren
|
|
|
115
117
|
- V2 upgrade playbook: docs/v2-upgrade-playbook.md
|
|
116
118
|
- Integration playbook: docs/integration-playbook.md
|
|
117
119
|
- Benchmark and stack reference: docs/benchmark-reference.md
|
|
120
|
+
- Terminology mapping reference: docs/terminology-mapping.md
|
|
118
121
|
- Product roadmap: docs/roadmap.md
|
|
119
122
|
|
|
120
123
|
---
|
|
@@ -502,6 +502,14 @@ async function askBlueprintSelection(promptMessage, selectableBlueprintFileNames
|
|
|
502
502
|
return selectableBlueprintFileNames[selectedIndex] || selectableBlueprintFileNames[0] || null;
|
|
503
503
|
}
|
|
504
504
|
|
|
505
|
+
function buildExistingProjectMajorConstraints() {
|
|
506
|
+
return [
|
|
507
|
+
'Preserve existing project markers and avoid forced stack migration.',
|
|
508
|
+
'Keep stack rule loading lazy and scoped to touched code.',
|
|
509
|
+
'Explicit stack or blueprint overrides always win over auto-detection.',
|
|
510
|
+
];
|
|
511
|
+
}
|
|
512
|
+
|
|
505
513
|
export async function runInitCommand(targetDirectoryArgument, initOptions = {}) {
|
|
506
514
|
const resolvedTargetDirectoryPath = path.resolve(targetDirectoryArgument || '.');
|
|
507
515
|
const isTokenOptimizationEnabled = typeof initOptions.tokenOptimize === 'boolean'
|
|
@@ -654,6 +662,64 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
654
662
|
console.log(`\nSelected profile: ${selectedProfile.displayName}`);
|
|
655
663
|
console.log(`This profile will block these review severities in CI: ${formatBlockingSeverities(selectedProfile.blockingSeverities)}.`);
|
|
656
664
|
|
|
665
|
+
const detectionMajorConstraints = buildExistingProjectMajorConstraints();
|
|
666
|
+
const detectionTransparency = {
|
|
667
|
+
declaredAt: new Date().toISOString(),
|
|
668
|
+
declarationType: projectDetection.hasExistingProjectFiles ? 'existing-project' : 'fresh-project',
|
|
669
|
+
declarationShown: projectDetection.hasExistingProjectFiles,
|
|
670
|
+
detectionSummary: projectDetection.hasExistingProjectFiles
|
|
671
|
+
? buildDetectionSummary(projectDetection)
|
|
672
|
+
: 'No existing project markers were detected.',
|
|
673
|
+
activeRulesSummary: {
|
|
674
|
+
canonicalSource: '.instructions.md',
|
|
675
|
+
compiledEntrypoints: ['.cursorrules', '.windsurfrules'],
|
|
676
|
+
stackLoadingMode: 'lazy',
|
|
677
|
+
selectedProfile: selectedProfileName,
|
|
678
|
+
selectedProfileDisplayName: selectedProfile.displayName,
|
|
679
|
+
blockingSeverities: selectedProfile.blockingSeverities,
|
|
680
|
+
ciGuardrailsEnabled: null,
|
|
681
|
+
},
|
|
682
|
+
majorConstraints: detectionMajorConstraints,
|
|
683
|
+
quickConfirmation: {
|
|
684
|
+
offered: false,
|
|
685
|
+
response: projectDetection.hasExistingProjectFiles ? 'pending' : 'not-applicable',
|
|
686
|
+
source: 'existing-project-detection',
|
|
687
|
+
},
|
|
688
|
+
decision: {
|
|
689
|
+
mode: projectDetection.hasExistingProjectFiles ? 'pending' : 'fresh-directory',
|
|
690
|
+
selectedStackFileName: null,
|
|
691
|
+
selectedBlueprintFileName: null,
|
|
692
|
+
},
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
if (projectDetection.hasExistingProjectFiles) {
|
|
696
|
+
console.log('\nExisting project detection transparency:');
|
|
697
|
+
|
|
698
|
+
if (projectDetection.recommendedStackFileName) {
|
|
699
|
+
const confidenceScoreLabel = Number(projectDetection.confidenceScore || 0).toFixed(2);
|
|
700
|
+
console.log(
|
|
701
|
+
`- Detected stack: ${toTitleCase(projectDetection.recommendedStackFileName)} (${projectDetection.confidenceLabel}, score ${confidenceScoreLabel})`
|
|
702
|
+
);
|
|
703
|
+
|
|
704
|
+
if (projectDetection.secondaryStackFileNames?.length) {
|
|
705
|
+
console.log(
|
|
706
|
+
`- Secondary stack signals: ${projectDetection.secondaryStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}`
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
} else {
|
|
710
|
+
console.log('- Detected stack: unresolved (insufficient markers).');
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
console.log('- Active rules baseline: canonical .instructions.md -> compiled .cursorrules/.windsurfrules');
|
|
714
|
+
console.log(
|
|
715
|
+
`- Active review profile: ${selectedProfile.displayName} (blocking severities: ${formatBlockingSeverities(selectedProfile.blockingSeverities)})`
|
|
716
|
+
);
|
|
717
|
+
console.log('- Major constraints:');
|
|
718
|
+
for (const majorConstraint of detectionMajorConstraints) {
|
|
719
|
+
console.log(` - ${majorConstraint}`);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
657
723
|
if (selectedProfilePack) {
|
|
658
724
|
console.log(`Applying team profile pack: ${selectedProfilePack.displayName}.`);
|
|
659
725
|
console.log(`Pack defaults: stack ${toTitleCase(selectedProfilePack.defaultStackFileName)}, blueprint ${toTitleCase(selectedProfilePack.defaultBlueprintFileName)}.`);
|
|
@@ -667,11 +733,15 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
667
733
|
&& !selectedStackFileNameFromOption
|
|
668
734
|
&& !selectedPreset?.stack
|
|
669
735
|
&& !selectedProfilePack?.defaultStackFileName;
|
|
736
|
+
const detectedBlueprintFileName = projectDetection.recommendedBlueprintFileName
|
|
737
|
+
|| BLUEPRINT_RECOMMENDATIONS[projectDetection.recommendedStackFileName]
|
|
738
|
+
|| null;
|
|
670
739
|
|
|
671
740
|
let selectedManualStackFileName = null;
|
|
672
741
|
let selectedManualBlueprintFileName = null;
|
|
673
742
|
let selectedAdditionalStackFileNames = [];
|
|
674
743
|
let selectedAdditionalBlueprintFileNames = [];
|
|
744
|
+
let detectedSetupWasApplied = false;
|
|
675
745
|
|
|
676
746
|
let architectureRecommendation = null;
|
|
677
747
|
let architectPreferenceState = await readArchitectPreferenceState();
|
|
@@ -684,11 +754,73 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
684
754
|
&& !selectedProfile.defaultStackFileName;
|
|
685
755
|
|
|
686
756
|
if (shouldAutoApplyDetectedStack) {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
console.log(
|
|
757
|
+
if (isInteractiveSession) {
|
|
758
|
+
detectionTransparency.quickConfirmation.offered = true;
|
|
759
|
+
console.log('\nQuick confirmation for existing project detection:');
|
|
760
|
+
console.log(`- Suggested stack: ${toTitleCase(projectDetection.recommendedStackFileName)}`);
|
|
761
|
+
if (detectedBlueprintFileName) {
|
|
762
|
+
console.log(`- Suggested blueprint: ${toTitleCase(detectedBlueprintFileName)}`);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const shouldUseDetectedSetup = await askYesNo(
|
|
766
|
+
'Use detected setup for this existing project?',
|
|
767
|
+
userInterface,
|
|
768
|
+
true
|
|
769
|
+
);
|
|
770
|
+
|
|
771
|
+
if (shouldUseDetectedSetup) {
|
|
772
|
+
detectedSetupWasApplied = true;
|
|
773
|
+
detectionTransparency.quickConfirmation.response = 'confirmed-detected';
|
|
774
|
+
detectionTransparency.decision.mode = 'confirmed-detected';
|
|
775
|
+
console.log(`Using detected stack automatically for this existing project: ${toTitleCase(projectDetection.recommendedStackFileName)}.`);
|
|
776
|
+
if (projectDetection.secondaryStackFileNames?.length) {
|
|
777
|
+
console.log(`Detected additional stack signals: ${projectDetection.secondaryStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}.`);
|
|
778
|
+
}
|
|
779
|
+
selectedAdditionalStackFileNames = projectDetection.secondaryStackFileNames || [];
|
|
780
|
+
} else {
|
|
781
|
+
const overrideStackFileName = await askStackSelection(
|
|
782
|
+
'Override detected stack (quick selection):',
|
|
783
|
+
stackFileNames,
|
|
784
|
+
userInterface
|
|
785
|
+
);
|
|
786
|
+
const overrideBlueprintCandidates = filterBlueprintFileNamesByCandidates(
|
|
787
|
+
blueprintFileNames,
|
|
788
|
+
[BLUEPRINT_RECOMMENDATIONS[overrideStackFileName]].filter(Boolean)
|
|
789
|
+
);
|
|
790
|
+
const overrideBlueprintFileName = await askBlueprintSelection(
|
|
791
|
+
'Override detected blueprint (quick selection):',
|
|
792
|
+
overrideBlueprintCandidates,
|
|
793
|
+
userInterface
|
|
794
|
+
);
|
|
795
|
+
|
|
796
|
+
selectedManualStackFileName = overrideStackFileName;
|
|
797
|
+
selectedManualBlueprintFileName = overrideBlueprintFileName;
|
|
798
|
+
selectedAdditionalStackFileNames = normalizeAdditionalStackSelection(
|
|
799
|
+
overrideStackFileName,
|
|
800
|
+
projectDetection.secondaryStackFileNames || []
|
|
801
|
+
);
|
|
802
|
+
detectionTransparency.quickConfirmation.response = 'overridden-detected';
|
|
803
|
+
detectionTransparency.decision.mode = 'overridden-detected';
|
|
804
|
+
console.log(
|
|
805
|
+
`Detection override applied: ${toTitleCase(overrideStackFileName)} + ${toTitleCase(overrideBlueprintFileName)}.`
|
|
806
|
+
);
|
|
807
|
+
}
|
|
808
|
+
} else {
|
|
809
|
+
detectedSetupWasApplied = true;
|
|
810
|
+
detectionTransparency.quickConfirmation.response = 'non-interactive-auto';
|
|
811
|
+
detectionTransparency.decision.mode = 'non-interactive-auto';
|
|
812
|
+
console.log(`Using detected stack automatically for this existing project: ${toTitleCase(projectDetection.recommendedStackFileName)}.`);
|
|
813
|
+
if (projectDetection.secondaryStackFileNames?.length) {
|
|
814
|
+
console.log(`Detected additional stack signals: ${projectDetection.secondaryStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}.`);
|
|
815
|
+
}
|
|
816
|
+
selectedAdditionalStackFileNames = projectDetection.secondaryStackFileNames || [];
|
|
690
817
|
}
|
|
691
|
-
|
|
818
|
+
} else if (projectDetection.hasExistingProjectFiles && projectDetection.recommendedStackFileName) {
|
|
819
|
+
detectionTransparency.quickConfirmation.response = 'explicit-selection-or-low-confidence';
|
|
820
|
+
detectionTransparency.decision.mode = 'explicit-selection-or-low-confidence';
|
|
821
|
+
} else if (!projectDetection.hasExistingProjectFiles) {
|
|
822
|
+
detectionTransparency.quickConfirmation.response = 'not-applicable';
|
|
823
|
+
detectionTransparency.decision.mode = 'fresh-directory';
|
|
692
824
|
}
|
|
693
825
|
|
|
694
826
|
if (shouldRunArchitectureRecommendation) {
|
|
@@ -805,10 +937,10 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
805
937
|
|
|
806
938
|
const selectedResolvedStackFileName = selectedStackFileNameFromOption
|
|
807
939
|
|| selectedPreset?.stack
|
|
808
|
-
||
|
|
940
|
+
|| selectedManualStackFileName
|
|
941
|
+
|| (detectedSetupWasApplied ? projectDetection.recommendedStackFileName : null)
|
|
809
942
|
|| selectedProfilePack?.defaultStackFileName
|
|
810
943
|
|| selectedProfile.defaultStackFileName
|
|
811
|
-
|| selectedManualStackFileName
|
|
812
944
|
|| stackFileNames[0];
|
|
813
945
|
|
|
814
946
|
selectedAdditionalStackFileNames = normalizeAdditionalStackSelection(
|
|
@@ -816,9 +948,9 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
816
948
|
selectedAdditionalStackFileNames
|
|
817
949
|
);
|
|
818
950
|
|
|
819
|
-
const recommendedBlueprintFileName =
|
|
820
|
-
&&
|
|
821
|
-
?
|
|
951
|
+
const recommendedBlueprintFileName = detectedSetupWasApplied
|
|
952
|
+
&& detectedBlueprintFileName
|
|
953
|
+
? detectedBlueprintFileName
|
|
822
954
|
: BLUEPRINT_RECOMMENDATIONS[selectedResolvedStackFileName] || null;
|
|
823
955
|
|
|
824
956
|
if (!recommendedBlueprintFileName && !selectedBlueprintFileNameFromOption && !selectedProfile.defaultBlueprintFileName) {
|
|
@@ -864,6 +996,12 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
864
996
|
: derivedAdditionalBlueprintFileNames
|
|
865
997
|
);
|
|
866
998
|
|
|
999
|
+
detectionTransparency.decision.selectedStackFileName = selectedResolvedStackFileName;
|
|
1000
|
+
detectionTransparency.decision.selectedBlueprintFileName = selectedResolvedBlueprintFileName;
|
|
1001
|
+
detectionTransparency.decision.selectedAdditionalStackFileNames = selectedAdditionalStackFileNames;
|
|
1002
|
+
detectionTransparency.decision.selectedAdditionalBlueprintFileNames = selectedAdditionalBlueprintFileNames;
|
|
1003
|
+
detectionTransparency.decision.usedDetectedSetup = detectedSetupWasApplied;
|
|
1004
|
+
|
|
867
1005
|
const selectedSkillDomainNames = inferSkillDomainNamesFromSelection(
|
|
868
1006
|
selectedResolvedStackFileName,
|
|
869
1007
|
selectedResolvedBlueprintFileName,
|
|
@@ -883,6 +1021,8 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
883
1021
|
? selectedProfile.defaultCi
|
|
884
1022
|
: await askYesNo('Enable CI/CD quality checks (guardrails) and the LLM Judge policy?', userInterface, selectedProfile.defaultCi);
|
|
885
1023
|
|
|
1024
|
+
detectionTransparency.activeRulesSummary.ciGuardrailsEnabled = includeCiGuardrails;
|
|
1025
|
+
|
|
886
1026
|
await copyGovernanceAssetsToTarget(resolvedTargetDirectoryPath, {
|
|
887
1027
|
includeMcpTemplate: shouldIncludeMcpTemplate,
|
|
888
1028
|
});
|
|
@@ -1044,6 +1184,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
1044
1184
|
stateFile: isMemoryContinuityEnabled ? '.agent-context/state/memory-continuity.json' : null,
|
|
1045
1185
|
},
|
|
1046
1186
|
architectRecommendation: architectureRecommendation,
|
|
1187
|
+
detectionTransparency,
|
|
1047
1188
|
});
|
|
1048
1189
|
|
|
1049
1190
|
if (architectPreferenceUpdated && architectPreferenceState) {
|
|
@@ -24,7 +24,11 @@ import {
|
|
|
24
24
|
copyGovernanceAssetsToTarget,
|
|
25
25
|
} from '../utils.mjs';
|
|
26
26
|
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
detectProjectContext,
|
|
29
|
+
buildDetectionSummary,
|
|
30
|
+
formatDetectionCandidates,
|
|
31
|
+
} from '../detector.mjs';
|
|
28
32
|
import {
|
|
29
33
|
buildCompiledRulesContent,
|
|
30
34
|
writeSelectedPolicy,
|
|
@@ -76,6 +80,14 @@ export function parseUpgradeArguments(commandArguments) {
|
|
|
76
80
|
return parsedUpgradeOptions;
|
|
77
81
|
}
|
|
78
82
|
|
|
83
|
+
function buildExistingProjectMajorConstraints() {
|
|
84
|
+
return [
|
|
85
|
+
'Preserve existing project markers and avoid forced stack migration.',
|
|
86
|
+
'Keep stack rule loading lazy and scoped to touched code.',
|
|
87
|
+
'Upgrade keeps prior onboarding choices unless user overrides them.',
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
|
|
79
91
|
export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions = {}) {
|
|
80
92
|
const resolvedTargetDirectoryPath = path.resolve(targetDirectoryArgument || '.');
|
|
81
93
|
|
|
@@ -143,6 +155,56 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
143
155
|
? existingOnboardingReport.ciGuardrailsEnabled
|
|
144
156
|
: true;
|
|
145
157
|
|
|
158
|
+
const detectionMajorConstraints = buildExistingProjectMajorConstraints();
|
|
159
|
+
const detectionTransparency = {
|
|
160
|
+
declaredAt: new Date().toISOString(),
|
|
161
|
+
declarationType: 'existing-project',
|
|
162
|
+
declarationShown: true,
|
|
163
|
+
detectionSummary: buildDetectionSummary(projectDetection),
|
|
164
|
+
activeRulesSummary: {
|
|
165
|
+
canonicalSource: '.instructions.md',
|
|
166
|
+
compiledEntrypoints: ['.cursorrules', '.windsurfrules'],
|
|
167
|
+
stackLoadingMode: 'lazy',
|
|
168
|
+
selectedProfile: selectedProfileName,
|
|
169
|
+
selectedProfileDisplayName: toTitleCase(selectedProfileName),
|
|
170
|
+
blockingSeverities: PROFILE_PRESETS[selectedProfileName]?.blockingSeverities || [],
|
|
171
|
+
ciGuardrailsEnabled: includeCiGuardrails,
|
|
172
|
+
},
|
|
173
|
+
majorConstraints: detectionMajorConstraints,
|
|
174
|
+
quickConfirmation: {
|
|
175
|
+
offered: false,
|
|
176
|
+
response: 'upgrade-auto',
|
|
177
|
+
source: 'upgrade-assistant',
|
|
178
|
+
},
|
|
179
|
+
decision: {
|
|
180
|
+
mode: 'upgrade-auto',
|
|
181
|
+
selectedStackFileName,
|
|
182
|
+
selectedBlueprintFileName,
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
console.log('\nExisting project detection transparency:');
|
|
187
|
+
if (projectDetection.recommendedStackFileName) {
|
|
188
|
+
const confidenceScoreLabel = Number(projectDetection.confidenceScore || 0).toFixed(2);
|
|
189
|
+
console.log(
|
|
190
|
+
`- Detected stack: ${toTitleCase(projectDetection.recommendedStackFileName)} (${projectDetection.confidenceLabel}, score ${confidenceScoreLabel})`
|
|
191
|
+
);
|
|
192
|
+
} else {
|
|
193
|
+
console.log('- Detected stack: unresolved (insufficient markers).');
|
|
194
|
+
}
|
|
195
|
+
console.log('- Active rules baseline: canonical .instructions.md -> compiled .cursorrules/.windsurfrules');
|
|
196
|
+
console.log(
|
|
197
|
+
`- Active review profile: ${toTitleCase(selectedProfileName)} (blocking severities: ${(
|
|
198
|
+
PROFILE_PRESETS[selectedProfileName]?.blockingSeverities || []
|
|
199
|
+
).join(', ') || 'none'})`
|
|
200
|
+
);
|
|
201
|
+
console.log('- Top candidates:');
|
|
202
|
+
console.log(formatDetectionCandidates(projectDetection.rankedCandidates));
|
|
203
|
+
console.log('- Major constraints:');
|
|
204
|
+
for (const majorConstraint of detectionMajorConstraints) {
|
|
205
|
+
console.log(` - ${majorConstraint}`);
|
|
206
|
+
}
|
|
207
|
+
|
|
146
208
|
const selectedSkillDomainNames = inferSkillDomainNamesFromSelection(
|
|
147
209
|
selectedStackFileName,
|
|
148
210
|
selectedBlueprintFileName,
|
|
@@ -249,6 +311,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
249
311
|
compatibilityWarnings,
|
|
250
312
|
runtimeEnvironment: existingOnboardingReport?.runtimeEnvironment || null,
|
|
251
313
|
operationMode: 'upgrade',
|
|
314
|
+
detectionTransparency,
|
|
252
315
|
});
|
|
253
316
|
|
|
254
317
|
console.log('\nUpgrade complete.');
|
package/lib/cli/compiler.mjs
CHANGED
|
@@ -56,6 +56,7 @@ export async function writeOnboardingReport({
|
|
|
56
56
|
tokenOptimization = undefined,
|
|
57
57
|
memoryContinuity = undefined,
|
|
58
58
|
architectRecommendation = null,
|
|
59
|
+
detectionTransparency = null,
|
|
59
60
|
}) {
|
|
60
61
|
const onboardingReportPath = path.join(targetDirectoryPath, '.agent-context', 'state', 'onboarding-report.json');
|
|
61
62
|
const resolvedTokenOptimization = typeof tokenOptimization === 'undefined'
|
|
@@ -110,6 +111,7 @@ export async function writeOnboardingReport({
|
|
|
110
111
|
detectionReasoning: projectDetection.detectionReasoning,
|
|
111
112
|
rankedCandidates: projectDetection.rankedCandidates,
|
|
112
113
|
evidence: projectDetection.evidence,
|
|
114
|
+
detectionTransparency: detectionTransparency || null,
|
|
113
115
|
},
|
|
114
116
|
};
|
|
115
117
|
|
package/package.json
CHANGED
package/scripts/validate.mjs
CHANGED
|
@@ -100,6 +100,86 @@ const REQUIRED_TERMINOLOGY_ROW_PATTERNS = [
|
|
|
100
100
|
];
|
|
101
101
|
const REQUIRED_TERMINOLOGY_RULE_SNIPPET =
|
|
102
102
|
'Rule: on first mention in developer-facing docs, include canonical term in parentheses.';
|
|
103
|
+
const TERMINOLOGY_REFERENCE_DOCUMENT_PATH = 'docs/terminology-mapping.md';
|
|
104
|
+
const REQUIRED_DEVELOPER_FIRST_MENTION_PATTERNS = [
|
|
105
|
+
{
|
|
106
|
+
path: 'README.md',
|
|
107
|
+
label: 'Rules Engine first mention includes Governance Engine',
|
|
108
|
+
pattern: /Rules Engine\s*\(Governance Engine\)/u,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
path: 'docs/deep-dive.md',
|
|
112
|
+
label: 'Dynamic Rules Engine first mention includes Governance Engine',
|
|
113
|
+
pattern: /Dynamic Rules Engine\s*\(Governance Engine\)/u,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
path: 'docs/faq.md',
|
|
117
|
+
label: 'Quality Checks first mention includes Guardrails',
|
|
118
|
+
pattern: /Quality Checks\s*\(Guardrails\)/u,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
path: '.agent-context/prompts/init-project.md',
|
|
122
|
+
label: 'Init prompt first mention includes Federated Governance baseline',
|
|
123
|
+
pattern: /rules operations context\s*\(Federated Governance baseline\)/iu,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
path: 'lib/cli/commands/init.mjs',
|
|
127
|
+
label: 'Init command wording includes Federated Governance baseline',
|
|
128
|
+
pattern: /rules operations\s+(assets|pack)[^\n]*\(Federated Governance baseline\)/iu,
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
path: 'lib/cli/commands/upgrade.mjs',
|
|
132
|
+
label: 'Upgrade command wording includes Federated Governance baseline',
|
|
133
|
+
pattern: /rules operations upgrade assistant\s*\(Federated Governance baseline\)/iu,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
path: 'lib/cli/utils.mjs',
|
|
137
|
+
label: 'CLI help wording includes quality checks and guardrails',
|
|
138
|
+
pattern: /quality checks\s*\(guardrails\)/iu,
|
|
139
|
+
},
|
|
140
|
+
];
|
|
141
|
+
const COMPLIANCE_TERMINOLOGY_BOUNDARY_PATHS = [
|
|
142
|
+
'.agent-context/review-checklists/security-audit.md',
|
|
143
|
+
'.agent-context/review-checklists/performance-audit.md',
|
|
144
|
+
'.agent-context/review-checklists/release-operations.md',
|
|
145
|
+
'scripts/release-gate.mjs',
|
|
146
|
+
'scripts/forbidden-content-check.mjs',
|
|
147
|
+
];
|
|
148
|
+
const COMPLIANCE_ALIAS_TERMS = [
|
|
149
|
+
'Federated Rules Operations',
|
|
150
|
+
];
|
|
151
|
+
const REQUIRED_COMPLIANCE_CANONICAL_SNIPPETS = [
|
|
152
|
+
{
|
|
153
|
+
path: '.agent-context/review-checklists/release-operations.md',
|
|
154
|
+
snippet: 'Federated Governance',
|
|
155
|
+
label: 'release operations checklist keeps canonical term Federated Governance',
|
|
156
|
+
},
|
|
157
|
+
];
|
|
158
|
+
const REQUIRED_DETECTION_TRANSPARENCY_SNIPPETS = [
|
|
159
|
+
{
|
|
160
|
+
path: 'lib/cli/commands/init.mjs',
|
|
161
|
+
snippets: [
|
|
162
|
+
'Existing project detection transparency:',
|
|
163
|
+
'Use detected setup for this existing project?',
|
|
164
|
+
'detectionTransparency',
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
path: 'lib/cli/commands/upgrade.mjs',
|
|
169
|
+
snippets: [
|
|
170
|
+
'Existing project detection transparency:',
|
|
171
|
+
'formatDetectionCandidates(projectDetection.rankedCandidates)',
|
|
172
|
+
'detectionTransparency',
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
path: 'lib/cli/compiler.mjs',
|
|
177
|
+
snippets: [
|
|
178
|
+
'detectionTransparency = null',
|
|
179
|
+
'detectionTransparency: detectionTransparency || null',
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
];
|
|
103
183
|
|
|
104
184
|
const validationResult = {
|
|
105
185
|
passed: 0,
|
|
@@ -212,6 +292,7 @@ async function validateRequiredFiles() {
|
|
|
212
292
|
'CHANGELOG.md',
|
|
213
293
|
'docs/faq.md',
|
|
214
294
|
'docs/deep-dive.md',
|
|
295
|
+
'docs/terminology-mapping.md',
|
|
215
296
|
'docs/v1.7-execution-playbook.md',
|
|
216
297
|
'docs/v1.7-issue-breakdown.md',
|
|
217
298
|
'docs/v1.8-operations-playbook.md',
|
|
@@ -750,6 +831,40 @@ async function validateDocumentationFlow() {
|
|
|
750
831
|
async function validateTerminologyMapping() {
|
|
751
832
|
console.log('\nChecking terminology mapping consistency...');
|
|
752
833
|
|
|
834
|
+
const terminologyReferenceDocumentPath = join(ROOT_DIR, TERMINOLOGY_REFERENCE_DOCUMENT_PATH);
|
|
835
|
+
|
|
836
|
+
if (!(await fileExists(terminologyReferenceDocumentPath))) {
|
|
837
|
+
fail(`Missing terminology reference document: ${TERMINOLOGY_REFERENCE_DOCUMENT_PATH}`);
|
|
838
|
+
} else {
|
|
839
|
+
const terminologyReferenceContent = await readTextFile(terminologyReferenceDocumentPath);
|
|
840
|
+
|
|
841
|
+
if (terminologyReferenceContent.includes('Dual-Term Mapping')) {
|
|
842
|
+
pass(`${TERMINOLOGY_REFERENCE_DOCUMENT_PATH} includes Dual-Term Mapping section`);
|
|
843
|
+
} else {
|
|
844
|
+
fail(`${TERMINOLOGY_REFERENCE_DOCUMENT_PATH} must include Dual-Term Mapping section`);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
for (const terminologyRowRule of REQUIRED_TERMINOLOGY_ROW_PATTERNS) {
|
|
848
|
+
if (terminologyRowRule.pattern.test(terminologyReferenceContent)) {
|
|
849
|
+
pass(`${TERMINOLOGY_REFERENCE_DOCUMENT_PATH} includes mapping row: ${terminologyRowRule.label}`);
|
|
850
|
+
} else {
|
|
851
|
+
fail(`${TERMINOLOGY_REFERENCE_DOCUMENT_PATH} is missing mapping row: ${terminologyRowRule.label}`);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
if (terminologyReferenceContent.includes('first mention must include canonical term in parentheses')) {
|
|
856
|
+
pass(`${TERMINOLOGY_REFERENCE_DOCUMENT_PATH} defines first-mention canonical term rule`);
|
|
857
|
+
} else {
|
|
858
|
+
fail(`${TERMINOLOGY_REFERENCE_DOCUMENT_PATH} must define first-mention canonical term rule`);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
if (terminologyReferenceContent.includes('Compliance and audit artifacts must keep canonical enterprise terminology')) {
|
|
862
|
+
pass(`${TERMINOLOGY_REFERENCE_DOCUMENT_PATH} defines compliance terminology boundary`);
|
|
863
|
+
} else {
|
|
864
|
+
fail(`${TERMINOLOGY_REFERENCE_DOCUMENT_PATH} must define compliance terminology boundary`);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
753
868
|
for (const terminologyReferencePath of TERMINOLOGY_REFERENCE_PATHS) {
|
|
754
869
|
const absoluteReferencePath = join(ROOT_DIR, terminologyReferencePath);
|
|
755
870
|
|
|
@@ -779,6 +894,84 @@ async function validateTerminologyMapping() {
|
|
|
779
894
|
} else {
|
|
780
895
|
fail(`${terminologyReferencePath} must include first-mention canonical term rule`);
|
|
781
896
|
}
|
|
897
|
+
|
|
898
|
+
if (referenceContent.includes(TERMINOLOGY_REFERENCE_DOCUMENT_PATH)) {
|
|
899
|
+
pass(`${terminologyReferencePath} links to ${TERMINOLOGY_REFERENCE_DOCUMENT_PATH}`);
|
|
900
|
+
} else {
|
|
901
|
+
fail(`${terminologyReferencePath} must link to ${TERMINOLOGY_REFERENCE_DOCUMENT_PATH}`);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
for (const firstMentionRule of REQUIRED_DEVELOPER_FIRST_MENTION_PATTERNS) {
|
|
906
|
+
const absoluteFirstMentionPath = join(ROOT_DIR, firstMentionRule.path);
|
|
907
|
+
|
|
908
|
+
if (!(await fileExists(absoluteFirstMentionPath))) {
|
|
909
|
+
fail(`Missing developer-facing first-mention source: ${firstMentionRule.path}`);
|
|
910
|
+
continue;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
const firstMentionContent = await readTextFile(absoluteFirstMentionPath);
|
|
914
|
+
if (firstMentionRule.pattern.test(firstMentionContent)) {
|
|
915
|
+
pass(`${firstMentionRule.path} keeps first-mention rule: ${firstMentionRule.label}`);
|
|
916
|
+
} else {
|
|
917
|
+
fail(`${firstMentionRule.path} must keep first-mention rule: ${firstMentionRule.label}`);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
for (const compliancePath of COMPLIANCE_TERMINOLOGY_BOUNDARY_PATHS) {
|
|
922
|
+
const absoluteCompliancePath = join(ROOT_DIR, compliancePath);
|
|
923
|
+
|
|
924
|
+
if (!(await fileExists(absoluteCompliancePath))) {
|
|
925
|
+
fail(`Missing compliance/audit artifact for terminology boundary: ${compliancePath}`);
|
|
926
|
+
continue;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
const complianceContent = await readTextFile(absoluteCompliancePath);
|
|
930
|
+
for (const aliasTerm of COMPLIANCE_ALIAS_TERMS) {
|
|
931
|
+
if (complianceContent.includes(aliasTerm)) {
|
|
932
|
+
fail(`${compliancePath} must not use developer-facing alias in compliance context: ${aliasTerm}`);
|
|
933
|
+
} else {
|
|
934
|
+
pass(`${compliancePath} keeps canonical terminology boundary for alias: ${aliasTerm}`);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
for (const complianceRule of REQUIRED_COMPLIANCE_CANONICAL_SNIPPETS) {
|
|
940
|
+
const absoluteComplianceRulePath = join(ROOT_DIR, complianceRule.path);
|
|
941
|
+
|
|
942
|
+
if (!(await fileExists(absoluteComplianceRulePath))) {
|
|
943
|
+
fail(`Missing compliance canonical source: ${complianceRule.path}`);
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
const complianceRuleContent = await readTextFile(absoluteComplianceRulePath);
|
|
948
|
+
if (complianceRuleContent.includes(complianceRule.snippet)) {
|
|
949
|
+
pass(`${complianceRule.path} keeps canonical terminology rule: ${complianceRule.label}`);
|
|
950
|
+
} else {
|
|
951
|
+
fail(`${complianceRule.path} must keep canonical terminology rule: ${complianceRule.label}`);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
async function validateDetectionTransparencyCoverage() {
|
|
957
|
+
console.log('\nChecking existing-project detection transparency coverage...');
|
|
958
|
+
|
|
959
|
+
for (const transparencyRule of REQUIRED_DETECTION_TRANSPARENCY_SNIPPETS) {
|
|
960
|
+
const absoluteTransparencyPath = join(ROOT_DIR, transparencyRule.path);
|
|
961
|
+
|
|
962
|
+
if (!(await fileExists(absoluteTransparencyPath))) {
|
|
963
|
+
fail(`Missing detection transparency source: ${transparencyRule.path}`);
|
|
964
|
+
continue;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
const transparencyContent = await readTextFile(absoluteTransparencyPath);
|
|
968
|
+
for (const requiredSnippet of transparencyRule.snippets) {
|
|
969
|
+
if (transparencyContent.includes(requiredSnippet)) {
|
|
970
|
+
pass(`${transparencyRule.path} includes detection transparency snippet: ${requiredSnippet}`);
|
|
971
|
+
} else {
|
|
972
|
+
fail(`${transparencyRule.path} is missing detection transparency snippet: ${requiredSnippet}`);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
782
975
|
}
|
|
783
976
|
}
|
|
784
977
|
|
|
@@ -1031,6 +1224,7 @@ async function main() {
|
|
|
1031
1224
|
await validateVersionConsistency();
|
|
1032
1225
|
await validateDocumentationFlow();
|
|
1033
1226
|
await validateTerminologyMapping();
|
|
1227
|
+
await validateDetectionTransparencyCoverage();
|
|
1034
1228
|
await validateMcpConfiguration();
|
|
1035
1229
|
await validateHumanWritingGovernance();
|
|
1036
1230
|
await validateInstructionAdapters();
|