@ryuenn3123/agentic-senior-core 4.4.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/.agents/plugins/marketplace.json +21 -0
  2. package/.agents/rules/agentic-senior-core.md +126 -0
  3. package/.claude-plugin/marketplace.json +17 -0
  4. package/.claude-plugin/plugin.json +17 -0
  5. package/.clinerules/agentic-senior-core.md +94 -0
  6. package/.codex-plugin/plugin.json +24 -0
  7. package/.cursor/rules/agentic-senior-core.mdc +99 -0
  8. package/.devin-plugin/plugin.json +13 -0
  9. package/.github/copilot-instructions.md +94 -0
  10. package/.github/plugin/marketplace.json +20 -0
  11. package/.github/plugin/plugin.json +16 -0
  12. package/.kiro/steering/agentic-senior-core.md +94 -0
  13. package/.openclaw/skills/asc/SKILL.md +23 -0
  14. package/.openclaw/skills/asc-audit/SKILL.md +28 -0
  15. package/.openclaw/skills/asc-review/SKILL.md +54 -0
  16. package/.opencode/plugins/agentic-senior-core.mjs +31 -0
  17. package/.windsurf/rules/agentic-senior-core.md +94 -0
  18. package/AGENTS.md +126 -127
  19. package/CONTRIBUTING.md +93 -63
  20. package/README.md +160 -111
  21. package/__init__.py +61 -0
  22. package/bin/agentic-senior-core.js +42 -41
  23. package/commands/asc-audit.md +1 -0
  24. package/commands/asc-audit.toml +2 -0
  25. package/commands/asc-help.md +9 -0
  26. package/commands/asc-help.toml +2 -0
  27. package/commands/asc-refactor.md +1 -0
  28. package/commands/asc-refactor.toml +2 -0
  29. package/commands/asc-review.md +1 -0
  30. package/commands/asc-review.toml +2 -0
  31. package/gemini-extension.json +10 -0
  32. package/hooks/copilot-hooks.json +21 -0
  33. package/hooks/hooks.json +31 -0
  34. package/hooks/session-start.js +36 -0
  35. package/hooks/subagent-start.js +38 -0
  36. package/lib/cli/commands/adapter.mjs +109 -0
  37. package/lib/cli/commands/clean.mjs +63 -0
  38. package/lib/cli/commands/status.mjs +94 -0
  39. package/package.json +43 -60
  40. package/plugin.yaml +16 -0
  41. package/scripts/uninstall.js +38 -0
  42. package/skills/asc/SKILL.md +16 -0
  43. package/skills/asc-audit/SKILL.md +28 -0
  44. package/skills/asc-refactor/SKILL.md +35 -0
  45. package/skills/asc-review/SKILL.md +54 -0
  46. package/.agent-context/policies/llm-judge-threshold.json +0 -29
  47. package/.agent-context/prompts/bootstrap-design.md +0 -63
  48. package/.agent-context/prompts/compact-natural-mode.md +0 -100
  49. package/.agent-context/prompts/init-project.md +0 -60
  50. package/.agent-context/prompts/refactor.md +0 -38
  51. package/.agent-context/prompts/review-code.md +0 -31
  52. package/.agent-context/review-checklists/architecture-review.md +0 -57
  53. package/.agent-context/review-checklists/pr-checklist.md +0 -134
  54. package/.agent-context/rules/api-docs.md +0 -24
  55. package/.agent-context/rules/api-versioning.md +0 -16
  56. package/.agent-context/rules/architecture.md +0 -38
  57. package/.agent-context/rules/background-jobs.md +0 -17
  58. package/.agent-context/rules/config-and-flags.md +0 -16
  59. package/.agent-context/rules/database-design.md +0 -18
  60. package/.agent-context/rules/docker-runtime.md +0 -17
  61. package/.agent-context/rules/error-handling.md +0 -16
  62. package/.agent-context/rules/event-driven.md +0 -16
  63. package/.agent-context/rules/frontend-architecture.md +0 -54
  64. package/.agent-context/rules/microservices.md +0 -16
  65. package/.agent-context/rules/migrations.md +0 -16
  66. package/.agent-context/rules/observability.md +0 -16
  67. package/.agent-context/rules/performance.md +0 -16
  68. package/.agent-context/rules/realtime.md +0 -16
  69. package/.agent-context/rules/resilience.md +0 -18
  70. package/.agent-context/rules/security.md +0 -18
  71. package/.agent-context/rules/testing.md +0 -16
  72. package/.agent-context/state/README.md +0 -25
  73. package/.agent-context/state/architecture-map.md +0 -40
  74. package/.agent-context/state/benchmark-comparison-schema.json +0 -181
  75. package/.agent-context/state/benchmark-reproducibility.json +0 -87
  76. package/.agent-context/state/benchmark-thresholds.json +0 -10
  77. package/.agent-context/state/benchmark-writer-judge-config.json +0 -58
  78. package/.agent-context/state/dependency-map.md +0 -41
  79. package/.agent-context/state/memory-adapter-contract.json +0 -52
  80. package/.agent-context/state/memory-schema-v1.json +0 -88
  81. package/GEMINI.md +0 -1
  82. package/benchmarks/README.md +0 -60
  83. package/benchmarks/compact-natural-mode/fixtures.mjs +0 -359
  84. package/benchmarks/compact-natural-mode/scorer.mjs +0 -331
  85. package/benchmarks/runtime-token-saver/fixtures.mjs +0 -836
  86. package/lib/cli/adaptive-context/catalog.mjs +0 -394
  87. package/lib/cli/adaptive-context/file-signals.mjs +0 -100
  88. package/lib/cli/adaptive-context/implications.mjs +0 -44
  89. package/lib/cli/adaptive-context.mjs +0 -151
  90. package/lib/cli/audits/typography-palette-anti-repeat/color-utils.mjs +0 -156
  91. package/lib/cli/audits/typography-palette-anti-repeat/file-scanner.mjs +0 -103
  92. package/lib/cli/audits/typography-palette-anti-repeat/typography-utils.mjs +0 -70
  93. package/lib/cli/backup.mjs +0 -210
  94. package/lib/cli/commands/context.mjs +0 -140
  95. package/lib/cli/commands/init/project-context.mjs +0 -60
  96. package/lib/cli/commands/init/runtime-environment.mjs +0 -59
  97. package/lib/cli/commands/init/setup-decisions.mjs +0 -83
  98. package/lib/cli/commands/init.mjs +0 -654
  99. package/lib/cli/commands/launch.mjs +0 -76
  100. package/lib/cli/commands/optimize.mjs +0 -284
  101. package/lib/cli/commands/rollback.mjs +0 -64
  102. package/lib/cli/commands/upgrade/token-optimization-state.mjs +0 -51
  103. package/lib/cli/commands/upgrade.mjs +0 -451
  104. package/lib/cli/compiler.mjs +0 -187
  105. package/lib/cli/constants.mjs +0 -136
  106. package/lib/cli/detector/constants.mjs +0 -135
  107. package/lib/cli/detector/design-evidence/collector.mjs +0 -256
  108. package/lib/cli/detector/design-evidence/constants.mjs +0 -39
  109. package/lib/cli/detector/design-evidence/file-traversal.mjs +0 -83
  110. package/lib/cli/detector/design-evidence/structured-attribute-evidence.mjs +0 -117
  111. package/lib/cli/detector/design-evidence/summary.mjs +0 -109
  112. package/lib/cli/detector/design-evidence/utility-helpers.mjs +0 -122
  113. package/lib/cli/detector/design-evidence.mjs +0 -25
  114. package/lib/cli/detector/stack-detection.mjs +0 -243
  115. package/lib/cli/detector/ui-signals.mjs +0 -150
  116. package/lib/cli/detector/workspace-scan.mjs +0 -177
  117. package/lib/cli/detector.mjs +0 -23
  118. package/lib/cli/init-detection-flow.mjs +0 -48
  119. package/lib/cli/init-options.mjs +0 -237
  120. package/lib/cli/init-selection.mjs +0 -29
  121. package/lib/cli/memory-continuity.mjs +0 -537
  122. package/lib/cli/preflight.mjs +0 -76
  123. package/lib/cli/project-scaffolder/constants.mjs +0 -69
  124. package/lib/cli/project-scaffolder/discovery.mjs +0 -272
  125. package/lib/cli/project-scaffolder/prompt-builders.mjs +0 -171
  126. package/lib/cli/project-scaffolder/storage.mjs +0 -144
  127. package/lib/cli/project-scaffolder/ui-scope-detection.mjs +0 -36
  128. package/lib/cli/project-scaffolder.mjs +0 -29
  129. package/lib/cli/rollback.mjs +0 -66
  130. package/lib/cli/token-optimization.mjs +0 -401
  131. package/lib/cli/utils/filesystem.mjs +0 -81
  132. package/lib/cli/utils/managed-surface.mjs +0 -280
  133. package/lib/cli/utils/prompting.mjs +0 -44
  134. package/lib/cli/utils.mjs +0 -479
  135. package/mcp.json +0 -134
  136. package/scripts/adaptive-context/fixtures.mjs +0 -183
  137. package/scripts/adaptive-context-benchmark.mjs +0 -9
  138. package/scripts/ascx-runtime-token-saver-benchmark.mjs +0 -9
  139. package/scripts/benchmark-evidence-bundle.mjs +0 -645
  140. package/scripts/benchmark-gate.mjs +0 -121
  141. package/scripts/benchmark-intelligence.mjs +0 -33
  142. package/scripts/benchmark-writer-judge-matrix.mjs +0 -379
  143. package/scripts/build-release-benchmark-bundle.mjs +0 -202
  144. package/scripts/bump-version.mjs +0 -103
  145. package/scripts/clean-local-artifacts.mjs +0 -78
  146. package/scripts/compact-natural-mode-benchmark.mjs +0 -9
  147. package/scripts/context-triggered-audit.mjs +0 -391
  148. package/scripts/detection-benchmark.mjs +0 -127
  149. package/scripts/docs-quality-drift-report.mjs +0 -358
  150. package/scripts/documentation-boundary-audit.mjs +0 -305
  151. package/scripts/explain-on-demand-audit.mjs +0 -427
  152. package/scripts/forbidden-content-check.mjs +0 -123
  153. package/scripts/frontend-usability-audit.mjs +0 -243
  154. package/scripts/generate-sbom.mjs +0 -61
  155. package/scripts/governance-weekly-report.mjs +0 -466
  156. package/scripts/llm-judge/checklist-loader.mjs +0 -45
  157. package/scripts/llm-judge/constants.mjs +0 -66
  158. package/scripts/llm-judge/diff-collection.mjs +0 -74
  159. package/scripts/llm-judge/prompting.mjs +0 -78
  160. package/scripts/llm-judge/providers.mjs +0 -111
  161. package/scripts/llm-judge/verdict.mjs +0 -134
  162. package/scripts/llm-judge.mjs +0 -200
  163. package/scripts/memory-continuity-benchmark.mjs +0 -322
  164. package/scripts/quality-trend-report.mjs +0 -289
  165. package/scripts/release-gate/audit-checks.mjs +0 -441
  166. package/scripts/release-gate/constants.mjs +0 -53
  167. package/scripts/release-gate/runtime.mjs +0 -63
  168. package/scripts/release-gate/static-checks.mjs +0 -182
  169. package/scripts/release-gate.mjs +0 -42
  170. package/scripts/rules-guardian-audit.mjs +0 -580
  171. package/scripts/single-source-lazy-loading-audit.mjs +0 -449
  172. package/scripts/sync-thin-adapters.mjs +0 -72
  173. package/scripts/token-optimization-benchmark.mjs +0 -252
  174. package/scripts/ui-design-judge/constants.mjs +0 -13
  175. package/scripts/ui-design-judge/design-execution-summary.mjs +0 -81
  176. package/scripts/ui-design-judge/git-input.mjs +0 -134
  177. package/scripts/ui-design-judge/prompting.mjs +0 -52
  178. package/scripts/ui-design-judge/providers.mjs +0 -102
  179. package/scripts/ui-design-judge/reporting.mjs +0 -183
  180. package/scripts/ui-design-judge/rubric-calibration.mjs +0 -214
  181. package/scripts/ui-design-judge/rubric-goldset.json +0 -188
  182. package/scripts/ui-design-judge.mjs +0 -319
  183. package/scripts/ui-rubric-calibration.mjs +0 -35
  184. package/scripts/validate/audits/cache-layer-contract.mjs +0 -230
  185. package/scripts/validate/audits/caching-scope-hygiene.mjs +0 -235
  186. package/scripts/validate/audits/file-size.mjs +0 -158
  187. package/scripts/validate/audits/reflection-citations.mjs +0 -130
  188. package/scripts/validate/audits/release-bundle.mjs +0 -135
  189. package/scripts/validate/audits/rule-id-uniqueness.mjs +0 -278
  190. package/scripts/validate/config.mjs +0 -501
  191. package/scripts/validate/coverage-checks.mjs +0 -446
  192. package/scripts/validate/file-structure.mjs +0 -158
  193. package/scripts/validate/markdown-content.mjs +0 -109
  194. package/scripts/validate/project-metadata.mjs +0 -166
  195. package/scripts/validate/utils.mjs +0 -52
  196. package/scripts/validate.mjs +0 -267
@@ -1,150 +0,0 @@
1
- /**
2
- * UI scope detection: combines marker sets, package.json dependencies, nested
3
- * workspace evidence, and explicit user scope keys to decide whether the
4
- * current target directory is a UI surface. Triggers the lightweight design
5
- * evidence scan when the answer is yes.
6
- */
7
-
8
- import { collectFrontendDesignEvidence } from './design-evidence.mjs';
9
- import { DIRECT_UI_MARKER_NAMES } from './constants.mjs';
10
- import { collectNestedWorkspaceProjects, collectProjectMarkers, readPackageJsonIfExists } from './workspace-scan.mjs';
11
-
12
- const UI_DEPENDENCY_NAMES = ['next', 'react', 'react-dom', 'react-native', 'expo', 'tailwindcss'];
13
-
14
- function analyzeUiSignalsForMarkerSet(markerNames, packageManifest, sourceLabel = null) {
15
- const detectedUiMarkers = DIRECT_UI_MARKER_NAMES.filter((markerName) => markerNames.has(markerName));
16
- const dependencySource = {
17
- ...(packageManifest?.dependencies || {}),
18
- ...(packageManifest?.devDependencies || {}),
19
- };
20
- const detectedUiDependencies = UI_DEPENDENCY_NAMES.filter((dependencyName) => dependencySource[dependencyName]);
21
- const hasStrongUiMarker = detectedUiMarkers.some((markerName) => (
22
- markerName.startsWith('next.config')
23
- || markerName === 'react-native.config.js'
24
- || markerName === 'android'
25
- || markerName === 'ios'
26
- ));
27
- const hasUiDependencies = detectedUiDependencies.length > 0;
28
- const hasStructuralUiMarkers = detectedUiMarkers.length >= 2;
29
- const signalReasons = [];
30
- const sourcePrefix = sourceLabel ? `${sourceLabel}: ` : '';
31
-
32
- if (detectedUiMarkers.length > 0) {
33
- signalReasons.push(`${sourcePrefix}ui markers: ${detectedUiMarkers.join(', ')}`);
34
- }
35
-
36
- if (detectedUiDependencies.length > 0) {
37
- signalReasons.push(`${sourcePrefix}ui dependencies: ${detectedUiDependencies.join(', ')}`);
38
- }
39
-
40
- return {
41
- signalReasons,
42
- detectedUiMarkers,
43
- detectedUiDependencies,
44
- hasStrongUiMarker,
45
- hasUiDependencies,
46
- hasStructuralUiMarkers,
47
- };
48
- }
49
-
50
- export async function detectUiScopeSignals({
51
- targetDirectoryPath,
52
- selectedStackFileName,
53
- selectedBlueprintFileName,
54
- packageManifest = null,
55
- projectScopeKey = null,
56
- projectScopeSourceLabel = 'project scope',
57
- }) {
58
- const signalReasons = [];
59
- const markerNames = await collectProjectMarkers(targetDirectoryPath);
60
- const resolvedPackageManifest = packageManifest || await readPackageJsonIfExists(targetDirectoryPath);
61
- const nestedWorkspaceProjects = await collectNestedWorkspaceProjects(targetDirectoryPath);
62
-
63
- const normalizedProjectScopeKey = String(projectScopeKey || '').trim().toLowerCase();
64
- if (normalizedProjectScopeKey === 'frontend-only' || normalizedProjectScopeKey === 'both') {
65
- signalReasons.push(`${projectScopeSourceLabel}: ${normalizedProjectScopeKey}`);
66
- }
67
-
68
- const selectedStackKey = String(selectedStackFileName || '').trim().toLowerCase();
69
- if (selectedStackKey === 'react-native.md' || selectedStackKey === 'flutter.md') {
70
- signalReasons.push(`selected stack implies UI runtime: ${selectedStackKey}`);
71
- }
72
-
73
- const selectedBlueprintKey = String(selectedBlueprintFileName || '').trim().toLowerCase();
74
- if (selectedBlueprintKey.includes('frontend') || selectedBlueprintKey.includes('landing') || selectedBlueprintKey.includes('mobile-app')) {
75
- signalReasons.push(`selected blueprint implies UI scope: ${selectedBlueprintKey}`);
76
- }
77
-
78
- const rootUiSignals = analyzeUiSignalsForMarkerSet(markerNames, resolvedPackageManifest);
79
- signalReasons.push(...rootUiSignals.signalReasons);
80
-
81
- const nestedUiSignals = nestedWorkspaceProjects
82
- .map((nestedWorkspaceProject) => ({
83
- ...nestedWorkspaceProject,
84
- ...analyzeUiSignalsForMarkerSet(
85
- nestedWorkspaceProject.markerNames,
86
- nestedWorkspaceProject.packageManifest,
87
- `workspace ${nestedWorkspaceProject.relativePath}`,
88
- ),
89
- }))
90
- .filter((nestedWorkspaceProject) => nestedWorkspaceProject.signalReasons.length > 0);
91
-
92
- for (const nestedUiSignal of nestedUiSignals) {
93
- signalReasons.push(...nestedUiSignal.signalReasons);
94
- }
95
-
96
- const detectedUiMarkers = Array.from(new Set([
97
- ...rootUiSignals.detectedUiMarkers,
98
- ...nestedUiSignals.flatMap((nestedUiSignal) => nestedUiSignal.detectedUiMarkers),
99
- ]));
100
- const detectedUiDependencies = Array.from(new Set([
101
- ...rootUiSignals.detectedUiDependencies,
102
- ...nestedUiSignals.flatMap((nestedUiSignal) => nestedUiSignal.detectedUiDependencies),
103
- ]));
104
-
105
- const hasStrongUiMarker = rootUiSignals.hasStrongUiMarker
106
- || nestedUiSignals.some((nestedUiSignal) => nestedUiSignal.hasStrongUiMarker);
107
- const hasUiDependencies = rootUiSignals.hasUiDependencies
108
- || nestedUiSignals.some((nestedUiSignal) => nestedUiSignal.hasUiDependencies);
109
- const hasStructuralUiMarkers = rootUiSignals.hasStructuralUiMarkers
110
- || nestedUiSignals.some((nestedUiSignal) => nestedUiSignal.hasStructuralUiMarkers);
111
- const isUiScopeLikely = signalReasons.length > 0
112
- && (hasStrongUiMarker || hasUiDependencies || hasStructuralUiMarkers || normalizedProjectScopeKey.length > 0);
113
- const preferredUiWorkspaceEntry = nestedUiSignals.find((nestedUiSignal) => (
114
- nestedUiSignal.hasStrongUiMarker
115
- || nestedUiSignal.hasUiDependencies
116
- || nestedUiSignal.hasStructuralUiMarkers
117
- )) || null;
118
- const frontendScanRootDirectoryPaths = (
119
- !rootUiSignals.hasStrongUiMarker
120
- && !rootUiSignals.hasUiDependencies
121
- && !rootUiSignals.hasStructuralUiMarkers
122
- && nestedUiSignals.length > 0
123
- )
124
- ? nestedUiSignals.map((nestedUiSignal) => nestedUiSignal.directoryPath)
125
- : [];
126
- const designEvidence = isUiScopeLikely
127
- ? await collectFrontendDesignEvidence({
128
- targetDirectoryPath,
129
- markerNames,
130
- scanRootDirectoryPaths: frontendScanRootDirectoryPaths,
131
- })
132
- : null;
133
- const frontendEvidenceMetrics = designEvidence?.frontendEvidenceMetrics || null;
134
- const designEvidenceSummary = designEvidence?.designEvidenceSummary || null;
135
-
136
- return {
137
- isUiScopeLikely,
138
- signalReasons,
139
- detectedUiMarkers,
140
- detectedUiDependencies,
141
- frontendEvidenceMetrics,
142
- designEvidenceSummary,
143
- packageManifest: preferredUiWorkspaceEntry?.packageManifest || resolvedPackageManifest,
144
- workspaceUiEntries: nestedUiSignals.map((nestedUiSignal) => ({
145
- relativePath: nestedUiSignal.relativePath,
146
- detectedUiMarkers: nestedUiSignal.detectedUiMarkers,
147
- detectedUiDependencies: nestedUiSignal.detectedUiDependencies,
148
- })),
149
- };
150
- }
@@ -1,177 +0,0 @@
1
- /**
2
- * Workspace traversal: from a target directory, find immediate project markers,
3
- * locate nested project candidates inside monorepo containers, and read package
4
- * manifests when present. The scan is bounded by max depth and a per-run
5
- * directory budget so it terminates cleanly on huge repos.
6
- */
7
-
8
- import fs from 'node:fs/promises';
9
- import path from 'node:path';
10
-
11
- import {
12
- hasProjectMarkers,
13
- INTERNAL_GOVERNANCE_SURFACE_NAMES,
14
- looksLikeWorkspaceSearchCandidate,
15
- WORKSPACE_CONTAINER_DIRECTORY_NAMES,
16
- WORKSPACE_ROOT_MARKER_FILE_NAMES,
17
- WORKSPACE_SCAN_IGNORE_DIRECTORY_NAMES,
18
- WORKSPACE_SCAN_MAX_DEPTH,
19
- WORKSPACE_SCAN_MAX_DIRECTORIES,
20
- } from './constants.mjs';
21
-
22
- export async function collectProjectMarkers(targetDirectoryPath) {
23
- const markerNames = new Set();
24
- const directoryEntries = await fs.readdir(targetDirectoryPath, { withFileTypes: true });
25
-
26
- for (const directoryEntry of directoryEntries) {
27
- if (directoryEntry.name === '.git' || directoryEntry.name === 'node_modules') {
28
- continue;
29
- }
30
-
31
- if (INTERNAL_GOVERNANCE_SURFACE_NAMES.has(directoryEntry.name)) {
32
- continue;
33
- }
34
-
35
- markerNames.add(directoryEntry.name);
36
- }
37
-
38
- return markerNames;
39
- }
40
-
41
- export async function readPackageJsonIfExists(targetDirectoryPath) {
42
- const packageJsonPath = path.join(targetDirectoryPath, 'package.json');
43
-
44
- try {
45
- const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8');
46
- return JSON.parse(packageJsonContent);
47
- } catch {
48
- return null;
49
- }
50
- }
51
-
52
- async function readDirectoryEntries(directoryPath) {
53
- try {
54
- return await fs.readdir(directoryPath, { withFileTypes: true });
55
- } catch {
56
- return [];
57
- }
58
- }
59
-
60
- export async function collectNestedWorkspaceProjects(targetDirectoryPath) {
61
- const rootDirectoryEntries = await readDirectoryEntries(targetDirectoryPath);
62
- const rootMarkerNames = new Set(rootDirectoryEntries.map((directoryEntry) => directoryEntry.name));
63
- const rootLooksLikeWorkspace = Array.from(rootMarkerNames).some((markerName) => (
64
- WORKSPACE_ROOT_MARKER_FILE_NAMES.has(markerName)
65
- || looksLikeWorkspaceSearchCandidate(markerName)
66
- ));
67
- const nestedWorkspaceProjects = [];
68
- const queuedWorkspacePaths = new Set();
69
- const workspaceQueue = [];
70
- let scannedDirectoryCount = 0;
71
-
72
- for (const rootDirectoryEntry of rootDirectoryEntries) {
73
- if (!rootDirectoryEntry.isDirectory()) {
74
- continue;
75
- }
76
-
77
- if (WORKSPACE_SCAN_IGNORE_DIRECTORY_NAMES.has(rootDirectoryEntry.name)) {
78
- continue;
79
- }
80
-
81
- const shouldInspectRootChild = rootLooksLikeWorkspace
82
- || looksLikeWorkspaceSearchCandidate(rootDirectoryEntry.name);
83
-
84
- if (!shouldInspectRootChild) {
85
- continue;
86
- }
87
-
88
- const rootChildDirectoryPath = path.join(targetDirectoryPath, rootDirectoryEntry.name);
89
- const rootChildEntries = await readDirectoryEntries(rootChildDirectoryPath);
90
- const rootChildMarkerNames = new Set(rootChildEntries.map((directoryEntry) => directoryEntry.name));
91
- const rootChildRelativePath = rootDirectoryEntry.name.replace(/\\/g, '/');
92
-
93
- workspaceQueue.push({
94
- directoryPath: rootChildDirectoryPath,
95
- relativePath: rootChildRelativePath,
96
- markerNames: rootChildMarkerNames,
97
- depth: 1,
98
- underWorkspaceContainer: WORKSPACE_CONTAINER_DIRECTORY_NAMES.has(rootDirectoryEntry.name.toLowerCase()),
99
- });
100
- queuedWorkspacePaths.add(rootChildRelativePath);
101
- }
102
-
103
- while (workspaceQueue.length > 0 && scannedDirectoryCount < WORKSPACE_SCAN_MAX_DIRECTORIES) {
104
- const currentWorkspaceEntry = workspaceQueue.shift();
105
- scannedDirectoryCount += 1;
106
-
107
- const isProjectCandidate = hasProjectMarkers(currentWorkspaceEntry.markerNames);
108
- const currentDirectoryName = path.basename(currentWorkspaceEntry.directoryPath).toLowerCase();
109
- const isWorkspaceContainer = WORKSPACE_CONTAINER_DIRECTORY_NAMES.has(currentDirectoryName);
110
-
111
- if (isProjectCandidate) {
112
- nestedWorkspaceProjects.push({
113
- directoryPath: currentWorkspaceEntry.directoryPath,
114
- relativePath: currentWorkspaceEntry.relativePath,
115
- markerNames: currentWorkspaceEntry.markerNames,
116
- packageManifest: currentWorkspaceEntry.markerNames.has('package.json')
117
- ? await readPackageJsonIfExists(currentWorkspaceEntry.directoryPath)
118
- : null,
119
- });
120
- }
121
-
122
- if (currentWorkspaceEntry.depth >= WORKSPACE_SCAN_MAX_DEPTH) {
123
- continue;
124
- }
125
-
126
- const shouldTraverseChildren = currentWorkspaceEntry.underWorkspaceContainer
127
- || isWorkspaceContainer
128
- || !isProjectCandidate;
129
-
130
- if (!shouldTraverseChildren) {
131
- continue;
132
- }
133
-
134
- const childEntries = await readDirectoryEntries(currentWorkspaceEntry.directoryPath);
135
- for (const childEntry of childEntries) {
136
- if (!childEntry.isDirectory()) {
137
- continue;
138
- }
139
-
140
- if (WORKSPACE_SCAN_IGNORE_DIRECTORY_NAMES.has(childEntry.name)) {
141
- continue;
142
- }
143
-
144
- const childLooksRelevant = looksLikeWorkspaceSearchCandidate(childEntry.name);
145
- if (!childLooksRelevant && !currentWorkspaceEntry.underWorkspaceContainer && !isWorkspaceContainer) {
146
- continue;
147
- }
148
-
149
- const childDirectoryPath = path.join(currentWorkspaceEntry.directoryPath, childEntry.name);
150
- const childRelativePath = path.join(currentWorkspaceEntry.relativePath, childEntry.name).replace(/\\/g, '/');
151
-
152
- if (queuedWorkspacePaths.has(childRelativePath)) {
153
- continue;
154
- }
155
-
156
- const childDirectoryEntries = await readDirectoryEntries(childDirectoryPath);
157
- const childMarkerNames = new Set(childDirectoryEntries.map((directoryEntry) => directoryEntry.name));
158
- const childIsProjectCandidate = hasProjectMarkers(childMarkerNames);
159
- const childIsWorkspaceContainer = WORKSPACE_CONTAINER_DIRECTORY_NAMES.has(childEntry.name.toLowerCase());
160
-
161
- if (!childIsProjectCandidate && !childIsWorkspaceContainer && !childLooksRelevant) {
162
- continue;
163
- }
164
-
165
- workspaceQueue.push({
166
- directoryPath: childDirectoryPath,
167
- relativePath: childRelativePath,
168
- markerNames: childMarkerNames,
169
- depth: currentWorkspaceEntry.depth + 1,
170
- underWorkspaceContainer: currentWorkspaceEntry.underWorkspaceContainer || isWorkspaceContainer || childIsWorkspaceContainer,
171
- });
172
- queuedWorkspacePaths.add(childRelativePath);
173
- }
174
- }
175
-
176
- return nestedWorkspaceProjects;
177
- }
@@ -1,23 +0,0 @@
1
- /**
2
- * Stack Detector — project context auto-detection. Aggregator that re-exports
3
- * the public surface of the detector subsystem. Implementation lives under
4
- * lib/cli/detector/* split per concern: workspace scan, UI signal analysis,
5
- * and stack detection scoring.
6
- *
7
- * Public exports:
8
- * collectProjectMarkers — read top-level markers in a directory
9
- * detectProjectContext — top-level stack detection with ranked candidates
10
- * detectUiScopeSignals — UI scope detection plus design evidence scan;
11
- * returns frontendEvidenceMetrics and
12
- * designEvidenceSummary when UI scope is detected
13
- * buildDetectionSummary — human-readable detection summary text
14
- * formatDetectionCandidates — formatter for ranked detection candidates
15
- */
16
-
17
- export { collectProjectMarkers } from './detector/workspace-scan.mjs';
18
- export { detectUiScopeSignals } from './detector/ui-signals.mjs';
19
- export {
20
- buildDetectionSummary,
21
- detectProjectContext,
22
- formatDetectionCandidates,
23
- } from './detector/stack-detection.mjs';
@@ -1,48 +0,0 @@
1
- export function buildExistingProjectMajorConstraints({ mode = 'init' } = {}) {
2
- if (mode === 'upgrade') {
3
- return [
4
- 'Preserve existing project markers and avoid forced stack migration.',
5
- 'Use runtime markers as evidence only unless the user already recorded an explicit runtime constraint.',
6
- 'Upgrade keeps prior explicit onboarding constraints but does not create new stack or blueprint decisions.',
7
- ];
8
- }
9
-
10
- return [
11
- 'Preserve existing project markers and avoid forced stack migration.',
12
- 'Use detected runtime markers as evidence only; do not convert them into stack migration or design direction.',
13
- 'Explicit stack or blueprint overrides are constraints only when the user provides them.',
14
- ];
15
- }
16
-
17
- export async function resolveDetectedSetupDecision({
18
- shouldAutoApplyDetectedStack,
19
- projectDetection,
20
- detectionTransparency,
21
- initialSelectedManualStackFileName,
22
- initialSelectedManualBlueprintFileName,
23
- initialSelectedAdditionalStackFileNames,
24
- }) {
25
- let selectedManualStackFileName = initialSelectedManualStackFileName || null;
26
- let selectedManualBlueprintFileName = initialSelectedManualBlueprintFileName || null;
27
- let selectedAdditionalStackFileNames = initialSelectedAdditionalStackFileNames || [];
28
- let detectedSetupWasApplied = false;
29
-
30
- if (shouldAutoApplyDetectedStack) {
31
- detectionTransparency.quickConfirmation.response = 'evidence-only';
32
- detectionTransparency.decision.mode = 'existing-project-evidence-only';
33
- selectedAdditionalStackFileNames = [];
34
- } else if (projectDetection.hasExistingProjectFiles && projectDetection.detectedStackFileName) {
35
- detectionTransparency.quickConfirmation.response = 'evidence-only';
36
- detectionTransparency.decision.mode = 'existing-project-evidence-only';
37
- } else if (!projectDetection.hasExistingProjectFiles) {
38
- detectionTransparency.quickConfirmation.response = 'not-applicable';
39
- detectionTransparency.decision.mode = 'fresh-agent-decision-required';
40
- }
41
-
42
- return {
43
- detectedSetupWasApplied,
44
- selectedManualStackFileName,
45
- selectedManualBlueprintFileName,
46
- selectedAdditionalStackFileNames,
47
- };
48
- }
@@ -1,237 +0,0 @@
1
- /**
2
- * Init Options Parser — isolates CLI option parsing from init runtime flow.
3
- */
4
- import { normalizeDocsLanguage } from './project-scaffolder.mjs';
5
- import { normalizeAgentName } from './token-optimization.mjs';
6
- import { normalizeChoiceInput, matchProfileNameFromInput } from './utils.mjs';
7
-
8
- export function normalizeRuntimeEnvironmentKey(rawRuntimeEnvironmentKey) {
9
- const normalizedRuntimeEnvironmentKey = normalizeChoiceInput(String(rawRuntimeEnvironmentKey || 'auto'));
10
- const supportedRuntimeEnvironmentKeys = new Set(['auto', 'linux-wsl', 'linux', 'windows', 'macos']);
11
- return supportedRuntimeEnvironmentKeys.has(normalizedRuntimeEnvironmentKey) ? normalizedRuntimeEnvironmentKey : null;
12
- }
13
-
14
- export function parseInitArguments(commandArguments) {
15
- const parsedInitOptions = {
16
- targetDirectory: '.',
17
- preset: undefined,
18
- profile: undefined,
19
- stack: undefined,
20
- blueprint: undefined,
21
- ci: undefined,
22
- newbie: false,
23
- tokenOptimize: true,
24
- memoryContinuity: true,
25
- tokenAgent: 'copilot',
26
- includeMcpTemplate: false,
27
- localOnly: undefined,
28
- scaffoldDocs: undefined,
29
- docsLang: 'en',
30
- docsLangProvided: false,
31
- projectConfig: undefined,
32
- projectDescription: '',
33
- runtimeEnv: 'auto',
34
- runtimeEnvProvided: false,
35
- };
36
-
37
- for (let argumentIndex = 0; argumentIndex < commandArguments.length; argumentIndex++) {
38
- const currentArgument = commandArguments[argumentIndex];
39
-
40
- if (!currentArgument.startsWith('--')) {
41
- parsedInitOptions.targetDirectory = currentArgument;
42
- continue;
43
- }
44
-
45
- if (currentArgument === '--profile') {
46
- parsedInitOptions.profile = matchProfileNameFromInput(commandArguments[argumentIndex + 1] || '');
47
- argumentIndex += 1;
48
- continue;
49
- }
50
-
51
- if (currentArgument === '--preset') {
52
- parsedInitOptions.preset = normalizeChoiceInput(commandArguments[argumentIndex + 1] || '');
53
- argumentIndex += 1;
54
- continue;
55
- }
56
-
57
- if (currentArgument.startsWith('--preset=')) {
58
- parsedInitOptions.preset = normalizeChoiceInput(currentArgument.split('=')[1]);
59
- continue;
60
- }
61
-
62
- if (currentArgument.startsWith('--profile=')) {
63
- parsedInitOptions.profile = matchProfileNameFromInput(currentArgument.split('=')[1]);
64
- continue;
65
- }
66
-
67
- if (currentArgument === '--stack') {
68
- parsedInitOptions.stack = commandArguments[argumentIndex + 1];
69
- argumentIndex += 1;
70
- continue;
71
- }
72
-
73
- if (currentArgument.startsWith('--stack=')) {
74
- parsedInitOptions.stack = currentArgument.split('=')[1];
75
- continue;
76
- }
77
-
78
- if (currentArgument === '--blueprint') {
79
- parsedInitOptions.blueprint = commandArguments[argumentIndex + 1];
80
- argumentIndex += 1;
81
- continue;
82
- }
83
-
84
- if (currentArgument.startsWith('--blueprint=')) {
85
- parsedInitOptions.blueprint = currentArgument.split('=')[1];
86
- continue;
87
- }
88
-
89
- if (currentArgument === '--ci') {
90
- const ciRawValue = commandArguments[argumentIndex + 1];
91
- parsedInitOptions.ci = ciRawValue?.toLowerCase() === 'true';
92
- argumentIndex += 1;
93
- continue;
94
- }
95
-
96
- if (currentArgument.startsWith('--ci=')) {
97
- parsedInitOptions.ci = currentArgument.split('=')[1]?.toLowerCase() === 'true';
98
- continue;
99
- }
100
-
101
- if (currentArgument === '--newbie') {
102
- parsedInitOptions.newbie = true;
103
- continue;
104
- }
105
-
106
- if (currentArgument === '--token-optimize') {
107
- parsedInitOptions.tokenOptimize = true;
108
- continue;
109
- }
110
-
111
- if (currentArgument === '--memory-continuity') {
112
- parsedInitOptions.memoryContinuity = true;
113
- continue;
114
- }
115
-
116
- if (currentArgument === '--token-agent') {
117
- parsedInitOptions.tokenAgent = commandArguments[argumentIndex + 1] || 'copilot';
118
- argumentIndex += 1;
119
- continue;
120
- }
121
-
122
- if (currentArgument.startsWith('--token-agent=')) {
123
- parsedInitOptions.tokenAgent = currentArgument.split('=')[1] || 'copilot';
124
- continue;
125
- }
126
-
127
- if (currentArgument === '--no-token-optimize') {
128
- parsedInitOptions.tokenOptimize = false;
129
- continue;
130
- }
131
-
132
- if (currentArgument === '--no-memory-continuity') {
133
- parsedInitOptions.memoryContinuity = false;
134
- continue;
135
- }
136
-
137
- if (currentArgument === '--mcp-template') {
138
- parsedInitOptions.includeMcpTemplate = true;
139
- continue;
140
- }
141
-
142
- if (currentArgument === '--no-mcp-template') {
143
- parsedInitOptions.includeMcpTemplate = false;
144
- continue;
145
- }
146
-
147
- if (currentArgument === '--local-only') {
148
- parsedInitOptions.localOnly = true;
149
- continue;
150
- }
151
-
152
- if (currentArgument === '--no-local-only') {
153
- parsedInitOptions.localOnly = false;
154
- continue;
155
- }
156
-
157
- if (currentArgument === '--scaffold-docs') {
158
- parsedInitOptions.scaffoldDocs = true;
159
- continue;
160
- }
161
-
162
- if (currentArgument === '--no-scaffold-docs') {
163
- parsedInitOptions.scaffoldDocs = false;
164
- continue;
165
- }
166
-
167
- if (currentArgument === '--docs-lang') {
168
- parsedInitOptions.docsLang = commandArguments[argumentIndex + 1] || 'en';
169
- parsedInitOptions.docsLangProvided = true;
170
- argumentIndex += 1;
171
- continue;
172
- }
173
-
174
- if (currentArgument.startsWith('--docs-lang=')) {
175
- parsedInitOptions.docsLang = currentArgument.split('=')[1] || 'en';
176
- parsedInitOptions.docsLangProvided = true;
177
- continue;
178
- }
179
-
180
- if (currentArgument === '--project-config') {
181
- parsedInitOptions.projectConfig = commandArguments[argumentIndex + 1];
182
- argumentIndex += 1;
183
- continue;
184
- }
185
-
186
- if (currentArgument.startsWith('--project-config=')) {
187
- parsedInitOptions.projectConfig = currentArgument.split('=')[1];
188
- continue;
189
- }
190
-
191
- if (currentArgument === '--project-description') {
192
- parsedInitOptions.projectDescription = commandArguments[argumentIndex + 1] || '';
193
- argumentIndex += 1;
194
- continue;
195
- }
196
-
197
- if (currentArgument.startsWith('--project-description=')) {
198
- parsedInitOptions.projectDescription = currentArgument.split('=')[1] || '';
199
- continue;
200
- }
201
-
202
- if (currentArgument === '--runtime-env') {
203
- parsedInitOptions.runtimeEnv = commandArguments[argumentIndex + 1] || 'auto';
204
- parsedInitOptions.runtimeEnvProvided = true;
205
- argumentIndex += 1;
206
- continue;
207
- }
208
-
209
- if (currentArgument.startsWith('--runtime-env=')) {
210
- parsedInitOptions.runtimeEnv = currentArgument.split('=')[1] || 'auto';
211
- parsedInitOptions.runtimeEnvProvided = true;
212
- continue;
213
- }
214
-
215
- throw new Error(`Unknown option: ${currentArgument}`);
216
- }
217
-
218
- if (parsedInitOptions.newbie && parsedInitOptions.profile && parsedInitOptions.profile !== 'beginner') {
219
- throw new Error('--newbie can only be combined with --profile beginner');
220
- }
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
- const normalizedRuntimeEnvironment = normalizeRuntimeEnvironmentKey(parsedInitOptions.runtimeEnv || 'auto');
228
- if (!normalizedRuntimeEnvironment) {
229
- throw new Error('--runtime-env must be one of: auto, linux-wsl, linux, windows, macos');
230
- }
231
-
232
- parsedInitOptions.docsLang = normalizedDocsLanguage;
233
- parsedInitOptions.runtimeEnv = normalizedRuntimeEnvironment;
234
- parsedInitOptions.tokenAgent = normalizeAgentName(parsedInitOptions.tokenAgent);
235
-
236
- return parsedInitOptions;
237
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * Init Selection Helpers — stack/blueprint filtering and scope normalization.
3
- */
4
- import {
5
- PROJECT_SCOPE_CHOICES,
6
- } from './constants.mjs';
7
-
8
- export function resolveProjectScopeKeyFromLabel(selectedProjectScopeLabel) {
9
- const projectScopeEntry = PROJECT_SCOPE_CHOICES.find((scopeChoice) => scopeChoice.label === selectedProjectScopeLabel);
10
- return projectScopeEntry?.key || 'both';
11
- }
12
-
13
- export function normalizeAdditionalStackSelection(selectedStackFileName, additionalStackFileNames) {
14
- if (!Array.isArray(additionalStackFileNames) || additionalStackFileNames.length === 0) {
15
- return [];
16
- }
17
-
18
- return Array.from(new Set(additionalStackFileNames.filter((stackFileName) => stackFileName && stackFileName !== selectedStackFileName)));
19
- }
20
-
21
- export function normalizeAdditionalBlueprintSelection(selectedBlueprintFileName, additionalBlueprintFileNames) {
22
- if (!Array.isArray(additionalBlueprintFileNames) || additionalBlueprintFileNames.length === 0) {
23
- return [];
24
- }
25
-
26
- return Array.from(new Set(additionalBlueprintFileNames.filter(
27
- (blueprintFileName) => blueprintFileName && blueprintFileName !== selectedBlueprintFileName
28
- )));
29
- }