@ryuenn3123/agentic-senior-core 4.3.15 → 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.
- package/.agents/plugins/marketplace.json +21 -0
- package/.agents/rules/agentic-senior-core.md +126 -0
- package/.claude-plugin/marketplace.json +17 -0
- package/.claude-plugin/plugin.json +17 -0
- package/.clinerules/agentic-senior-core.md +94 -0
- package/.codex-plugin/plugin.json +24 -0
- package/.cursor/rules/agentic-senior-core.mdc +99 -0
- package/.devin-plugin/plugin.json +13 -0
- package/.github/copilot-instructions.md +94 -0
- package/.github/plugin/marketplace.json +20 -0
- package/.github/plugin/plugin.json +16 -0
- package/.kiro/steering/agentic-senior-core.md +94 -0
- package/.openclaw/skills/asc/SKILL.md +23 -0
- package/.openclaw/skills/asc-audit/SKILL.md +28 -0
- package/.openclaw/skills/asc-review/SKILL.md +54 -0
- package/.opencode/plugins/agentic-senior-core.mjs +31 -0
- package/.windsurf/rules/agentic-senior-core.md +94 -0
- package/AGENTS.md +126 -179
- package/CONTRIBUTING.md +93 -63
- package/README.md +160 -111
- package/__init__.py +61 -0
- package/bin/agentic-senior-core.js +41 -43
- package/commands/asc-audit.md +1 -0
- package/commands/asc-audit.toml +2 -0
- package/commands/asc-help.md +9 -0
- package/commands/asc-help.toml +2 -0
- package/commands/asc-refactor.md +1 -0
- package/commands/asc-refactor.toml +2 -0
- package/commands/asc-review.md +1 -0
- package/commands/asc-review.toml +2 -0
- package/gemini-extension.json +10 -0
- package/hooks/copilot-hooks.json +21 -0
- package/hooks/hooks.json +31 -0
- package/hooks/session-start.js +36 -0
- package/hooks/subagent-start.js +38 -0
- package/lib/cli/commands/adapter.mjs +109 -0
- package/lib/cli/commands/clean.mjs +63 -0
- package/lib/cli/commands/status.mjs +94 -0
- package/package.json +43 -67
- package/plugin.yaml +16 -0
- package/scripts/uninstall.js +38 -0
- package/skills/asc/SKILL.md +16 -0
- package/skills/asc-audit/SKILL.md +28 -0
- package/skills/asc-refactor/SKILL.md +35 -0
- package/skills/asc-review/SKILL.md +54 -0
- package/.agent-context/policies/llm-judge-threshold.json +0 -29
- package/.agent-context/prompts/bootstrap-design.md +0 -63
- package/.agent-context/prompts/compact-natural-mode.md +0 -100
- package/.agent-context/prompts/init-project.md +0 -60
- package/.agent-context/prompts/refactor.md +0 -38
- package/.agent-context/prompts/review-code.md +0 -31
- package/.agent-context/review-checklists/architecture-review.md +0 -57
- package/.agent-context/review-checklists/pr-checklist.md +0 -136
- package/.agent-context/rules/api-docs.md +0 -24
- package/.agent-context/rules/api-versioning.md +0 -16
- package/.agent-context/rules/architecture.md +0 -33
- package/.agent-context/rules/background-jobs.md +0 -17
- package/.agent-context/rules/config-and-flags.md +0 -16
- package/.agent-context/rules/database-design.md +0 -18
- package/.agent-context/rules/docker-runtime.md +0 -17
- package/.agent-context/rules/error-handling.md +0 -16
- package/.agent-context/rules/event-driven.md +0 -16
- package/.agent-context/rules/frontend-architecture.md +0 -54
- package/.agent-context/rules/microservices.md +0 -16
- package/.agent-context/rules/migrations.md +0 -16
- package/.agent-context/rules/observability.md +0 -16
- package/.agent-context/rules/performance.md +0 -16
- package/.agent-context/rules/realtime.md +0 -16
- package/.agent-context/rules/resilience.md +0 -18
- package/.agent-context/rules/security.md +0 -18
- package/.agent-context/rules/testing.md +0 -16
- package/.agent-context/state/README.md +0 -25
- package/.agent-context/state/architecture-map.md +0 -40
- package/.agent-context/state/benchmark-comparison-schema.json +0 -181
- package/.agent-context/state/benchmark-reproducibility.json +0 -87
- package/.agent-context/state/benchmark-thresholds.json +0 -10
- package/.agent-context/state/benchmark-writer-judge-config.json +0 -58
- package/.agent-context/state/dependency-map.md +0 -41
- package/.agent-context/state/memory-adapter-contract.json +0 -52
- package/.agent-context/state/memory-schema-v1.json +0 -88
- package/GEMINI.md +0 -1
- package/benchmarks/README.md +0 -60
- package/benchmarks/compact-natural-mode/fixtures.mjs +0 -359
- package/benchmarks/compact-natural-mode/scorer.mjs +0 -331
- package/benchmarks/runtime-token-saver/fixtures.mjs +0 -836
- package/lib/cli/adaptive-context/catalog.mjs +0 -390
- package/lib/cli/adaptive-context/file-signals.mjs +0 -100
- package/lib/cli/adaptive-context/implications.mjs +0 -44
- package/lib/cli/adaptive-context.mjs +0 -365
- package/lib/cli/audits/typography-palette-anti-repeat/color-utils.mjs +0 -156
- package/lib/cli/audits/typography-palette-anti-repeat/file-scanner.mjs +0 -103
- package/lib/cli/audits/typography-palette-anti-repeat/typography-utils.mjs +0 -70
- package/lib/cli/audits/typography-palette-anti-repeat-audit.mjs +0 -239
- package/lib/cli/backup.mjs +0 -210
- package/lib/cli/commands/audit-design-anti-repeat.mjs +0 -39
- package/lib/cli/commands/context.mjs +0 -140
- package/lib/cli/commands/init/project-context.mjs +0 -60
- package/lib/cli/commands/init/runtime-environment.mjs +0 -59
- package/lib/cli/commands/init/setup-decisions.mjs +0 -83
- package/lib/cli/commands/init.mjs +0 -654
- package/lib/cli/commands/launch.mjs +0 -76
- package/lib/cli/commands/optimize.mjs +0 -284
- package/lib/cli/commands/rollback.mjs +0 -64
- package/lib/cli/commands/upgrade/token-optimization-state.mjs +0 -51
- package/lib/cli/commands/upgrade.mjs +0 -451
- package/lib/cli/compiler.mjs +0 -570
- package/lib/cli/constants.mjs +0 -136
- package/lib/cli/detector/constants.mjs +0 -135
- package/lib/cli/detector/design-evidence/collector.mjs +0 -256
- package/lib/cli/detector/design-evidence/constants.mjs +0 -39
- package/lib/cli/detector/design-evidence/file-traversal.mjs +0 -83
- package/lib/cli/detector/design-evidence/structured-attribute-evidence.mjs +0 -117
- package/lib/cli/detector/design-evidence/summary.mjs +0 -109
- package/lib/cli/detector/design-evidence/utility-helpers.mjs +0 -122
- package/lib/cli/detector/design-evidence.mjs +0 -25
- package/lib/cli/detector/stack-detection.mjs +0 -243
- package/lib/cli/detector/ui-signals.mjs +0 -150
- package/lib/cli/detector/workspace-scan.mjs +0 -177
- package/lib/cli/detector.mjs +0 -23
- package/lib/cli/init-detection-flow.mjs +0 -48
- package/lib/cli/init-options.mjs +0 -237
- package/lib/cli/init-selection.mjs +0 -29
- package/lib/cli/memory-continuity.mjs +0 -537
- package/lib/cli/preflight.mjs +0 -76
- package/lib/cli/project-scaffolder/constants.mjs +0 -69
- package/lib/cli/project-scaffolder/discovery.mjs +0 -272
- package/lib/cli/project-scaffolder/prompt-builders.mjs +0 -171
- package/lib/cli/project-scaffolder/storage.mjs +0 -144
- package/lib/cli/project-scaffolder/ui-scope-detection.mjs +0 -36
- package/lib/cli/project-scaffolder.mjs +0 -29
- package/lib/cli/rollback.mjs +0 -66
- package/lib/cli/token-optimization.mjs +0 -486
- package/lib/cli/utils/filesystem.mjs +0 -81
- package/lib/cli/utils/managed-surface.mjs +0 -280
- package/lib/cli/utils/prompting.mjs +0 -44
- package/lib/cli/utils.mjs +0 -479
- package/mcp.json +0 -134
- package/scripts/adaptive-context/fixtures.mjs +0 -183
- package/scripts/adaptive-context-benchmark.mjs +0 -9
- package/scripts/ascx-runtime-token-saver-benchmark.mjs +0 -9
- package/scripts/audit-cache-layer-contract.mjs +0 -263
- package/scripts/audit-caching-scope-hygiene.mjs +0 -268
- package/scripts/audit-file-size.mjs +0 -219
- package/scripts/audit-reflection-citations.mjs +0 -163
- package/scripts/audit-release-bundle.mjs +0 -170
- package/scripts/audit-rule-id-uniqueness.mjs +0 -313
- package/scripts/audit-typography-palette-anti-repeat.mjs +0 -120
- package/scripts/benchmark-evidence-bundle.mjs +0 -645
- package/scripts/benchmark-gate.mjs +0 -121
- package/scripts/benchmark-intelligence.mjs +0 -33
- package/scripts/benchmark-writer-judge-matrix.mjs +0 -379
- package/scripts/build-release-benchmark-bundle.mjs +0 -202
- package/scripts/bump-version.mjs +0 -103
- package/scripts/clean-local-artifacts.mjs +0 -78
- package/scripts/compact-natural-mode-benchmark.mjs +0 -9
- package/scripts/context-triggered-audit.mjs +0 -391
- package/scripts/detection-benchmark.mjs +0 -127
- package/scripts/docs-quality-drift-report.mjs +0 -358
- package/scripts/documentation-boundary-audit.mjs +0 -305
- package/scripts/explain-on-demand-audit.mjs +0 -427
- package/scripts/forbidden-content-check.mjs +0 -123
- package/scripts/frontend-usability-audit.mjs +0 -243
- package/scripts/generate-sbom.mjs +0 -61
- package/scripts/governance-weekly-report.mjs +0 -466
- package/scripts/llm-judge/checklist-loader.mjs +0 -45
- package/scripts/llm-judge/constants.mjs +0 -66
- package/scripts/llm-judge/diff-collection.mjs +0 -74
- package/scripts/llm-judge/prompting.mjs +0 -78
- package/scripts/llm-judge/providers.mjs +0 -111
- package/scripts/llm-judge/verdict.mjs +0 -134
- package/scripts/llm-judge.mjs +0 -200
- package/scripts/memory-continuity-benchmark.mjs +0 -322
- package/scripts/quality-trend-report.mjs +0 -289
- package/scripts/release-gate/audit-checks.mjs +0 -441
- package/scripts/release-gate/constants.mjs +0 -53
- package/scripts/release-gate/runtime.mjs +0 -63
- package/scripts/release-gate/static-checks.mjs +0 -182
- package/scripts/release-gate.mjs +0 -42
- package/scripts/rules-guardian-audit.mjs +0 -580
- package/scripts/single-source-lazy-loading-audit.mjs +0 -449
- package/scripts/sync-thin-adapters.mjs +0 -72
- package/scripts/token-optimization-benchmark.mjs +0 -252
- package/scripts/ui-design-judge/constants.mjs +0 -13
- package/scripts/ui-design-judge/design-execution-summary.mjs +0 -81
- package/scripts/ui-design-judge/git-input.mjs +0 -134
- package/scripts/ui-design-judge/prompting.mjs +0 -52
- package/scripts/ui-design-judge/providers.mjs +0 -102
- package/scripts/ui-design-judge/reporting.mjs +0 -183
- package/scripts/ui-design-judge/rubric-calibration.mjs +0 -214
- package/scripts/ui-design-judge/rubric-goldset.json +0 -188
- package/scripts/ui-design-judge.mjs +0 -319
- package/scripts/ui-rubric-calibration.mjs +0 -35
- package/scripts/validate/config.mjs +0 -519
- package/scripts/validate/coverage-checks.mjs +0 -446
- package/scripts/validate/file-structure.mjs +0 -162
- package/scripts/validate/markdown-content.mjs +0 -109
- package/scripts/validate/project-metadata.mjs +0 -166
- package/scripts/validate.mjs +0 -338
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Typography and palette anti-repeat audit.
|
|
5
|
-
*
|
|
6
|
-
* Scans CSS-like files for font-family declarations and color values, then
|
|
7
|
-
*
|
|
8
|
-
* DEPRECATED: This audit was built for the legacy design-intent.json system
|
|
9
|
-
* and its machine-readable antiRepeatLedger. In the 2026 Context Ops Paradigm,
|
|
10
|
-
* anti-repeat checks are handled by the LLM reading docs/DESIGN.md's
|
|
11
|
-
* "Previous Directions" blocklist. This audit now unconditionally skips.
|
|
12
|
-
* - Typography matches are EXACT family-name matches and are always
|
|
13
|
-
* blocking (kind: typography.previously-shipped-family,
|
|
14
|
-
* diagnosticCode: BOUNDARY_TYPOGRAPHY_LEDGER_VIOLATION).
|
|
15
|
-
* - Palette matches are HEURISTIC. OKLCH-to-OKLCH distance is perceptually
|
|
16
|
-
* uniform (deltaE < threshold => match). Hex-to-hex matches are exact
|
|
17
|
-
* normalized equality. Cross-type matches (hex declared in CSS vs OKLCH
|
|
18
|
-
* in the ledger, or vice versa) are NOT performed; reporting cross-type
|
|
19
|
-
* would require a color-space conversion that is its own correctness
|
|
20
|
-
* surface (tracked in docs/deep-analysis-and-roadmap-backlog.md).
|
|
21
|
-
* - Palette findings BLOCK by default with kind:
|
|
22
|
-
* palette.previously-shipped-color and diagnosticCode:
|
|
23
|
-
* BOUNDARY_PALETTE_LEDGER_VIOLATION. Pass
|
|
24
|
-
* `treatPaletteAsAdvisory: true` (or `--palette-advisory` on the CLI)
|
|
25
|
-
* to opt a project into advisory-only palette reporting; severity drops
|
|
26
|
-
* to "advisory" and the diagnostic code becomes
|
|
27
|
-
* BOUNDARY_PALETTE_LEDGER_ADVISORY. Use the advisory mode only when a
|
|
28
|
-
* project knowingly accepts the false-positive risk of OKLCH distance
|
|
29
|
-
* matching at its chosen threshold.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
33
|
-
import { join, relative } from 'node:path';
|
|
34
|
-
|
|
35
|
-
import {
|
|
36
|
-
collectScannableFilePaths,
|
|
37
|
-
lineNumberFromIndex,
|
|
38
|
-
} from './typography-palette-anti-repeat/file-scanner.mjs';
|
|
39
|
-
import {
|
|
40
|
-
extractFontFamiliesFromText,
|
|
41
|
-
extractLedgerTypographyFamilies,
|
|
42
|
-
} from './typography-palette-anti-repeat/typography-utils.mjs';
|
|
43
|
-
import {
|
|
44
|
-
extractColorOccurrencesFromText,
|
|
45
|
-
extractLedgerColors,
|
|
46
|
-
oklchPerceptualDistance,
|
|
47
|
-
} from './typography-palette-anti-repeat/color-utils.mjs';
|
|
48
|
-
|
|
49
|
-
const DEFAULT_OKLCH_DISTANCE_THRESHOLD = 0.04;
|
|
50
|
-
|
|
51
|
-
function findTypographyViolationsForFile({ relativeFilePath, sourceText, ledgerFamilies }) {
|
|
52
|
-
const violations = [];
|
|
53
|
-
const fontFamilyOccurrences = extractFontFamiliesFromText(sourceText);
|
|
54
|
-
for (const familyOccurrence of fontFamilyOccurrences) {
|
|
55
|
-
const ledgerEntry = ledgerFamilies.get(familyOccurrence.family);
|
|
56
|
-
if (!ledgerEntry) {
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
violations.push({
|
|
60
|
-
file: relativeFilePath,
|
|
61
|
-
line: lineNumberFromIndex(sourceText, familyOccurrence.index),
|
|
62
|
-
kind: 'typography.previously-shipped-family',
|
|
63
|
-
severity: 'blocking',
|
|
64
|
-
diagnosticCode: 'BOUNDARY_TYPOGRAPHY_LEDGER_VIOLATION',
|
|
65
|
-
detail: `CSS declares font-family "${familyOccurrence.family}" which appears in researchDossier.metadata.antiRepeatLedger.previousTypographyChoices ("${ledgerEntry.summary}"). Either escape the previously-shipped trio, or set derivedTokenLogic.tokenContinuityClassification.typography to continuity-retained with explicit rationale.`,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
return violations;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function buildHexAdvisory({ relativeFilePath, sourceText, colorOccurrence, ledgerColor, paletteSeverity, paletteDiagnosticCode }) {
|
|
72
|
-
return {
|
|
73
|
-
file: relativeFilePath,
|
|
74
|
-
line: lineNumberFromIndex(sourceText, colorOccurrence.index),
|
|
75
|
-
kind: 'palette.previously-shipped-color',
|
|
76
|
-
severity: paletteSeverity,
|
|
77
|
-
diagnosticCode: paletteDiagnosticCode,
|
|
78
|
-
detail: `CSS hex "${colorOccurrence.raw}" matches a hex color in researchDossier.metadata.antiRepeatLedger.previousPalettes ("${ledgerColor.sourceEntry.summary}"). Either escape the previously-shipped palette or set derivedTokenLogic.tokenContinuityClassification.palette to continuity-retained with explicit rationale.`,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function buildOklchAdvisory({ relativeFilePath, sourceText, colorOccurrence, ledgerColor, perceptualDistance, oklchDistanceThreshold, paletteSeverity, paletteDiagnosticCode }) {
|
|
83
|
-
return {
|
|
84
|
-
file: relativeFilePath,
|
|
85
|
-
line: lineNumberFromIndex(sourceText, colorOccurrence.index),
|
|
86
|
-
kind: 'palette.previously-shipped-color',
|
|
87
|
-
severity: paletteSeverity,
|
|
88
|
-
diagnosticCode: paletteDiagnosticCode,
|
|
89
|
-
detail: `CSS OKLCH "${colorOccurrence.raw}" is within ${perceptualDistance.toFixed(4)} of an OKLCH color in researchDossier.metadata.antiRepeatLedger.previousPalettes ("${ledgerColor.sourceEntry.summary}") (threshold ${oklchDistanceThreshold}). Heuristic match on perceptually-uniform OKLCH distance; either escape the previously-shipped palette, raise the threshold via --threshold, or set derivedTokenLogic.tokenContinuityClassification.palette to continuity-retained with explicit rationale.`,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function findPaletteFindingsForFile({ relativeFilePath, sourceText, ledgerColors, oklchDistanceThreshold, paletteSeverity, paletteDiagnosticCode }) {
|
|
94
|
-
const findings = [];
|
|
95
|
-
const colorOccurrences = extractColorOccurrencesFromText(sourceText);
|
|
96
|
-
for (const colorOccurrence of colorOccurrences) {
|
|
97
|
-
for (const ledgerColor of ledgerColors) {
|
|
98
|
-
if (colorOccurrence.kind === 'hex' && ledgerColor.kind === 'hex') {
|
|
99
|
-
if (
|
|
100
|
-
colorOccurrence.normalized
|
|
101
|
-
&& ledgerColor.normalized
|
|
102
|
-
&& colorOccurrence.normalized === ledgerColor.normalized
|
|
103
|
-
) {
|
|
104
|
-
findings.push(buildHexAdvisory({
|
|
105
|
-
relativeFilePath, sourceText, colorOccurrence, ledgerColor,
|
|
106
|
-
paletteSeverity, paletteDiagnosticCode,
|
|
107
|
-
}));
|
|
108
|
-
}
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
if (colorOccurrence.kind === 'oklch' && ledgerColor.kind === 'oklch' && colorOccurrence.oklch && ledgerColor.oklch) {
|
|
112
|
-
const perceptualDistance = oklchPerceptualDistance(colorOccurrence.oklch, ledgerColor.oklch);
|
|
113
|
-
if (perceptualDistance <= oklchDistanceThreshold) {
|
|
114
|
-
findings.push(buildOklchAdvisory({
|
|
115
|
-
relativeFilePath, sourceText, colorOccurrence, ledgerColor, perceptualDistance, oklchDistanceThreshold,
|
|
116
|
-
paletteSeverity, paletteDiagnosticCode,
|
|
117
|
-
}));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
// Cross-type (hex declared vs OKLCH ledger or vice versa) is intentionally
|
|
121
|
-
// skipped here; reporting cross-type would require a color-space conversion
|
|
122
|
-
// pass that is its own correctness surface. Tracked in
|
|
123
|
-
// docs/deep-analysis-and-roadmap-backlog.md.
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return findings;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function loadDesignIntentContract() {
|
|
130
|
-
return { contract: null, reason: 'design-intent-deprecated-use-design-md-blocklist' };
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function buildSkippedReport(reportShell, reason) {
|
|
134
|
-
return {
|
|
135
|
-
...reportShell,
|
|
136
|
-
passed: true,
|
|
137
|
-
skipped: true,
|
|
138
|
-
reason,
|
|
139
|
-
filesScanned: 0,
|
|
140
|
-
typographyViolationCount: 0,
|
|
141
|
-
paletteFindingCount: 0,
|
|
142
|
-
typographyViolations: [],
|
|
143
|
-
paletteFindings: [],
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Runs the typography and palette anti-repeat audit.
|
|
149
|
-
*
|
|
150
|
-
* @param {object} [auditOptions]
|
|
151
|
-
* @param {string} [auditOptions.repositoryRootPath]
|
|
152
|
-
* @param {string[]} [auditOptions.scanRoots]
|
|
153
|
-
* @param {string} [auditOptions.designIntentRelativePath]
|
|
154
|
-
* @param {number} [auditOptions.oklchDistanceThreshold]
|
|
155
|
-
* @param {boolean} [auditOptions.treatPaletteAsAdvisory]
|
|
156
|
-
*/
|
|
157
|
-
export function runTypographyPaletteAntiRepeatAudit(auditOptions = {}) {
|
|
158
|
-
const repositoryRootPath = auditOptions.repositoryRootPath || process.cwd();
|
|
159
|
-
const scanRoots = Array.isArray(auditOptions.scanRoots) && auditOptions.scanRoots.length > 0
|
|
160
|
-
? auditOptions.scanRoots
|
|
161
|
-
: ['.'];
|
|
162
|
-
const designIntentRelativePath = auditOptions.designIntentRelativePath || 'docs/design-intent.json';
|
|
163
|
-
const oklchDistanceThreshold = typeof auditOptions.oklchDistanceThreshold === 'number'
|
|
164
|
-
? auditOptions.oklchDistanceThreshold
|
|
165
|
-
: DEFAULT_OKLCH_DISTANCE_THRESHOLD;
|
|
166
|
-
const treatPaletteAsAdvisory = auditOptions.treatPaletteAsAdvisory === true;
|
|
167
|
-
const paletteSeverity = treatPaletteAsAdvisory ? 'advisory' : 'blocking';
|
|
168
|
-
const paletteDiagnosticCode = treatPaletteAsAdvisory
|
|
169
|
-
? 'BOUNDARY_PALETTE_LEDGER_ADVISORY'
|
|
170
|
-
: 'BOUNDARY_PALETTE_LEDGER_VIOLATION';
|
|
171
|
-
|
|
172
|
-
const reportShell = {
|
|
173
|
-
auditName: 'audit-typography-palette-anti-repeat',
|
|
174
|
-
reportVersion: '2.0.0',
|
|
175
|
-
generatedAt: new Date().toISOString(),
|
|
176
|
-
designIntentRelativePath,
|
|
177
|
-
paletteSeverity,
|
|
178
|
-
paletteDiagnosticCode,
|
|
179
|
-
oklchDistanceThreshold,
|
|
180
|
-
scope: {
|
|
181
|
-
typographyMatching: 'exact-family-name-after-normalization',
|
|
182
|
-
paletteHexMatching: 'exact-hex-after-7-digit-normalization',
|
|
183
|
-
paletteOklchMatching: 'l*c*h-distance-under-threshold',
|
|
184
|
-
paletteCrossTypeMatching: 'not-supported-color-conversion-out-of-scope',
|
|
185
|
-
paletteCrossTypeMatchingTrackedIn: 'docs/deep-analysis-and-roadmap-backlog.md',
|
|
186
|
-
},
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
const designIntentLoad = loadDesignIntentContract();
|
|
190
|
-
if (!designIntentLoad.contract) {
|
|
191
|
-
return buildSkippedReport(reportShell, designIntentLoad.reason);
|
|
192
|
-
}
|
|
193
|
-
if (!antiRepeatLedger || typeof antiRepeatLedger !== 'object') {
|
|
194
|
-
return buildSkippedReport(reportShell, 'anti-repeat-ledger-absent');
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const ledgerFamilies = extractLedgerTypographyFamilies(antiRepeatLedger);
|
|
198
|
-
const ledgerColors = extractLedgerColors(antiRepeatLedger);
|
|
199
|
-
const scannableFilePaths = collectScannableFilePaths(repositoryRootPath, scanRoots);
|
|
200
|
-
|
|
201
|
-
/** @type {any[]} */
|
|
202
|
-
const typographyViolations = [];
|
|
203
|
-
/** @type {any[]} */
|
|
204
|
-
const paletteFindings = [];
|
|
205
|
-
|
|
206
|
-
for (const absoluteFilePath of scannableFilePaths) {
|
|
207
|
-
const relativeFilePath = relative(repositoryRootPath, absoluteFilePath).replace(/\\/g, '/');
|
|
208
|
-
let sourceText;
|
|
209
|
-
try {
|
|
210
|
-
sourceText = readFileSync(absoluteFilePath, 'utf8');
|
|
211
|
-
} catch {
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
if (ledgerFamilies.size > 0) {
|
|
215
|
-
typographyViolations.push(...findTypographyViolationsForFile({
|
|
216
|
-
relativeFilePath, sourceText, ledgerFamilies,
|
|
217
|
-
}));
|
|
218
|
-
}
|
|
219
|
-
if (ledgerColors.length > 0) {
|
|
220
|
-
paletteFindings.push(...findPaletteFindingsForFile({
|
|
221
|
-
relativeFilePath, sourceText, ledgerColors, oklchDistanceThreshold,
|
|
222
|
-
paletteSeverity, paletteDiagnosticCode,
|
|
223
|
-
}));
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const blockingViolationCount = typographyViolations.length + (treatPaletteAsAdvisory ? 0 : paletteFindings.length);
|
|
228
|
-
|
|
229
|
-
return {
|
|
230
|
-
...reportShell,
|
|
231
|
-
passed: blockingViolationCount === 0,
|
|
232
|
-
skipped: false,
|
|
233
|
-
filesScanned: scannableFilePaths.length,
|
|
234
|
-
typographyViolationCount: typographyViolations.length,
|
|
235
|
-
paletteFindingCount: paletteFindings.length,
|
|
236
|
-
typographyViolations,
|
|
237
|
-
paletteFindings,
|
|
238
|
-
};
|
|
239
|
-
}
|
package/lib/cli/backup.mjs
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import crypto from 'node:crypto';
|
|
4
|
-
import { pathExists, ensureDirectory } from './utils.mjs';
|
|
5
|
-
import { entryPointFiles, BACKUP_DIR_NAME } from './constants.mjs';
|
|
6
|
-
|
|
7
|
-
const BACKUP_GITIGNORE_ENTRY = `${BACKUP_DIR_NAME}/`;
|
|
8
|
-
const BACKUP_GITIGNORE_COMMENT = '# agentic-senior-core: local backup artifacts';
|
|
9
|
-
const RUNTIME_ARTIFACT_GITIGNORE_ENTRIES = [
|
|
10
|
-
'.agent-context/state/token-saver/',
|
|
11
|
-
'.agent-context/state/token-optimization-report.json',
|
|
12
|
-
];
|
|
13
|
-
const RUNTIME_ARTIFACT_GITIGNORE_COMMENT = '# agentic-senior-core: local runtime artifacts';
|
|
14
|
-
|
|
15
|
-
const GOVERNANCE_GITIGNORE_ENTRIES = [
|
|
16
|
-
'.agent-context/',
|
|
17
|
-
'AGENTS.md',
|
|
18
|
-
'CLAUDE.md',
|
|
19
|
-
'GEMINI.md',
|
|
20
|
-
'mcp.json',
|
|
21
|
-
];
|
|
22
|
-
const GOVERNANCE_GITIGNORE_COMMENT = '# agentic-senior-core: local-only governance files';
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Calculates a SHA-256 hash of a file's contents.
|
|
26
|
-
*/
|
|
27
|
-
async function hashFile(filePath) {
|
|
28
|
-
const fileBuffer = await fs.readFile(filePath);
|
|
29
|
-
const hashSum = crypto.createHash('sha256');
|
|
30
|
-
hashSum.update(fileBuffer);
|
|
31
|
-
return hashSum.digest('hex');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Helper to get all files in a directory recursively.
|
|
36
|
-
*/
|
|
37
|
-
async function getFilesInDirectory(dirPath) {
|
|
38
|
-
const files = [];
|
|
39
|
-
try {
|
|
40
|
-
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
41
|
-
for (const entry of entries) {
|
|
42
|
-
if (entry.name === '.git' || entry.name === 'node_modules' || entry.name === BACKUP_DIR_NAME) {
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
const fullPath = path.join(dirPath, entry.name);
|
|
46
|
-
if (entry.isDirectory()) {
|
|
47
|
-
const nestedFiles = await getFilesInDirectory(fullPath);
|
|
48
|
-
files.push(...nestedFiles);
|
|
49
|
-
} else {
|
|
50
|
-
files.push(fullPath);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
} catch (error) {
|
|
54
|
-
if (error.code !== 'ENOENT') {
|
|
55
|
-
throw error;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return files;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Creates a backup of specific paths in the target directory.
|
|
63
|
-
* Currently backs up: managed entrypoint files and the entire .agent-context directory.
|
|
64
|
-
* @param {string} targetDirectoryPath
|
|
65
|
-
*/
|
|
66
|
-
export async function createBackup(targetDirectoryPath) {
|
|
67
|
-
const startTime = Date.now();
|
|
68
|
-
const backupRoot = path.join(targetDirectoryPath, BACKUP_DIR_NAME);
|
|
69
|
-
const objectsDir = path.join(backupRoot, 'objects');
|
|
70
|
-
|
|
71
|
-
await ensureDirectory(objectsDir);
|
|
72
|
-
|
|
73
|
-
const pathsToTrack = [
|
|
74
|
-
path.join(targetDirectoryPath, '.gitignore'),
|
|
75
|
-
...entryPointFiles.map((entryPointFileName) => path.join(targetDirectoryPath, entryPointFileName)),
|
|
76
|
-
path.join(targetDirectoryPath, '.agent-context'),
|
|
77
|
-
];
|
|
78
|
-
|
|
79
|
-
const resolvedFilesToTrack = [];
|
|
80
|
-
|
|
81
|
-
for (const trackPath of pathsToTrack) {
|
|
82
|
-
try {
|
|
83
|
-
const stats = await fs.stat(trackPath);
|
|
84
|
-
if (stats.isDirectory()) {
|
|
85
|
-
const nested = await getFilesInDirectory(trackPath);
|
|
86
|
-
resolvedFilesToTrack.push(...nested);
|
|
87
|
-
} else if (stats.isFile()) {
|
|
88
|
-
resolvedFilesToTrack.push(trackPath);
|
|
89
|
-
}
|
|
90
|
-
} catch (err) {
|
|
91
|
-
if (err.code !== 'ENOENT') {
|
|
92
|
-
throw err;
|
|
93
|
-
}
|
|
94
|
-
// If it doesn't exist, we track it as missing so that a rollback knows to delete it
|
|
95
|
-
// if it gets created during the run. Wait, tracking everything that doesn't exist
|
|
96
|
-
// is infinite. We should record the paths we intend to write to as "absent" state.
|
|
97
|
-
resolvedFilesToTrack.push(trackPath);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const manifest = {
|
|
102
|
-
timestamp: new Date().toISOString(),
|
|
103
|
-
files: {}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
for (const filePath of resolvedFilesToTrack) {
|
|
107
|
-
const relativePath = path.relative(targetDirectoryPath, filePath);
|
|
108
|
-
// Ignore any backup operations within the backup directory itself
|
|
109
|
-
if (relativePath.startsWith(BACKUP_DIR_NAME)) continue;
|
|
110
|
-
|
|
111
|
-
if (await pathExists(filePath)) {
|
|
112
|
-
// File exists: hash and backup
|
|
113
|
-
const fileHash = await hashFile(filePath);
|
|
114
|
-
const destObjectPath = path.join(objectsDir, fileHash);
|
|
115
|
-
|
|
116
|
-
if (!(await pathExists(destObjectPath))) {
|
|
117
|
-
await fs.copyFile(filePath, destObjectPath);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const stats = await fs.stat(filePath);
|
|
121
|
-
manifest.files[relativePath] = {
|
|
122
|
-
action: 'restore',
|
|
123
|
-
hash: fileHash,
|
|
124
|
-
mtimeMs: stats.mtimeMs
|
|
125
|
-
};
|
|
126
|
-
} else {
|
|
127
|
-
// File did not exist before operation: must be deleted on rollback
|
|
128
|
-
manifest.files[relativePath] = {
|
|
129
|
-
action: 'delete'
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const manifestPath = path.join(backupRoot, 'manifest.json');
|
|
135
|
-
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
136
|
-
|
|
137
|
-
return {
|
|
138
|
-
manifestPath,
|
|
139
|
-
backupRoot,
|
|
140
|
-
durationMs: Date.now() - startTime
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async function ensureGitignoreEntries(targetDirectoryPath, { comment, entries, aliasesByEntry = {} }) {
|
|
145
|
-
const gitignorePath = path.join(targetDirectoryPath, '.gitignore');
|
|
146
|
-
const existingContent = await pathExists(gitignorePath)
|
|
147
|
-
? await fs.readFile(gitignorePath, 'utf8')
|
|
148
|
-
: '';
|
|
149
|
-
const existingLines = existingContent.split(/\r?\n/).map((line) => line.trim());
|
|
150
|
-
const missingEntries = entries.filter((entry) => {
|
|
151
|
-
const equivalentEntries = [entry, ...(aliasesByEntry[entry] || [])];
|
|
152
|
-
return !equivalentEntries.some((equivalentEntry) => existingLines.includes(equivalentEntry));
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
if (missingEntries.length === 0) {
|
|
156
|
-
return {
|
|
157
|
-
status: 'unchanged',
|
|
158
|
-
gitignorePath,
|
|
159
|
-
entries,
|
|
160
|
-
addedEntries: [],
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
let nextContent = existingContent;
|
|
165
|
-
if (nextContent.length > 0 && !nextContent.endsWith('\n')) {
|
|
166
|
-
nextContent += '\n';
|
|
167
|
-
}
|
|
168
|
-
if (nextContent.length > 0 && !nextContent.endsWith('\n\n')) {
|
|
169
|
-
nextContent += '\n';
|
|
170
|
-
}
|
|
171
|
-
nextContent += `${comment}\n${missingEntries.join('\n')}\n`;
|
|
172
|
-
|
|
173
|
-
await fs.writeFile(gitignorePath, nextContent, 'utf8');
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
status: existingContent ? 'updated' : 'created',
|
|
177
|
-
gitignorePath,
|
|
178
|
-
entries,
|
|
179
|
-
addedEntries: missingEntries,
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export async function ensureBackupGitignoreEntry(targetDirectoryPath) {
|
|
184
|
-
const result = await ensureGitignoreEntries(targetDirectoryPath, {
|
|
185
|
-
comment: BACKUP_GITIGNORE_COMMENT,
|
|
186
|
-
entries: [BACKUP_GITIGNORE_ENTRY],
|
|
187
|
-
aliasesByEntry: {
|
|
188
|
-
[BACKUP_GITIGNORE_ENTRY]: [BACKUP_DIR_NAME],
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
return {
|
|
193
|
-
...result,
|
|
194
|
-
entry: BACKUP_GITIGNORE_ENTRY,
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export async function ensureRuntimeArtifactGitignoreEntries(targetDirectoryPath) {
|
|
199
|
-
return ensureGitignoreEntries(targetDirectoryPath, {
|
|
200
|
-
comment: RUNTIME_ARTIFACT_GITIGNORE_COMMENT,
|
|
201
|
-
entries: RUNTIME_ARTIFACT_GITIGNORE_ENTRIES,
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export async function ensureLocalGovernanceGitignoreEntries(targetDirectoryPath) {
|
|
206
|
-
return ensureGitignoreEntries(targetDirectoryPath, {
|
|
207
|
-
comment: GOVERNANCE_GITIGNORE_COMMENT,
|
|
208
|
-
entries: GOVERNANCE_GITIGNORE_ENTRIES,
|
|
209
|
-
});
|
|
210
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* `agentic-senior-core audit:design-anti-repeat`
|
|
5
|
-
*
|
|
6
|
-
* [DEPRECATED in 2026 Context Ops Paradigm]
|
|
7
|
-
* This script is retired because the anti-repeat ledger is now maintained
|
|
8
|
-
* as plain-text inside docs/DESIGN.md. The Adaptive Context AI agent enforces
|
|
9
|
-
* this naturally without needing regex-based JSON compliance theater.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
export async function runDesignAntiRepeatAuditCommand(commandLineArgs = []) {
|
|
13
|
-
if (commandLineArgs.includes('--json')) {
|
|
14
|
-
process.stdout.write(JSON.stringify({
|
|
15
|
-
passed: true,
|
|
16
|
-
skipped: true,
|
|
17
|
-
reason: 'audit-design-anti-repeat is deprecated in Context Ops 2026. Plain text ledgers in DESIGN.md are handled by the agent contextually.',
|
|
18
|
-
targetDirectoryPath: process.cwd(),
|
|
19
|
-
filesScanned: 0,
|
|
20
|
-
typographyViolationCount: 0,
|
|
21
|
-
paletteFindingCount: 0,
|
|
22
|
-
paletteSeverity: 'advisory',
|
|
23
|
-
oklchDistanceThreshold: 0.04,
|
|
24
|
-
typographyViolations: [],
|
|
25
|
-
paletteFindings: []
|
|
26
|
-
}, null, 2) + '\n');
|
|
27
|
-
return 0;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
console.log('===============================================');
|
|
31
|
-
console.log(' audit:design-anti-repeat (DEPRECATED)');
|
|
32
|
-
console.log('===============================================');
|
|
33
|
-
console.log(' Audit skipped: audit-design-anti-repeat is retired in Context Ops 2026.');
|
|
34
|
-
console.log(' Plain text ledgers in docs/DESIGN.md are handled by the agent contextually.');
|
|
35
|
-
console.log(' You can safely remove this check from your CI pipeline.');
|
|
36
|
-
console.log('');
|
|
37
|
-
|
|
38
|
-
return 0;
|
|
39
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { stdin } from 'node:process';
|
|
2
|
-
|
|
3
|
-
import { buildSelectedContextManifest } from '../adaptive-context.mjs';
|
|
4
|
-
|
|
5
|
-
export function parseContextArguments(commandArguments) {
|
|
6
|
-
const parsedOptions = {
|
|
7
|
-
requestId: 'adhoc-request',
|
|
8
|
-
requestText: '',
|
|
9
|
-
contextFiles: [],
|
|
10
|
-
json: false,
|
|
11
|
-
readStdin: false,
|
|
12
|
-
};
|
|
13
|
-
const requestParts = [];
|
|
14
|
-
|
|
15
|
-
for (let argumentIndex = 0; argumentIndex < commandArguments.length; argumentIndex++) {
|
|
16
|
-
const currentArgument = commandArguments[argumentIndex];
|
|
17
|
-
|
|
18
|
-
if (currentArgument === '--json') {
|
|
19
|
-
parsedOptions.json = true;
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (currentArgument === '--stdin') {
|
|
24
|
-
parsedOptions.readStdin = true;
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (currentArgument === '--file') {
|
|
29
|
-
const contextFilePath = commandArguments[argumentIndex + 1];
|
|
30
|
-
if (!contextFilePath || contextFilePath.startsWith('--')) {
|
|
31
|
-
throw new Error('Missing value for --file');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
parsedOptions.contextFiles.push(contextFilePath);
|
|
35
|
-
argumentIndex++;
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (currentArgument === '--files') {
|
|
40
|
-
const contextFileList = commandArguments[argumentIndex + 1];
|
|
41
|
-
if (!contextFileList || contextFileList.startsWith('--')) {
|
|
42
|
-
throw new Error('Missing value for --files');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
parsedOptions.contextFiles.push(
|
|
46
|
-
...contextFileList
|
|
47
|
-
.split(',')
|
|
48
|
-
.map((contextFilePath) => contextFilePath.trim())
|
|
49
|
-
.filter(Boolean)
|
|
50
|
-
);
|
|
51
|
-
argumentIndex++;
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (currentArgument === '--request-id') {
|
|
56
|
-
const requestId = commandArguments[argumentIndex + 1];
|
|
57
|
-
if (!requestId || requestId.startsWith('--')) {
|
|
58
|
-
throw new Error('Missing value for --request-id');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
parsedOptions.requestId = requestId;
|
|
62
|
-
argumentIndex++;
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (currentArgument.startsWith('--')) {
|
|
67
|
-
throw new Error(`Unknown option: ${currentArgument}`);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
requestParts.push(currentArgument);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
parsedOptions.requestText = requestParts.join(' ').trim();
|
|
74
|
-
return parsedOptions;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function readRequestFromStdin() {
|
|
78
|
-
return new Promise((resolve, reject) => {
|
|
79
|
-
let requestText = '';
|
|
80
|
-
|
|
81
|
-
stdin.setEncoding('utf8');
|
|
82
|
-
stdin.on('data', (chunk) => {
|
|
83
|
-
requestText += chunk;
|
|
84
|
-
});
|
|
85
|
-
stdin.on('error', reject);
|
|
86
|
-
stdin.on('end', () => {
|
|
87
|
-
resolve(requestText.trim());
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function formatList(label, values) {
|
|
93
|
-
if (values.length === 0) {
|
|
94
|
-
return [`${label}: none`];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return [
|
|
98
|
-
`${label}:`,
|
|
99
|
-
...values.map((value) => `- ${value}`),
|
|
100
|
-
];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function formatManifestText(manifest) {
|
|
104
|
-
return [
|
|
105
|
-
'Adaptive Context',
|
|
106
|
-
`requestId: ${manifest.requestId}`,
|
|
107
|
-
`labels: ${manifest.labels.length > 0 ? manifest.labels.join(', ') : 'none'}`,
|
|
108
|
-
`uncertainty: ${manifest.uncertainty}`,
|
|
109
|
-
`budget: ${manifest.budget.status} (${manifest.budget.selectedRuleCount}/${manifest.budget.maxRecommendedRuleCount} recommended rules)`,
|
|
110
|
-
`fallbackRequired: ${manifest.fallbackRequired}`,
|
|
111
|
-
...formatList('contextFiles', manifest.contextFiles),
|
|
112
|
-
...formatList('selectedRules', manifest.selectedRules),
|
|
113
|
-
...formatList('selectedPrompts', manifest.selectedPrompts),
|
|
114
|
-
...formatList('selectedDocs', manifest.selectedDocs),
|
|
115
|
-
].join('\n');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export async function runContextCommand(commandArguments) {
|
|
119
|
-
const contextOptions = parseContextArguments(commandArguments);
|
|
120
|
-
const requestText = contextOptions.readStdin
|
|
121
|
-
? await readRequestFromStdin()
|
|
122
|
-
: contextOptions.requestText;
|
|
123
|
-
|
|
124
|
-
if (!requestText) {
|
|
125
|
-
throw new Error('Context request text is required. Pass text as arguments or use --stdin.');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const manifest = buildSelectedContextManifest({
|
|
129
|
-
contextFiles: contextOptions.contextFiles,
|
|
130
|
-
requestId: contextOptions.requestId,
|
|
131
|
-
requestText,
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
if (contextOptions.json) {
|
|
135
|
-
console.log(JSON.stringify(manifest, null, 2));
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
console.log(formatManifestText(manifest));
|
|
140
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
function normalizeContextLine(rawText) {
|
|
6
|
-
return String(rawText || '')
|
|
7
|
-
.replace(/\s+/g, ' ')
|
|
8
|
-
.trim();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async function readTextIfExists(filePath) {
|
|
12
|
-
try {
|
|
13
|
-
return await fs.readFile(filePath, 'utf8');
|
|
14
|
-
} catch {
|
|
15
|
-
return '';
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function extractMarkdownContext(rawMarkdown) {
|
|
20
|
-
return String(rawMarkdown || '')
|
|
21
|
-
.split(/\r?\n/)
|
|
22
|
-
.map((line) => normalizeContextLine(line.replace(/^#+\s*/, '')))
|
|
23
|
-
.filter((line) => line && !line.startsWith('---') && !line.startsWith('```'))
|
|
24
|
-
.slice(0, 3)
|
|
25
|
-
.join(' ');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export async function inferExistingProjectDescriptionHint(targetDirectoryPath) {
|
|
29
|
-
const evidence = [];
|
|
30
|
-
const packageJsonContent = await readTextIfExists(path.join(targetDirectoryPath, 'package.json'));
|
|
31
|
-
|
|
32
|
-
if (packageJsonContent) {
|
|
33
|
-
try {
|
|
34
|
-
const packageManifest = JSON.parse(packageJsonContent);
|
|
35
|
-
const packageSummary = [
|
|
36
|
-
normalizeContextLine(packageManifest.name),
|
|
37
|
-
normalizeContextLine(packageManifest.description),
|
|
38
|
-
].filter(Boolean).join(': ');
|
|
39
|
-
|
|
40
|
-
if (packageSummary) {
|
|
41
|
-
evidence.push(`package.json: ${packageSummary}`);
|
|
42
|
-
}
|
|
43
|
-
} catch {
|
|
44
|
-
// Invalid package metadata should not block init; other files can still provide context.
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
for (const relativeDocPath of ['docs/project-brief.md', 'docs/README.md', 'README.md']) {
|
|
49
|
-
const docContext = extractMarkdownContext(
|
|
50
|
-
await readTextIfExists(path.join(targetDirectoryPath, relativeDocPath))
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
if (docContext) {
|
|
54
|
-
evidence.push(`${relativeDocPath}: ${docContext}`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return evidence.slice(0, 3).join(' | ');
|
|
59
|
-
}
|
|
60
|
-
|