devworkspace 0.2.1 → 0.2.2
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/CHANGELOG.md +24 -0
- package/README.md +4 -3
- package/dist/agents/claude/content.js +3 -2
- package/dist/agents/claude/content.js.map +1 -1
- package/dist/cli/args.d.ts +16 -0
- package/dist/cli/args.js +5 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/help.js +30 -7
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/render.d.ts +7 -1
- package/dist/cli/render.js +64 -11
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/run.js +47 -8
- package/dist/cli/run.js.map +1 -1
- package/dist/config/schemas.d.ts +5 -0
- package/dist/config/schemas.js +2 -0
- package/dist/config/schemas.js.map +1 -1
- package/dist/discovery/commands.js +17 -3
- package/dist/discovery/commands.js.map +1 -1
- package/dist/discovery/detect.d.ts +6 -0
- package/dist/discovery/detect.js +12 -6
- package/dist/discovery/detect.js.map +1 -1
- package/dist/discovery/docs.d.ts +10 -0
- package/dist/discovery/docs.js +52 -0
- package/dist/discovery/docs.js.map +1 -0
- package/dist/discovery/entrypoints.d.ts +20 -0
- package/dist/discovery/entrypoints.js +67 -0
- package/dist/discovery/entrypoints.js.map +1 -0
- package/dist/knowledge/facts.d.ts +59 -2
- package/dist/knowledge/facts.js +115 -17
- package/dist/knowledge/facts.js.map +1 -1
- package/dist/prompts/onboarding.js +6 -3
- package/dist/prompts/onboarding.js.map +1 -1
- package/dist/services/analysis.js +6 -0
- package/dist/services/analysis.js.map +1 -1
- package/dist/services/doctor.js +14 -3
- package/dist/services/doctor.js.map +1 -1
- package/dist/services/knowledge.d.ts +17 -0
- package/dist/services/knowledge.js +28 -2
- package/dist/services/knowledge.js.map +1 -1
- package/dist/services/refresh.js +5 -5
- package/dist/services/refresh.js.map +1 -1
- package/dist/services/status.d.ts +11 -2
- package/dist/services/status.js +11 -9
- package/dist/services/status.js.map +1 -1
- package/dist/services/tasks.d.ts +2 -0
- package/dist/services/tasks.js +20 -12
- package/dist/services/tasks.js.map +1 -1
- package/dist/services/verify.d.ts +47 -0
- package/dist/services/verify.js +172 -0
- package/dist/services/verify.js.map +1 -0
- package/dist/tasks/routing.js +8 -3
- package/dist/tasks/routing.js.map +1 -1
- package/dist/tasks/task.d.ts +49 -5
- package/dist/tasks/task.js +68 -11
- package/dist/tasks/task.js.map +1 -1
- package/dist/verification/safety.d.ts +38 -0
- package/dist/verification/safety.js +120 -0
- package/dist/verification/safety.js.map +1 -0
- package/dist/verification/scope.d.ts +19 -0
- package/dist/verification/scope.js +119 -0
- package/dist/verification/scope.js.map +1 -0
- package/docs/knowledge.md +2 -0
- package/docs/testing.md +25 -2
- package/package.json +1 -1
package/dist/config/schemas.js
CHANGED
|
@@ -71,6 +71,8 @@ export function validateCommands(v, file = 'commands.json') {
|
|
|
71
71
|
ec.at_('command').str(eo.command, { max: 500 });
|
|
72
72
|
ec.at_('required').oneOf(eo.required, REQUIRED_LEVELS);
|
|
73
73
|
ec.at_('origin').oneOf(eo.origin, ['repository-script', 'inferred', 'user']);
|
|
74
|
+
if (eo.mutates !== undefined)
|
|
75
|
+
ec.at_('mutates').bool(eo.mutates);
|
|
74
76
|
if (eo.cwd !== undefined) {
|
|
75
77
|
const cwd = ec.at_('cwd').str(eo.cwd, { max: 240 });
|
|
76
78
|
const err = validateRelativePath(cwd);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/config/schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { DevWorkspaceError } from '../errors/index.js';\nimport { validateRelativePath } from '../utils/paths.js';\nimport { Check } from './validate.js';\n\nexport const SCHEMA_VERSION = 1;\n\nexport const CONFIDENCE = ['HIGH', 'MEDIUM', 'LOW'] as const;\nexport const FACT_STATUS = ['VERIFIED', 'DETECTED', 'INFERRED', 'USER_DECISION', 'UNKNOWN', 'STALE'] as const;\nexport const SOURCE_TYPES = ['detector', 'file', 'git', 'user', 'ai'] as const;\nexport const REVIEW_LEVELS = ['off', 'light', 'strict'] as const;\n\nexport type Confidence = (typeof CONFIDENCE)[number];\nexport type FactStatus = (typeof FACT_STATUS)[number];\nexport type SourceType = (typeof SOURCE_TYPES)[number];\nexport type ReviewLevel = (typeof REVIEW_LEVELS)[number];\n\nexport interface ManagedFile {\n path: string;\n mode: 'owned' | 'section';\n agent?: string;\n}\n\nexport interface ProjectConfig {\n schemaVersion: number;\n projectId: string;\n name: string;\n createdAt: string;\n updatedAt: string;\n devworkspaceVersion: string;\n settings: { review: ReviewLevel; maxFiles: number; /** The project intentionally has no tests/lint/build; doctor stops warning about it. */ acknowledgeNoVerification?: boolean };\n managedFiles: ManagedFile[];\n}\n\nexport function validateProject(v: unknown, file = 'project.json'): ProjectConfig {\n const c = new Check(file);\n const o = c.obj(v);\n c.at_('schemaVersion').int(o.schemaVersion, 1);\n c.at_('projectId').str(o.projectId, { min: 8, max: 64 });\n c.at_('name').str(o.name, { min: 1, max: 200 });\n c.at_('createdAt').iso(o.createdAt);\n c.at_('updatedAt').iso(o.updatedAt);\n c.at_('devworkspaceVersion').str(o.devworkspaceVersion, { max: 40 });\n const s = c.at_('settings').obj(o.settings);\n c.at_('settings.review').oneOf(s.review, REVIEW_LEVELS);\n c.at_('settings.maxFiles').int(s.maxFiles, 100);\n if (s.acknowledgeNoVerification !== undefined) c.at_('settings.acknowledgeNoVerification').bool(s.acknowledgeNoVerification);\n const mf = c.at_('managedFiles').arr(o.managedFiles, 200);\n mf.forEach((m, i) => {\n const mc = c.at_(`managedFiles.${i}`);\n const mo = mc.obj(m);\n mc.at_('path').str(mo.path, { max: 240 });\n mc.at_('mode').oneOf(mo.mode, ['owned', 'section'] as const);\n });\n return o as unknown as ProjectConfig;\n}\n\nexport interface Fact {\n id: string;\n key: string;\n value: string;\n source: string;\n sourceType: SourceType;\n sources: string[];\n sourceHashes: Record<string, string>;\n confidence: Confidence;\n status: FactStatus;\n createdAt: string;\n updatedAt: string;\n lastVerifiedAt: string | null;\n staleReason?: string;\n}\n\nexport interface FactsFile {\n schemaVersion: number;\n facts: Fact[];\n}\n\nexport function validateFacts(v: unknown, file = 'facts.json'): FactsFile {\n const c = new Check(file);\n const o = c.obj(v);\n c.at_('schemaVersion').int(o.schemaVersion, 1);\n const facts = c.at_('facts').arr(o.facts, 5000);\n facts.forEach((f, i) => {\n const fc = c.at_(`facts.${i}`);\n const fo = fc.obj(f);\n fc.at_('id').str(fo.id, { max: 64 });\n fc.at_('key').str(fo.key, { min: 1, max: 100 });\n fc.at_('value').str(fo.value, { max: 4000 });\n fc.at_('source').str(fo.source, { max: 500 });\n fc.at_('sourceType').oneOf(fo.sourceType, SOURCE_TYPES);\n fc.at_('sources').strArr(fo.sources, 100);\n fc.at_('sourceHashes').obj(fo.sourceHashes);\n fc.at_('confidence').oneOf(fo.confidence, CONFIDENCE);\n fc.at_('status').oneOf(fo.status, FACT_STATUS);\n fc.at_('createdAt').iso(fo.createdAt);\n fc.at_('updatedAt').iso(fo.updatedAt);\n if (fo.lastVerifiedAt !== null) fc.at_('lastVerifiedAt').iso(fo.lastVerifiedAt);\n });\n return o as unknown as FactsFile;\n}\n\nexport const CHECK_IDS = ['typecheck', 'unit', 'integration', 'e2e', 'lint', 'format', 'build', 'migrations', 'security'] as const;\nexport type CheckId = (typeof CHECK_IDS)[number];\nexport const REQUIRED_LEVELS = ['yes', 'context', 'no'] as const;\n\nexport interface CommandEntry {\n id: CheckId;\n available: boolean;\n command: string | null;\n required: (typeof REQUIRED_LEVELS)[number];\n source: string | null;\n /** 'repository-script' = defined by repo config (untrusted input); 'inferred' = guessed from tooling; 'user' = set by a human. */\n origin: 'repository-script' | 'inferred' | 'user';\n /**\n * Working directory, relative to the project root (POSIX separators). Absent means the project root.\n * Package-specific commands (backend vs frontend) must carry it so they are never run in the wrong place.\n */\n cwd?: string;\n}\n\nexport interface CommandsFile {\n schemaVersion: number;\n checks: CommandEntry[];\n trustNote: string;\n}\n\nexport function validateCommands(v: unknown, file = 'commands.json'): CommandsFile {\n const c = new Check(file);\n const o = c.obj(v);\n c.at_('schemaVersion').int(o.schemaVersion, 1);\n c.at_('trustNote').str(o.trustNote);\n c.at_('checks')\n .arr(o.checks, 100)\n .forEach((e, i) => {\n const ec = c.at_(`checks.${i}`);\n const eo = ec.obj(e);\n ec.at_('id').oneOf(eo.id, CHECK_IDS);\n ec.at_('available').bool(eo.available);\n if (eo.command !== null) ec.at_('command').str(eo.command, { max: 500 });\n ec.at_('required').oneOf(eo.required, REQUIRED_LEVELS);\n ec.at_('origin').oneOf(eo.origin, ['repository-script', 'inferred', 'user'] as const);\n if (eo.cwd !== undefined) {\n const cwd = ec.at_('cwd').str(eo.cwd, { max: 240 });\n const err = validateRelativePath(cwd);\n if (err) throw new DevWorkspaceError('SCHEMA', `Invalid ${file}: checks.${i}.cwd ${err}.`);\n }\n });\n return o as unknown as CommandsFile;\n}\n\nexport interface AnalysisState {\n schemaVersion: number;\n analyzedAt: string;\n refreshedAt: string | null;\n gitHead: string | null;\n fileCount: number;\n truncated: boolean;\n discoveryHash: string;\n}\n\nexport function validateAnalysisState(v: unknown, file = 'analysis.json'): AnalysisState {\n const c = new Check(file);\n const o = c.obj(v);\n c.at_('schemaVersion').int(o.schemaVersion, 1);\n c.at_('analyzedAt').iso(o.analyzedAt);\n c.at_('fileCount').int(o.fileCount);\n c.at_('truncated').bool(o.truncated);\n c.at_('discoveryHash').str(o.discoveryHash, { max: 100 });\n return o as unknown as AnalysisState;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/config/schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { DevWorkspaceError } from '../errors/index.js';\nimport { validateRelativePath } from '../utils/paths.js';\nimport { Check } from './validate.js';\n\nexport const SCHEMA_VERSION = 1;\n\nexport const CONFIDENCE = ['HIGH', 'MEDIUM', 'LOW'] as const;\nexport const FACT_STATUS = ['VERIFIED', 'DETECTED', 'INFERRED', 'USER_DECISION', 'UNKNOWN', 'STALE'] as const;\nexport const SOURCE_TYPES = ['detector', 'file', 'git', 'user', 'ai'] as const;\nexport const REVIEW_LEVELS = ['off', 'light', 'strict'] as const;\n\nexport type Confidence = (typeof CONFIDENCE)[number];\nexport type FactStatus = (typeof FACT_STATUS)[number];\nexport type SourceType = (typeof SOURCE_TYPES)[number];\nexport type ReviewLevel = (typeof REVIEW_LEVELS)[number];\n\nexport interface ManagedFile {\n path: string;\n mode: 'owned' | 'section';\n agent?: string;\n}\n\nexport interface ProjectConfig {\n schemaVersion: number;\n projectId: string;\n name: string;\n createdAt: string;\n updatedAt: string;\n devworkspaceVersion: string;\n settings: { review: ReviewLevel; maxFiles: number; /** The project intentionally has no tests/lint/build; doctor stops warning about it. */ acknowledgeNoVerification?: boolean };\n managedFiles: ManagedFile[];\n}\n\nexport function validateProject(v: unknown, file = 'project.json'): ProjectConfig {\n const c = new Check(file);\n const o = c.obj(v);\n c.at_('schemaVersion').int(o.schemaVersion, 1);\n c.at_('projectId').str(o.projectId, { min: 8, max: 64 });\n c.at_('name').str(o.name, { min: 1, max: 200 });\n c.at_('createdAt').iso(o.createdAt);\n c.at_('updatedAt').iso(o.updatedAt);\n c.at_('devworkspaceVersion').str(o.devworkspaceVersion, { max: 40 });\n const s = c.at_('settings').obj(o.settings);\n c.at_('settings.review').oneOf(s.review, REVIEW_LEVELS);\n c.at_('settings.maxFiles').int(s.maxFiles, 100);\n if (s.acknowledgeNoVerification !== undefined) c.at_('settings.acknowledgeNoVerification').bool(s.acknowledgeNoVerification);\n const mf = c.at_('managedFiles').arr(o.managedFiles, 200);\n mf.forEach((m, i) => {\n const mc = c.at_(`managedFiles.${i}`);\n const mo = mc.obj(m);\n mc.at_('path').str(mo.path, { max: 240 });\n mc.at_('mode').oneOf(mo.mode, ['owned', 'section'] as const);\n });\n return o as unknown as ProjectConfig;\n}\n\nexport interface Fact {\n id: string;\n key: string;\n value: string;\n source: string;\n sourceType: SourceType;\n sources: string[];\n sourceHashes: Record<string, string>;\n confidence: Confidence;\n status: FactStatus;\n createdAt: string;\n updatedAt: string;\n lastVerifiedAt: string | null;\n staleReason?: string;\n}\n\nexport interface FactsFile {\n schemaVersion: number;\n facts: Fact[];\n}\n\nexport function validateFacts(v: unknown, file = 'facts.json'): FactsFile {\n const c = new Check(file);\n const o = c.obj(v);\n c.at_('schemaVersion').int(o.schemaVersion, 1);\n const facts = c.at_('facts').arr(o.facts, 5000);\n facts.forEach((f, i) => {\n const fc = c.at_(`facts.${i}`);\n const fo = fc.obj(f);\n fc.at_('id').str(fo.id, { max: 64 });\n fc.at_('key').str(fo.key, { min: 1, max: 100 });\n fc.at_('value').str(fo.value, { max: 4000 });\n fc.at_('source').str(fo.source, { max: 500 });\n fc.at_('sourceType').oneOf(fo.sourceType, SOURCE_TYPES);\n fc.at_('sources').strArr(fo.sources, 100);\n fc.at_('sourceHashes').obj(fo.sourceHashes);\n fc.at_('confidence').oneOf(fo.confidence, CONFIDENCE);\n fc.at_('status').oneOf(fo.status, FACT_STATUS);\n fc.at_('createdAt').iso(fo.createdAt);\n fc.at_('updatedAt').iso(fo.updatedAt);\n if (fo.lastVerifiedAt !== null) fc.at_('lastVerifiedAt').iso(fo.lastVerifiedAt);\n });\n return o as unknown as FactsFile;\n}\n\nexport const CHECK_IDS = ['typecheck', 'unit', 'integration', 'e2e', 'lint', 'format', 'build', 'migrations', 'security'] as const;\nexport type CheckId = (typeof CHECK_IDS)[number];\nexport const REQUIRED_LEVELS = ['yes', 'context', 'no'] as const;\n\nexport interface CommandEntry {\n id: CheckId;\n available: boolean;\n command: string | null;\n required: (typeof REQUIRED_LEVELS)[number];\n source: string | null;\n /** 'repository-script' = defined by repo config (untrusted input); 'inferred' = guessed from tooling; 'user' = set by a human. */\n origin: 'repository-script' | 'inferred' | 'user';\n /**\n * Working directory, relative to the project root (POSIX separators). Absent means the project root.\n * Package-specific commands (backend vs frontend) must carry it so they are never run in the wrong place.\n */\n cwd?: string;\n /**\n * True when running the command rewrites project files (a formatter, a fixer). Absent means read-only or unknown.\n * DevWorkspace never runs a mutating command on its own.\n */\n mutates?: boolean;\n}\n\nexport interface CommandsFile {\n schemaVersion: number;\n checks: CommandEntry[];\n trustNote: string;\n}\n\nexport function validateCommands(v: unknown, file = 'commands.json'): CommandsFile {\n const c = new Check(file);\n const o = c.obj(v);\n c.at_('schemaVersion').int(o.schemaVersion, 1);\n c.at_('trustNote').str(o.trustNote);\n c.at_('checks')\n .arr(o.checks, 100)\n .forEach((e, i) => {\n const ec = c.at_(`checks.${i}`);\n const eo = ec.obj(e);\n ec.at_('id').oneOf(eo.id, CHECK_IDS);\n ec.at_('available').bool(eo.available);\n if (eo.command !== null) ec.at_('command').str(eo.command, { max: 500 });\n ec.at_('required').oneOf(eo.required, REQUIRED_LEVELS);\n ec.at_('origin').oneOf(eo.origin, ['repository-script', 'inferred', 'user'] as const);\n if (eo.mutates !== undefined) ec.at_('mutates').bool(eo.mutates);\n if (eo.cwd !== undefined) {\n const cwd = ec.at_('cwd').str(eo.cwd, { max: 240 });\n const err = validateRelativePath(cwd);\n if (err) throw new DevWorkspaceError('SCHEMA', `Invalid ${file}: checks.${i}.cwd ${err}.`);\n }\n });\n return o as unknown as CommandsFile;\n}\n\nexport interface AnalysisState {\n schemaVersion: number;\n analyzedAt: string;\n refreshedAt: string | null;\n gitHead: string | null;\n fileCount: number;\n truncated: boolean;\n discoveryHash: string;\n}\n\nexport function validateAnalysisState(v: unknown, file = 'analysis.json'): AnalysisState {\n const c = new Check(file);\n const o = c.obj(v);\n c.at_('schemaVersion').int(o.schemaVersion, 1);\n c.at_('analyzedAt').iso(o.analyzedAt);\n c.at_('fileCount').int(o.fileCount);\n c.at_('truncated').bool(o.truncated);\n c.at_('discoveryHash').str(o.discoveryHash, { max: 100 });\n return o as unknown as AnalysisState;\n}\n"]}
|
|
@@ -12,6 +12,14 @@ const SCRIPT_CANDIDATES = {
|
|
|
12
12
|
migrations: ['db:migrate', 'migrate'],
|
|
13
13
|
security: ['test:security', 'security:test', 'security', 'audit:security'],
|
|
14
14
|
};
|
|
15
|
+
/** Scripts that format in place. They are listed for the user but are never required and never run by DevWorkspace. */
|
|
16
|
+
const FORMATTER_SCRIPTS = ['format', 'fmt', 'format:write', 'prettier:write', 'format:fix'];
|
|
17
|
+
/** True unless the script body clearly only checks. Unknown formatter bodies are treated as modifying files. */
|
|
18
|
+
function writesFiles(body) {
|
|
19
|
+
if (/(^|\s)--(?:check|list-different)\b|(^|\s)-l(\s|$)/.test(body))
|
|
20
|
+
return false;
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
15
23
|
const REQUIRED = {
|
|
16
24
|
typecheck: 'yes',
|
|
17
25
|
unit: 'yes',
|
|
@@ -45,9 +53,9 @@ const byCwd = (a, b) => (a.cwd ?? '').localeCompare(b.cwd ?? '');
|
|
|
45
53
|
*/
|
|
46
54
|
export function buildContract(input) {
|
|
47
55
|
const found = [];
|
|
48
|
-
const add = (id, command, source, origin, cwd) => {
|
|
56
|
+
const add = (id, command, source, origin, cwd, mutates) => {
|
|
49
57
|
if (!found.some((f) => f.id === id && (f.cwd ?? '') === (cwd ?? ''))) {
|
|
50
|
-
found.push({ id, available: true, command, required: REQUIRED[id], source, origin, ...(cwd ? { cwd } : {}) });
|
|
58
|
+
found.push({ id, available: true, command, required: mutates ? 'no' : REQUIRED[id], source, origin, ...(cwd ? { cwd } : {}), ...(mutates !== undefined ? { mutates } : {}) });
|
|
51
59
|
}
|
|
52
60
|
};
|
|
53
61
|
for (const np of input.nodePackages) {
|
|
@@ -56,11 +64,17 @@ export function buildContract(input) {
|
|
|
56
64
|
for (const name of names) {
|
|
57
65
|
const body = np.pkg.scripts[name];
|
|
58
66
|
if (body !== undefined && isRealScript(body)) {
|
|
59
|
-
add(id, scriptCommand(np.packageManager, name), `${manifest}#scripts.${name}`, 'repository-script', np.dir);
|
|
67
|
+
add(id, scriptCommand(np.packageManager, name), `${manifest}#scripts.${name}`, 'repository-script', np.dir, id === 'format' ? /(^|\s)(?:--write|--fix|-w)(\s|$)/.test(body) : undefined);
|
|
60
68
|
break;
|
|
61
69
|
}
|
|
62
70
|
}
|
|
63
71
|
}
|
|
72
|
+
// A package with only an in-place formatter (`format`) still gets a format entry, flagged as modifying files.
|
|
73
|
+
if (!found.some((f) => f.id === 'format' && (f.cwd ?? '') === np.dir)) {
|
|
74
|
+
const name = FORMATTER_SCRIPTS.find((n) => np.pkg.scripts[n] !== undefined && isRealScript(np.pkg.scripts[n]));
|
|
75
|
+
if (name)
|
|
76
|
+
add('format', scriptCommand(np.packageManager, name), `${manifest}#scripts.${name}`, 'repository-script', np.dir, writesFiles(np.pkg.scripts[name]));
|
|
77
|
+
}
|
|
64
78
|
if (np.pkg.scripts.typecheck === undefined && np.hasTsconfig && np.pkg.hasTypes && !found.some((f) => f.id === 'typecheck' && (f.cwd ?? '') === np.dir)) {
|
|
65
79
|
add('typecheck', `${np.packageManager === 'pnpm' ? 'pnpm exec' : 'npx'} tsc --noEmit`, `${np.dir ? `${np.dir}/` : ''}tsconfig.json`, 'inferred', np.dir);
|
|
66
80
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/discovery/commands.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,UAAU,GACrB,6HAA6H;IAC7H,uGAAuG,CAAC;AAmB1G,mGAAmG;AACnG,MAAM,iBAAiB,GAA6B;IAClD,SAAS,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,CAAC;IACrE,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC;IAC/C,WAAW,EAAE,CAAC,kBAAkB,EAAE,UAAU,EAAE,aAAa,CAAC;IAC5D,GAAG,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,aAAa,CAAC;IAC1E,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC;IACtC,MAAM,EAAE,CAAC,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,CAAC;IAC1E,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;IAC3B,UAAU,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC;IACrC,QAAQ,EAAE,CAAC,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,CAAC;CAC3E,CAAC;AAEF,MAAM,QAAQ,GAA8C;IAC1D,SAAS,EAAE,KAAK;IAChB,IAAI,EAAE,KAAK;IACX,WAAW,EAAE,SAAS;IACtB,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,KAAK;IACX,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,KAAK;IACZ,UAAU,EAAE,SAAS;IACrB,QAAQ,EAAE,SAAS;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAc,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;AAEvI,SAAS,aAAa,CAAC,EAAU,EAAE,MAAc;IAC/C,IAAI,MAAM,KAAK,MAAM,IAAI,CAAC,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,MAAM,IAAI,EAAE,KAAK,MAAM,IAAI,EAAE,KAAK,KAAK,CAAC;QAAE,OAAO,GAAG,EAAE,OAAO,CAAC;IAC/G,IAAI,EAAE,KAAK,MAAM;QAAE,OAAO,QAAQ,MAAM,EAAE,CAAC;IAC3C,IAAI,EAAE,KAAK,KAAK;QAAE,OAAO,WAAW,MAAM,EAAE,CAAC;IAC7C,OAAO,GAAG,EAAE,QAAQ,MAAM,EAAE,CAAC;AAC/B,CAAC;AAED,2FAA2F;AAC3F,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,CAAe,EAAE,CAAe,EAAU,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;AAErG;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAoB;IAChD,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,CAAC,EAAW,EAAE,OAAe,EAAE,MAAc,EAAE,MAA8B,EAAE,GAAY,EAAQ,EAAE;QAC/G,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YACrE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAChH,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,cAAc,CAAC;QACpE,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC5D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAClC,IAAI,IAAI,KAAK,SAAS,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7C,GAAG,CAAC,EAAa,EAAE,aAAa,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,EAAE,GAAG,QAAQ,YAAY,IAAI,EAAE,EAAE,mBAAmB,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;oBACvH,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;YACxJ,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,eAAe,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,UAAU,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QAC3J,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,MAAM,EAAE,GAAG,KAAK,CAAC,cAAc,CAAC;QAChC,MAAM,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3F,IAAI,EAAE,CAAC,MAAM,IAAI,WAAW,IAAI,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC;YAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,IAAI,QAAQ,EAAE,UAAU,CAAC,CAAC;QAClH,IAAI,EAAE,CAAC,IAAI;YAAE,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC9D,IAAI,EAAE,CAAC,IAAI;YAAE,GAAG,CAAC,WAAW,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC7D,IAAI,EAAE,CAAC,KAAK;YAAE,GAAG,CAAC,QAAQ,EAAE,iBAAiB,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QACrE,IAAI,EAAE,CAAC,OAAO;YAAE,GAAG,CAAC,YAAY,EAAE,eAAe,EAAE,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QACnD,GAAG,CAAC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QACrD,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACjC,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QACpD,GAAG,CAAC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QACtD,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAC/C,GAAG,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;QACvD,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAuB;IAC/C,MAAM,GAAG,GAAmB,EAAE,CAAC;IAC/B,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3E,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;aAClC,CAAC;YACJ,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YACrD,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QACrH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAYD;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,QAA+B,EAAE,QAAwB,EAAE,OAAgC,EAAE;IACzH,MAAM,IAAI,GAAG,QAAQ,IAAI,EAAE,CAAC;IAC5B,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;IACtE,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,MAAM,GAAG,GAAmB,EAAE,CAAC;IAE/B,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC;QACnF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,MAAM,MAAM,GAAmB,CAAC,GAAG,IAAI,CAAC,CAAC;QACzC,aAAa,IAAI,IAAI,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,KAAK,MAAM,CAAC,IAAI,GAAG;gBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;oBAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,EAAE,CAAC;YACtC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC;YAC3D,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;YACpB,cAAc,IAAI,GAAG,CAAC,MAAM,CAAC;QAC/B,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;aAClD,CAAC;YACJ,kHAAkH;YAClH,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAmB,EAAE,CAAC;YACrK,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC;AACpE,CAAC","sourcesContent":["import type { CheckId, CommandEntry } from '../config/schemas.js';\nimport type { PackageInfo } from './detect.js';\n\nexport const TRUST_NOTE =\n 'Commands marked \"repository-script\" come from files in the repository (e.g. package.json scripts) and are untrusted input. ' +\n 'Inspect what a script does before running it, especially in automation or on unfamiliar repositories.';\n\n/** One Node.js package: the manifest, where it lives, and which package manager its own lockfile says it uses. */\nexport interface NodePackageInput {\n /** Directory relative to the project root, POSIX separators; '' for the root. */\n dir: string;\n pkg: PackageInfo;\n packageManager: string;\n hasTsconfig: boolean;\n}\n\nexport interface ContractInput {\n nodePackages: NodePackageInput[];\n ecosystems: Set<string>;\n has: (rel: string) => boolean;\n pythonEvidence: Record<string, string>;\n files: Set<string>;\n}\n\n/** First match wins, so more specific scripts (test:unit) are preferred over catch-alls (test). */\nconst SCRIPT_CANDIDATES: Record<string, string[]> = {\n typecheck: ['typecheck', 'type-check', 'check-types', 'tsc', 'types'],\n unit: ['test:unit', 'unit', 'test', 'test:run'],\n integration: ['test:integration', 'test:int', 'integration'],\n e2e: ['test:e2e', 'e2e', 'test:playwright', 'test:cypress', 'cypress:run'],\n lint: ['lint', 'eslint', 'lint:check'],\n format: ['format:check', 'prettier:check', 'format-check', 'check:format'],\n build: ['build', 'compile'],\n migrations: ['db:migrate', 'migrate'],\n security: ['test:security', 'security:test', 'security', 'audit:security'],\n};\n\nconst REQUIRED: Record<CheckId, CommandEntry['required']> = {\n typecheck: 'yes',\n unit: 'yes',\n integration: 'context',\n e2e: 'context',\n lint: 'yes',\n format: 'context',\n build: 'yes',\n migrations: 'context',\n security: 'context',\n};\n\nexport const CHECK_ORDER: CheckId[] = ['typecheck', 'unit', 'integration', 'e2e', 'lint', 'format', 'build', 'migrations', 'security'];\n\nfunction scriptCommand(pm: string, script: string): string {\n if (script === 'test' && (pm === 'npm' || pm === 'pnpm' || pm === 'yarn' || pm === 'bun')) return `${pm} test`;\n if (pm === 'yarn') return `yarn ${script}`;\n if (pm === 'bun') return `bun run ${script}`;\n return `${pm} run ${script}`;\n}\n\n/** Placeholder scripts such as npm's default \"no test specified\" do not count as tests. */\nfunction isRealScript(body: string): boolean {\n return !/no test specified/i.test(body) && body.trim() !== '';\n}\n\nconst byCwd = (a: CommandEntry, b: CommandEntry): number => (a.cwd ?? '').localeCompare(b.cwd ?? '');\n\n/**\n * Detected verification commands. Node commands are produced per package and only for scripts that exist in that\n * package's own manifest. Every check that no package provides gets one unavailable entry so the contract always\n * lists all nine checks.\n */\nexport function buildContract(input: ContractInput): CommandEntry[] {\n const found: CommandEntry[] = [];\n const add = (id: CheckId, command: string, source: string, origin: CommandEntry['origin'], cwd?: string): void => {\n if (!found.some((f) => f.id === id && (f.cwd ?? '') === (cwd ?? ''))) {\n found.push({ id, available: true, command, required: REQUIRED[id], source, origin, ...(cwd ? { cwd } : {}) });\n }\n };\n\n for (const np of input.nodePackages) {\n const manifest = np.dir ? `${np.dir}/package.json` : 'package.json';\n for (const [id, names] of Object.entries(SCRIPT_CANDIDATES)) {\n for (const name of names) {\n const body = np.pkg.scripts[name];\n if (body !== undefined && isRealScript(body)) {\n add(id as CheckId, scriptCommand(np.packageManager, name), `${manifest}#scripts.${name}`, 'repository-script', np.dir);\n break;\n }\n }\n }\n if (np.pkg.scripts.typecheck === undefined && np.hasTsconfig && np.pkg.hasTypes && !found.some((f) => f.id === 'typecheck' && (f.cwd ?? '') === np.dir)) {\n add('typecheck', `${np.packageManager === 'pnpm' ? 'pnpm exec' : 'npx'} tsc --noEmit`, `${np.dir ? `${np.dir}/` : ''}tsconfig.json`, 'inferred', np.dir);\n }\n }\n\n if (input.ecosystems.has('python')) {\n const ev = input.pythonEvidence;\n const hasTestsDir = [...input.files].some((f) => /^tests?\\//.test(f) && f.endsWith('.py'));\n if (ev.pytest || hasTestsDir || input.has('pytest.ini')) add('unit', 'pytest', ev.pytest ?? 'tests/', 'inferred');\n if (ev.ruff) add('lint', 'ruff check .', ev.ruff, 'inferred');\n if (ev.mypy) add('typecheck', 'mypy .', ev.mypy, 'inferred');\n if (ev.black) add('format', 'black --check .', ev.black, 'inferred');\n if (ev.alembic) add('migrations', 'alembic check', ev.alembic, 'inferred');\n }\n if (input.ecosystems.has('go')) {\n add('unit', 'go test ./...', 'go.mod', 'inferred');\n add('build', 'go build ./...', 'go.mod', 'inferred');\n add('lint', 'go vet ./...', 'go.mod', 'inferred');\n }\n if (input.ecosystems.has('rust')) {\n add('unit', 'cargo test', 'Cargo.toml', 'inferred');\n add('build', 'cargo build', 'Cargo.toml', 'inferred');\n add('lint', 'cargo clippy', 'Cargo.toml', 'inferred');\n }\n if (input.has('pom.xml')) {\n add('unit', 'mvn test', 'pom.xml', 'inferred');\n add('build', 'mvn package', 'pom.xml', 'inferred');\n }\n if (input.has('build.gradle') || input.has('build.gradle.kts')) {\n add('unit', 'gradle test', 'build.gradle', 'inferred');\n add('build', 'gradle build', 'build.gradle', 'inferred');\n }\n\n return withPlaceholders(found);\n}\n\nfunction withPlaceholders(entries: CommandEntry[]): CommandEntry[] {\n const out: CommandEntry[] = [];\n for (const id of CHECK_ORDER) {\n const mine = entries.filter((e) => e.id === id && e.available).sort(byCwd);\n if (mine.length > 0) out.push(...mine);\n else {\n const unavailable = entries.find((e) => e.id === id);\n out.push(unavailable ?? { id, available: false, command: null, required: 'no', source: null, origin: 'inferred' });\n }\n }\n return out;\n}\n\nexport interface MergeResult {\n checks: CommandEntry[];\n /** Entries kept from the previous contract because a human confirmed them (origin \"user\"). */\n preservedUser: number;\n /** Previously detected entries kept because this analysis found nothing or was cut short. */\n preservedStale: number;\n /** The new detection found no verification commands at all, or the scan was truncated. */\n incomplete: boolean;\n}\n\n/**\n * Combine the previous contract with fresh detection.\n * - Entries confirmed by a person (origin \"user\") are never dropped or overwritten. A user entry without a cwd\n * covers its whole check; one with a cwd covers only that directory, and detection fills in the other packages.\n * - If detection is incomplete, previously available entries survive too, with their original provenance.\n */\nexport function mergeContract(previous: CommandEntry[] | null, detected: CommandEntry[], opts: { truncated?: boolean } = {}): MergeResult {\n const prev = previous ?? [];\n const detectedAvailable = detected.filter((d) => d.available);\n const incomplete = detectedAvailable.length === 0 || !!opts.truncated;\n let preservedUser = 0;\n let preservedStale = 0;\n const out: CommandEntry[] = [];\n\n for (const id of CHECK_ORDER) {\n const user = prev.filter((p) => p.id === id && p.origin === 'user' && p.available);\n const globalUser = user.some((u) => !u.cwd);\n const det = detectedAvailable.filter((d) => d.id === id);\n const chosen: CommandEntry[] = [...user];\n preservedUser += user.length;\n if (!globalUser) {\n for (const d of det) if (!user.some((u) => (u.cwd ?? '') === (d.cwd ?? ''))) chosen.push(d);\n }\n if (chosen.length === 0 && incomplete) {\n const old = prev.filter((p) => p.id === id && p.available);\n chosen.push(...old);\n preservedStale += old.length;\n }\n if (chosen.length > 0) out.push(...chosen.sort(byCwd));\n else {\n // nothing confirmed, nothing detected: list the check as unavailable so the contract always names all nine checks\n const unavailable = detected.find((d) => d.id === id) ?? { id, available: false, command: null, required: 'no' as const, source: null, origin: 'inferred' as const };\n out.push(unavailable);\n }\n }\n return { checks: out, preservedUser, preservedStale, incomplete };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/discovery/commands.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CheckId, CommandEntry } from '../config/schemas.js';\nimport type { PackageInfo } from './detect.js';\n\nexport const TRUST_NOTE =\n 'Commands marked \"repository-script\" come from files in the repository (e.g. package.json scripts) and are untrusted input. ' +\n 'Inspect what a script does before running it, especially in automation or on unfamiliar repositories.';\n\n/** One Node.js package: the manifest, where it lives, and which package manager its own lockfile says it uses. */\nexport interface NodePackageInput {\n /** Directory relative to the project root, POSIX separators; '' for the root. */\n dir: string;\n pkg: PackageInfo;\n packageManager: string;\n hasTsconfig: boolean;\n}\n\nexport interface ContractInput {\n nodePackages: NodePackageInput[];\n ecosystems: Set<string>;\n has: (rel: string) => boolean;\n pythonEvidence: Record<string, string>;\n files: Set<string>;\n}\n\n/** First match wins, so more specific scripts (test:unit) are preferred over catch-alls (test). */\nconst SCRIPT_CANDIDATES: Record<string, string[]> = {\n typecheck: ['typecheck', 'type-check', 'check-types', 'tsc', 'types'],\n unit: ['test:unit', 'unit', 'test', 'test:run'],\n integration: ['test:integration', 'test:int', 'integration'],\n e2e: ['test:e2e', 'e2e', 'test:playwright', 'test:cypress', 'cypress:run'],\n lint: ['lint', 'eslint', 'lint:check'],\n format: ['format:check', 'prettier:check', 'format-check', 'check:format'],\n build: ['build', 'compile'],\n migrations: ['db:migrate', 'migrate'],\n security: ['test:security', 'security:test', 'security', 'audit:security'],\n};\n\n/** Scripts that format in place. They are listed for the user but are never required and never run by DevWorkspace. */\nconst FORMATTER_SCRIPTS = ['format', 'fmt', 'format:write', 'prettier:write', 'format:fix'];\n\n/** True unless the script body clearly only checks. Unknown formatter bodies are treated as modifying files. */\nfunction writesFiles(body: string): boolean {\n if (/(^|\\s)--(?:check|list-different)\\b|(^|\\s)-l(\\s|$)/.test(body)) return false;\n return true;\n}\n\nconst REQUIRED: Record<CheckId, CommandEntry['required']> = {\n typecheck: 'yes',\n unit: 'yes',\n integration: 'context',\n e2e: 'context',\n lint: 'yes',\n format: 'context',\n build: 'yes',\n migrations: 'context',\n security: 'context',\n};\n\nexport const CHECK_ORDER: CheckId[] = ['typecheck', 'unit', 'integration', 'e2e', 'lint', 'format', 'build', 'migrations', 'security'];\n\nfunction scriptCommand(pm: string, script: string): string {\n if (script === 'test' && (pm === 'npm' || pm === 'pnpm' || pm === 'yarn' || pm === 'bun')) return `${pm} test`;\n if (pm === 'yarn') return `yarn ${script}`;\n if (pm === 'bun') return `bun run ${script}`;\n return `${pm} run ${script}`;\n}\n\n/** Placeholder scripts such as npm's default \"no test specified\" do not count as tests. */\nfunction isRealScript(body: string): boolean {\n return !/no test specified/i.test(body) && body.trim() !== '';\n}\n\nconst byCwd = (a: CommandEntry, b: CommandEntry): number => (a.cwd ?? '').localeCompare(b.cwd ?? '');\n\n/**\n * Detected verification commands. Node commands are produced per package and only for scripts that exist in that\n * package's own manifest. Every check that no package provides gets one unavailable entry so the contract always\n * lists all nine checks.\n */\nexport function buildContract(input: ContractInput): CommandEntry[] {\n const found: CommandEntry[] = [];\n const add = (id: CheckId, command: string, source: string, origin: CommandEntry['origin'], cwd?: string, mutates?: boolean): void => {\n if (!found.some((f) => f.id === id && (f.cwd ?? '') === (cwd ?? ''))) {\n found.push({ id, available: true, command, required: mutates ? 'no' : REQUIRED[id], source, origin, ...(cwd ? { cwd } : {}), ...(mutates !== undefined ? { mutates } : {}) });\n }\n };\n\n for (const np of input.nodePackages) {\n const manifest = np.dir ? `${np.dir}/package.json` : 'package.json';\n for (const [id, names] of Object.entries(SCRIPT_CANDIDATES)) {\n for (const name of names) {\n const body = np.pkg.scripts[name];\n if (body !== undefined && isRealScript(body)) {\n add(id as CheckId, scriptCommand(np.packageManager, name), `${manifest}#scripts.${name}`, 'repository-script', np.dir, id === 'format' ? /(^|\\s)(?:--write|--fix|-w)(\\s|$)/.test(body) : undefined);\n break;\n }\n }\n }\n // A package with only an in-place formatter (`format`) still gets a format entry, flagged as modifying files.\n if (!found.some((f) => f.id === 'format' && (f.cwd ?? '') === np.dir)) {\n const name = FORMATTER_SCRIPTS.find((n) => np.pkg.scripts[n] !== undefined && isRealScript(np.pkg.scripts[n]!));\n if (name) add('format', scriptCommand(np.packageManager, name), `${manifest}#scripts.${name}`, 'repository-script', np.dir, writesFiles(np.pkg.scripts[name]!));\n }\n if (np.pkg.scripts.typecheck === undefined && np.hasTsconfig && np.pkg.hasTypes && !found.some((f) => f.id === 'typecheck' && (f.cwd ?? '') === np.dir)) {\n add('typecheck', `${np.packageManager === 'pnpm' ? 'pnpm exec' : 'npx'} tsc --noEmit`, `${np.dir ? `${np.dir}/` : ''}tsconfig.json`, 'inferred', np.dir);\n }\n }\n\n if (input.ecosystems.has('python')) {\n const ev = input.pythonEvidence;\n const hasTestsDir = [...input.files].some((f) => /^tests?\\//.test(f) && f.endsWith('.py'));\n if (ev.pytest || hasTestsDir || input.has('pytest.ini')) add('unit', 'pytest', ev.pytest ?? 'tests/', 'inferred');\n if (ev.ruff) add('lint', 'ruff check .', ev.ruff, 'inferred');\n if (ev.mypy) add('typecheck', 'mypy .', ev.mypy, 'inferred');\n if (ev.black) add('format', 'black --check .', ev.black, 'inferred');\n if (ev.alembic) add('migrations', 'alembic check', ev.alembic, 'inferred');\n }\n if (input.ecosystems.has('go')) {\n add('unit', 'go test ./...', 'go.mod', 'inferred');\n add('build', 'go build ./...', 'go.mod', 'inferred');\n add('lint', 'go vet ./...', 'go.mod', 'inferred');\n }\n if (input.ecosystems.has('rust')) {\n add('unit', 'cargo test', 'Cargo.toml', 'inferred');\n add('build', 'cargo build', 'Cargo.toml', 'inferred');\n add('lint', 'cargo clippy', 'Cargo.toml', 'inferred');\n }\n if (input.has('pom.xml')) {\n add('unit', 'mvn test', 'pom.xml', 'inferred');\n add('build', 'mvn package', 'pom.xml', 'inferred');\n }\n if (input.has('build.gradle') || input.has('build.gradle.kts')) {\n add('unit', 'gradle test', 'build.gradle', 'inferred');\n add('build', 'gradle build', 'build.gradle', 'inferred');\n }\n\n return withPlaceholders(found);\n}\n\nfunction withPlaceholders(entries: CommandEntry[]): CommandEntry[] {\n const out: CommandEntry[] = [];\n for (const id of CHECK_ORDER) {\n const mine = entries.filter((e) => e.id === id && e.available).sort(byCwd);\n if (mine.length > 0) out.push(...mine);\n else {\n const unavailable = entries.find((e) => e.id === id);\n out.push(unavailable ?? { id, available: false, command: null, required: 'no', source: null, origin: 'inferred' });\n }\n }\n return out;\n}\n\nexport interface MergeResult {\n checks: CommandEntry[];\n /** Entries kept from the previous contract because a human confirmed them (origin \"user\"). */\n preservedUser: number;\n /** Previously detected entries kept because this analysis found nothing or was cut short. */\n preservedStale: number;\n /** The new detection found no verification commands at all, or the scan was truncated. */\n incomplete: boolean;\n}\n\n/**\n * Combine the previous contract with fresh detection.\n * - Entries confirmed by a person (origin \"user\") are never dropped or overwritten. A user entry without a cwd\n * covers its whole check; one with a cwd covers only that directory, and detection fills in the other packages.\n * - If detection is incomplete, previously available entries survive too, with their original provenance.\n */\nexport function mergeContract(previous: CommandEntry[] | null, detected: CommandEntry[], opts: { truncated?: boolean } = {}): MergeResult {\n const prev = previous ?? [];\n const detectedAvailable = detected.filter((d) => d.available);\n const incomplete = detectedAvailable.length === 0 || !!opts.truncated;\n let preservedUser = 0;\n let preservedStale = 0;\n const out: CommandEntry[] = [];\n\n for (const id of CHECK_ORDER) {\n const user = prev.filter((p) => p.id === id && p.origin === 'user' && p.available);\n const globalUser = user.some((u) => !u.cwd);\n const det = detectedAvailable.filter((d) => d.id === id);\n const chosen: CommandEntry[] = [...user];\n preservedUser += user.length;\n if (!globalUser) {\n for (const d of det) if (!user.some((u) => (u.cwd ?? '') === (d.cwd ?? ''))) chosen.push(d);\n }\n if (chosen.length === 0 && incomplete) {\n const old = prev.filter((p) => p.id === id && p.available);\n chosen.push(...old);\n preservedStale += old.length;\n }\n if (chosen.length > 0) out.push(...chosen.sort(byCwd));\n else {\n // nothing confirmed, nothing detected: list the check as unavailable so the contract always names all nine checks\n const unavailable = detected.find((d) => d.id === id) ?? { id, available: false, command: null, required: 'no' as const, source: null, origin: 'inferred' as const };\n out.push(unavailable);\n }\n }\n return { checks: out, preservedUser, preservedStale, incomplete };\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ScanResult } from './scan.js';
|
|
2
2
|
import { type NodePackageInput } from './commands.js';
|
|
3
3
|
import type { CommandEntry } from '../config/schemas.js';
|
|
4
|
+
import { type EntryPoint } from './entrypoints.js';
|
|
4
5
|
export interface Detected {
|
|
5
6
|
name: string;
|
|
6
7
|
category: 'framework' | 'test' | 'tool' | 'database' | 'runtime';
|
|
@@ -22,6 +23,9 @@ export interface PackageInfo {
|
|
|
22
23
|
packageManagerField?: string;
|
|
23
24
|
hasTypes: boolean;
|
|
24
25
|
type?: string;
|
|
26
|
+
/** `main` field and `bin` targets, used as evidence for entry points. */
|
|
27
|
+
main?: string;
|
|
28
|
+
bin?: string[];
|
|
25
29
|
}
|
|
26
30
|
export interface DiscoveryReport {
|
|
27
31
|
schemaVersion: 1;
|
|
@@ -62,6 +66,8 @@ export interface DiscoveryReport {
|
|
|
62
66
|
/** Names of credential-like files that exist. Their content is never read. */
|
|
63
67
|
sensitiveFilesPresent: string[];
|
|
64
68
|
entryHints: string[];
|
|
69
|
+
/** Entry points a package itself declares (start-like scripts, `main`, `bin`), with the evidence for each. */
|
|
70
|
+
entryPoints: EntryPoint[];
|
|
65
71
|
warnings: string[];
|
|
66
72
|
}
|
|
67
73
|
export declare function isAuxPath(rel: string): boolean;
|
package/dist/discovery/detect.js
CHANGED
|
@@ -2,6 +2,8 @@ import path from 'node:path';
|
|
|
2
2
|
import { safeReadText } from '../security/files.js';
|
|
3
3
|
import { isSensitiveFile } from '../security/files.js';
|
|
4
4
|
import { buildContract } from './commands.js';
|
|
5
|
+
import { detectDocs, MAX_DOCS } from './docs.js';
|
|
6
|
+
import { discoverEntryPoints } from './entrypoints.js';
|
|
5
7
|
const EXT_LANG = {
|
|
6
8
|
'.ts': 'TypeScript',
|
|
7
9
|
'.tsx': 'TypeScript',
|
|
@@ -145,6 +147,8 @@ export async function readPackageJson(root, rel) {
|
|
|
145
147
|
packageManagerField: typeof j.packageManager === 'string' ? j.packageManager : undefined,
|
|
146
148
|
hasTypes: 'typescript' in deps,
|
|
147
149
|
type: typeof j.type === 'string' ? j.type : undefined,
|
|
150
|
+
main: typeof j.main === 'string' ? j.main : undefined,
|
|
151
|
+
bin: typeof j.bin === 'string' ? [j.bin] : Object.values(strMap(j.bin)),
|
|
148
152
|
};
|
|
149
153
|
}
|
|
150
154
|
function nodeFrameworks(pkg) {
|
|
@@ -417,12 +421,11 @@ export async function detectProject(input) {
|
|
|
417
421
|
.filter(has)
|
|
418
422
|
.concat([...files].filter((f) => /^(k8s|kubernetes|deploy|infra|terraform)\//.test(f)).slice(0, 5))
|
|
419
423
|
.sort();
|
|
420
|
-
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
].sort();
|
|
424
|
+
// Instruction files only: CLAUDE.md, settings and each skill's SKILL.md. A skill's reference documents are tool-managed noise.
|
|
425
|
+
const claudeFiles = [...files].filter((f) => /^\.claude\/(?:[^/]+\.(?:md|json)|skills\/[^/]+\/SKILL\.md)$/.test(f)).slice(0, 20);
|
|
426
|
+
const aiInstructions = [...new Set([...AI_FILES.filter(has), ...claudeFiles])].sort();
|
|
427
|
+
const { docs, omitted: docsOmitted } = detectDocs(files, nodePkgs.map((p) => p.dir));
|
|
428
|
+
const entryPoints = discoverEntryPoints(nodePkgs, files);
|
|
426
429
|
const entryHints = [];
|
|
427
430
|
for (const cand of ['src/index.ts', 'src/main.ts', 'src/app.ts', 'src/server.ts', 'index.js', 'server.js', 'app.js', 'main.py', 'app/main.py', 'main.go', 'cmd', 'src/main.rs', 'manage.py', 'src/App.tsx', 'app/layout.tsx']) {
|
|
428
431
|
if (has(cand) || [...files].some((f) => f.startsWith(cand + '/')))
|
|
@@ -442,6 +445,8 @@ export async function detectProject(input) {
|
|
|
442
445
|
if (ecosystems.size > 0 && !commands.some((c) => c.available)) {
|
|
443
446
|
warnings.push('No verification commands (tests, lint, typecheck, build) were found in the package manifests.');
|
|
444
447
|
}
|
|
448
|
+
if (docsOmitted > 0)
|
|
449
|
+
warnings.push(`${docsOmitted} more documentation file(s) were found than are listed (limit ${MAX_DOCS}).`);
|
|
445
450
|
if (scan.truncated)
|
|
446
451
|
warnings.push('Scan hit its file or depth limit; discovery is partial.');
|
|
447
452
|
if (scan.sensitiveFiles.length > 0)
|
|
@@ -474,6 +479,7 @@ export async function detectProject(input) {
|
|
|
474
479
|
docs,
|
|
475
480
|
sensitiveFilesPresent: scan.sensitiveFiles.filter((f) => isSensitiveFile(f)),
|
|
476
481
|
entryHints,
|
|
482
|
+
entryPoints,
|
|
477
483
|
warnings,
|
|
478
484
|
};
|
|
479
485
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/discovery/detect.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { safeReadText } from '../security/files.js';\nimport { isSensitiveFile } from '../security/files.js';\nimport type { ScanResult } from './scan.js';\nimport { buildContract, type NodePackageInput } from './commands.js';\nimport type { CommandEntry } from '../config/schemas.js';\n\nexport interface Detected {\n name: string;\n category: 'framework' | 'test' | 'tool' | 'database' | 'runtime';\n evidence: string;\n}\n\nexport interface SubProject {\n path: string;\n name: string;\n ecosystem: string;\n frameworks: string[];\n packageManager?: string;\n}\n\nexport interface PackageInfo {\n rel: string;\n name?: string;\n scripts: Record<string, string>;\n deps: Record<string, string>;\n workspaces: string[];\n packageManagerField?: string;\n hasTypes: boolean;\n type?: string;\n}\n\nexport interface DiscoveryReport {\n schemaVersion: 1;\n project: { name: string };\n scan: {\n fileCount: number;\n dirCount: number;\n truncated: boolean;\n skippedSymlinks: number;\n ignoredEntries: number;\n };\n languages: { name: string; files: number }[];\n topDirs: { name: string; files: number }[];\n ecosystems: string[];\n packageManager: string | null;\n frameworks: Detected[];\n monorepo: { tool: string | null; packages: SubProject[] };\n commands: CommandEntry[];\n /** Recognised package manifests (project-relative). Used as evidence for derived facts. */\n manifests: string[];\n testConfigs: string[];\n ci: string[];\n docker: string[];\n deployment: string[];\n aiInstructions: string[];\n docs: string[];\n /** Names of credential-like files that exist. Their content is never read. */\n sensitiveFilesPresent: string[];\n entryHints: string[];\n warnings: string[];\n}\n\nconst EXT_LANG: Record<string, string> = {\n '.ts': 'TypeScript',\n '.tsx': 'TypeScript',\n '.mts': 'TypeScript',\n '.cts': 'TypeScript',\n '.js': 'JavaScript',\n '.jsx': 'JavaScript',\n '.mjs': 'JavaScript',\n '.cjs': 'JavaScript',\n '.py': 'Python',\n '.go': 'Go',\n '.rs': 'Rust',\n '.java': 'Java',\n '.kt': 'Kotlin',\n '.php': 'PHP',\n '.rb': 'Ruby',\n '.cs': 'C#',\n '.swift': 'Swift',\n '.c': 'C',\n '.h': 'C',\n '.cpp': 'C++',\n '.cc': 'C++',\n '.hpp': 'C++',\n '.vue': 'Vue',\n '.svelte': 'Svelte',\n '.sql': 'SQL',\n};\n\nconst NODE_DEP_MAP: Record<string, { name: string; category: Detected['category'] }> = {\n express: { name: 'Express', category: 'framework' },\n fastify: { name: 'Fastify', category: 'framework' },\n koa: { name: 'Koa', category: 'framework' },\n hono: { name: 'Hono', category: 'framework' },\n '@nestjs/core': { name: 'NestJS', category: 'framework' },\n next: { name: 'Next.js', category: 'framework' },\n react: { name: 'React', category: 'framework' },\n vue: { name: 'Vue', category: 'framework' },\n nuxt: { name: 'Nuxt', category: 'framework' },\n svelte: { name: 'Svelte', category: 'framework' },\n '@sveltejs/kit': { name: 'SvelteKit', category: 'framework' },\n '@angular/core': { name: 'Angular', category: 'framework' },\n astro: { name: 'Astro', category: 'framework' },\n electron: { name: 'Electron', category: 'framework' },\n '@remix-run/react': { name: 'Remix', category: 'framework' },\n vite: { name: 'Vite', category: 'tool' },\n typescript: { name: 'TypeScript', category: 'tool' },\n eslint: { name: 'ESLint', category: 'tool' },\n prettier: { name: 'Prettier', category: 'tool' },\n tailwindcss: { name: 'Tailwind CSS', category: 'tool' },\n webpack: { name: 'webpack', category: 'tool' },\n '@biomejs/biome': { name: 'Biome', category: 'tool' },\n jest: { name: 'Jest', category: 'test' },\n vitest: { name: 'Vitest', category: 'test' },\n mocha: { name: 'Mocha', category: 'test' },\n '@playwright/test': { name: 'Playwright', category: 'test' },\n cypress: { name: 'Cypress', category: 'test' },\n prisma: { name: 'Prisma', category: 'database' },\n '@prisma/client': { name: 'Prisma', category: 'database' },\n typeorm: { name: 'TypeORM', category: 'database' },\n mongoose: { name: 'Mongoose', category: 'database' },\n sequelize: { name: 'Sequelize', category: 'database' },\n 'drizzle-orm': { name: 'Drizzle', category: 'database' },\n knex: { name: 'Knex', category: 'database' },\n pg: { name: 'PostgreSQL client', category: 'database' },\n redis: { name: 'Redis client', category: 'database' },\n ioredis: { name: 'Redis client', category: 'database' },\n};\n\nconst PY_DEP_MAP: Record<string, { name: string; category: Detected['category'] }> = {\n fastapi: { name: 'FastAPI', category: 'framework' },\n django: { name: 'Django', category: 'framework' },\n flask: { name: 'Flask', category: 'framework' },\n starlette: { name: 'Starlette', category: 'framework' },\n celery: { name: 'Celery', category: 'framework' },\n pydantic: { name: 'Pydantic', category: 'tool' },\n sqlalchemy: { name: 'SQLAlchemy', category: 'database' },\n alembic: { name: 'Alembic', category: 'database' },\n pytest: { name: 'pytest', category: 'test' },\n ruff: { name: 'Ruff', category: 'tool' },\n mypy: { name: 'mypy', category: 'tool' },\n black: { name: 'Black', category: 'tool' },\n};\n\nconst TEST_CONFIG_RE =\n /(^|\\/)(jest\\.config\\.[cm]?[jt]s|jest\\.config\\.json|vitest\\.config\\.[cm]?[jt]s|vitest\\.workspace\\.[cm]?[jt]s|playwright\\.config\\.[cm]?[jt]s|cypress\\.config\\.[cm]?[jt]s|\\.mocharc\\.[a-z]+|pytest\\.ini|tox\\.ini|conftest\\.py|phpunit\\.xml(\\.dist)?|karma\\.conf\\.[cm]?js)$/;\n\nconst AI_FILES = [\n 'CLAUDE.md',\n 'CLAUDE.local.md',\n '.claude/CLAUDE.md',\n 'AGENTS.md',\n 'GEMINI.md',\n '.cursorrules',\n '.github/copilot-instructions.md',\n '.windsurfrules',\n];\n\n/** Directories that hold samples or test data rather than the project's own code; they must not define its stack. */\nconst AUX_DIRS = new Set(['fixtures', 'fixture', '__fixtures__', 'examples', 'example', 'samples', 'sample', 'testdata', 'test-data', 'demo', 'demos', 'docs', 'doc', 'third_party', 'thirdparty']);\n\nexport function isAuxPath(rel: string): boolean {\n return rel.split('/').slice(0, -1).some((s) => AUX_DIRS.has(s.toLowerCase()));\n}\n\nfunction parseJsonLoose(text: string | null): Record<string, unknown> | null {\n if (!text) return null;\n try {\n const v = JSON.parse(text);\n return typeof v === 'object' && v !== null && !Array.isArray(v) ? (v as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nfunction strMap(v: unknown): Record<string, string> {\n const out: Record<string, string> = {};\n if (typeof v === 'object' && v !== null) {\n for (const [k, val] of Object.entries(v as Record<string, unknown>)) if (typeof val === 'string') out[k] = val;\n }\n return out;\n}\n\nexport async function readPackageJson(root: string, rel: string): Promise<PackageInfo | null> {\n let text: string | null;\n try {\n text = await safeReadText(root, rel, 1024 * 1024);\n } catch {\n return null;\n }\n const j = parseJsonLoose(text);\n if (!j) return null;\n const ws = j.workspaces;\n const workspaces = Array.isArray(ws)\n ? ws.filter((x): x is string => typeof x === 'string')\n : typeof ws === 'object' && ws !== null && Array.isArray((ws as { packages?: unknown }).packages)\n ? ((ws as { packages: unknown[] }).packages.filter((x) => typeof x === 'string') as string[])\n : [];\n const deps = { ...strMap(j.dependencies), ...strMap(j.devDependencies), ...strMap(j.peerDependencies) };\n return {\n rel,\n name: typeof j.name === 'string' ? j.name : undefined,\n scripts: strMap(j.scripts),\n deps,\n workspaces,\n packageManagerField: typeof j.packageManager === 'string' ? j.packageManager : undefined,\n hasTypes: 'typescript' in deps,\n type: typeof j.type === 'string' ? j.type : undefined,\n };\n}\n\nfunction nodeFrameworks(pkg: PackageInfo): Detected[] {\n const out = new Map<string, Detected>();\n for (const dep of Object.keys(pkg.deps)) {\n const hit = NODE_DEP_MAP[dep];\n if (hit && !out.has(hit.name)) out.set(hit.name, { ...hit, evidence: pkg.rel });\n }\n return [...out.values()];\n}\n\nasync function pythonText(root: string, scan: ScanResult): Promise<{ text: string; evidence: Record<string, string> }> {\n const names = [...scan.files].filter((f) => {\n const b = path.posix.basename(f);\n const depth = f.split('/').length;\n return depth <= 3 && !isAuxPath(f) && (b === 'pyproject.toml' || /^requirements.*\\.txt$/.test(b) || b === 'Pipfile' || b === 'setup.py' || b === 'setup.cfg');\n });\n let text = '';\n const evidence: Record<string, string> = {};\n for (const n of names.slice(0, 12)) {\n const t = await safeReadText(root, n, 256 * 1024).catch(() => null);\n if (t) {\n text += `\\n${t.toLowerCase()}`;\n for (const key of Object.keys(PY_DEP_MAP)) {\n if (!evidence[key] && new RegExp(`(^|[\\\\s\"'\\\\[,=<>~!-])${key}(?![a-z0-9_])`, 'm').test(t.toLowerCase())) evidence[key] = n;\n }\n }\n }\n return { text, evidence };\n}\n\nfunction parseWorkspaceYaml(text: string): string[] {\n const out: string[] = [];\n for (const line of text.split(/\\r?\\n/)) {\n const m = /^\\s*-\\s*['\"]?([^'\"#]+?)['\"]?\\s*(?:#.*)?$/.exec(line);\n if (m && m[1] && !m[1].startsWith('!')) out.push(m[1].trim());\n }\n return out;\n}\n\n/** Expand simple workspace globs (\"packages/*\", \"apps/**\" treated as one level, or a literal directory). */\nexport function expandWorkspaceGlobs(patterns: string[], files: Set<string>, manifest: string): string[] {\n const dirs = new Set<string>();\n for (const f of files) {\n if (path.posix.basename(f) === manifest && f.includes('/')) dirs.add(path.posix.dirname(f));\n }\n const out = new Set<string>();\n for (const pat of patterns) {\n const clean = pat.replace(/^\\.\\//, '').replace(/\\/$/, '');\n if (!clean.includes('*')) {\n if (dirs.has(clean)) out.add(clean);\n continue;\n }\n const prefix = clean.slice(0, clean.indexOf('*')).replace(/\\/$/, '');\n const deep = clean.includes('**');\n for (const d of dirs) {\n if (!d.startsWith(prefix + '/')) continue;\n const rest = d.slice(prefix.length + 1);\n if (deep || !rest.includes('/')) out.add(d);\n }\n }\n return [...out].sort();\n}\n\nfunction languagesFrom(byExt: Record<string, number>): { name: string; files: number }[] {\n const acc = new Map<string, number>();\n for (const [ext, n] of Object.entries(byExt)) {\n const lang = EXT_LANG[ext];\n if (lang) acc.set(lang, (acc.get(lang) ?? 0) + n);\n }\n return [...acc.entries()].map(([name, files]) => ({ name, files })).sort((a, b) => b.files - a.files || a.name.localeCompare(b.name));\n}\n\nexport interface DetectInput {\n root: string;\n projectName: string;\n scan: ScanResult;\n}\n\nconst LOCKFILES: [string, string][] = [\n ['pnpm-lock.yaml', 'pnpm'],\n ['yarn.lock', 'yarn'],\n ['bun.lockb', 'bun'],\n ['bun.lock', 'bun'],\n ['package-lock.json', 'npm'],\n ['npm-shrinkwrap.json', 'npm'],\n];\n\nconst MAX_NODE_PACKAGES = 200;\nconst MAX_MANIFEST_DEPTH = 5;\n\n/** A package.json that only sets {\"type\":\"module\"} (a marker file) is not a package. */\nfunction isRealManifest(p: PackageInfo): boolean {\n return !!p.name || Object.keys(p.scripts).length > 0 || Object.keys(p.deps).length > 0 || p.workspaces.length > 0;\n}\n\nfunction lockfilePm(files: Set<string>, dir: string): string | null {\n for (const [lock, pm] of LOCKFILES) if (files.has(dir ? `${dir}/${lock}` : lock)) return pm;\n return null;\n}\n\nexport interface FoundNodePackage extends NodePackageInput {\n manifest: string;\n /** Where the package manager came from, for transparency in discovery.json consumers. */\n pmSource: 'lockfile' | 'packageManager field' | 'inherited from root' | 'default';\n}\n\n/**\n * Find every Node.js package, not just the root one. Each package gets its own package manager from its own lockfile\n * (falling back to the packageManager field, then the root lockfile, then npm). No script is ever executed.\n */\nexport async function discoverNodePackages(root: string, files: Set<string>): Promise<{ packages: FoundNodePackage[]; unparsable: string[] }> {\n const manifests = [...files]\n .filter((f) => path.posix.basename(f) === 'package.json' && !isAuxPath(f) && f.split('/').length <= MAX_MANIFEST_DEPTH)\n .sort((a, b) => a.split('/').length - b.split('/').length || a.localeCompare(b))\n .slice(0, MAX_NODE_PACKAGES);\n const rootLockPm = lockfilePm(files, '');\n const packages: FoundNodePackage[] = [];\n const unparsable: string[] = [];\n for (const manifest of manifests) {\n const pkg = await readPackageJson(root, manifest);\n if (!pkg) {\n unparsable.push(manifest);\n continue;\n }\n if (!isRealManifest(pkg)) continue;\n const dir = path.posix.dirname(manifest) === '.' ? '' : path.posix.dirname(manifest);\n const own = lockfilePm(files, dir);\n const field = pkg.packageManagerField?.split('@')[0] ?? null;\n let packageManager: string;\n let pmSource: FoundNodePackage['pmSource'];\n if (own) {\n packageManager = own;\n pmSource = 'lockfile';\n } else if (field) {\n packageManager = field;\n pmSource = 'packageManager field';\n } else if (rootLockPm && dir !== '') {\n packageManager = rootLockPm;\n pmSource = 'inherited from root';\n } else {\n packageManager = 'npm';\n pmSource = 'default';\n }\n packages.push({ dir, pkg, packageManager, hasTsconfig: files.has(dir ? `${dir}/tsconfig.json` : 'tsconfig.json'), manifest, pmSource });\n }\n return { packages, unparsable };\n}\n\nexport async function detectProject(input: DetectInput): Promise<DiscoveryReport> {\n const { root, scan } = input;\n const files = scan.files;\n const has = (rel: string): boolean => files.has(rel);\n const warnings: string[] = [];\n const ecosystems = new Set<string>();\n const frameworks = new Map<string, Detected>();\n const addFw = (d: Detected): void => {\n if (!frameworks.has(d.name)) frameworks.set(d.name, d);\n };\n\n // Node / JS: every package.json, not only the one at the root\n const { packages: nodePkgs, unparsable } = await discoverNodePackages(root, files);\n for (const m of unparsable.slice(0, 5)) warnings.push(`${m} exists but could not be parsed.`);\n const rootNode = nodePkgs.find((p) => p.dir === '');\n const rootPkg = rootNode?.pkg ?? null;\n if (nodePkgs.length > 0) {\n ecosystems.add('node');\n for (const p of nodePkgs) nodeFrameworks(p.pkg).forEach(addFw);\n }\n let packageManager: string | null = null;\n const pms = [...new Set(nodePkgs.map((p) => p.packageManager))].sort();\n if (pms.length === 1) packageManager = pms[0]!;\n else if (pms.length > 1) packageManager = `mixed (${pms.join(', ')})`;\n\n // Python\n const py = await pythonText(root, scan);\n const hasPy = has('pyproject.toml') || has('requirements.txt') || has('Pipfile') || has('setup.py') || [...files].some((f) => f.endsWith('.py') && !isAuxPath(f));\n if (hasPy) {\n ecosystems.add('python');\n for (const [k, ev] of Object.entries(py.evidence)) {\n const m = PY_DEP_MAP[k];\n if (m) addFw({ ...m, evidence: ev });\n }\n if (!packageManager) {\n if (has('poetry.lock') || py.text.includes('[tool.poetry]')) packageManager = 'poetry';\n else if (has('uv.lock')) packageManager = 'uv';\n else if (has('Pipfile')) packageManager = 'pipenv';\n else if (has('requirements.txt') || has('pyproject.toml')) packageManager = 'pip';\n }\n }\n\n const simple: [string, string, string][] = [\n ['go.mod', 'go', 'go'],\n ['Cargo.toml', 'rust', 'cargo'],\n ['pom.xml', 'java', 'maven'],\n ['build.gradle', 'java', 'gradle'],\n ['build.gradle.kts', 'java', 'gradle'],\n ['composer.json', 'php', 'composer'],\n ['Gemfile', 'ruby', 'bundler'],\n ];\n for (const [file, eco, pm] of simple) {\n if (has(file)) {\n ecosystems.add(eco);\n if (!packageManager) packageManager = pm;\n }\n }\n if ([...files].some((f) => /\\.csproj$/.test(f) && f.split('/').length <= 3)) ecosystems.add('dotnet');\n\n // Monorepo\n let monoTool: string | null = null;\n let workspacePatterns: string[] = [];\n let manifest = 'package.json';\n if (has('pnpm-workspace.yaml')) {\n monoTool = 'pnpm-workspaces';\n workspacePatterns = parseWorkspaceYaml((await safeReadText(root, 'pnpm-workspace.yaml', 64 * 1024).catch(() => null)) ?? '');\n } else if (rootPkg && rootPkg.workspaces.length > 0) {\n monoTool = rootNode?.packageManager === 'yarn' ? 'yarn-workspaces' : 'npm-workspaces';\n workspacePatterns = rootPkg.workspaces;\n } else if (has('lerna.json')) monoTool = 'lerna';\n else if (has('nx.json')) monoTool = 'nx';\n else if (has('turbo.json')) monoTool = 'turborepo';\n else if (has('Cargo.toml')) {\n const cargo = (await safeReadText(root, 'Cargo.toml', 64 * 1024).catch(() => null)) ?? '';\n if (/^\\[workspace\\]/m.test(cargo)) {\n monoTool = 'cargo-workspace';\n manifest = 'Cargo.toml';\n workspacePatterns = [...cargo.matchAll(/\"([^\"]+)\"/g)].map((m) => m[1]!).filter((s) => !s.includes(' '));\n }\n } else if (has('go.work')) monoTool = 'go-work';\n\n const packages: SubProject[] = [];\n for (const p of nodePkgs) {\n if (p.dir === '') continue;\n packages.push({ path: p.dir, name: p.pkg.name ?? path.posix.basename(p.dir), ecosystem: 'node', frameworks: nodeFrameworks(p.pkg).map((f) => f.name), packageManager: p.packageManager });\n }\n if (monoTool === 'cargo-workspace') {\n for (const d of expandWorkspaceGlobs(workspacePatterns, files, manifest).slice(0, 100)) {\n packages.push({ path: d, name: path.posix.basename(d), ecosystem: 'rust', frameworks: [] });\n }\n }\n // Several packages without any workspace tooling (e.g. backend/ + frontend/ and no root package.json) is still one repository of many packages.\n if (!monoTool && nodePkgs.length >= 2) monoTool = 'multi-package';\n\n const testConfigs = [...files].filter((f) => TEST_CONFIG_RE.test(f) && f.split('/').length <= 4 && !isAuxPath(f)).sort().slice(0, 30);\n const ci = [\n ...[...files].filter((f) => f.startsWith('.github/workflows/')),\n ...['.gitlab-ci.yml', 'azure-pipelines.yml', 'Jenkinsfile', '.travis.yml', 'bitbucket-pipelines.yml', '.circleci/config.yml'].filter(has),\n ].sort();\n const docker = [...files].filter((f) => !isAuxPath(f) && /(^|\\/)(Dockerfile(\\..+)?|docker-compose[^/]*\\.ya?ml|compose\\.ya?ml)$/.test(f) && f.split('/').length <= 3).sort();\n const deployment = [\n 'vercel.json',\n 'netlify.toml',\n 'fly.toml',\n 'render.yaml',\n 'Procfile',\n 'app.yaml',\n 'serverless.yml',\n 'wrangler.toml',\n 'railway.json',\n 'firebase.json',\n 'Chart.yaml',\n ]\n .filter(has)\n .concat([...files].filter((f) => /^(k8s|kubernetes|deploy|infra|terraform)\\//.test(f)).slice(0, 5))\n .sort();\n const aiInstructions = [...AI_FILES.filter(has), ...[...files].filter((f) => f.startsWith('.claude/') && /\\.(md|json)$/.test(f)).slice(0, 20)].sort();\n const docs = [\n ...[...files].filter((f) => /^readme(\\.[a-z]+)?$/i.test(f)),\n ...[...files].filter((f) => /^docs\\/[^/]+\\.(md|mdx|rst)$/i.test(f)).slice(0, 15),\n ...['CONTRIBUTING.md', 'ARCHITECTURE.md', 'CHANGELOG.md'].filter(has),\n ].sort();\n\n const entryHints: string[] = [];\n for (const cand of ['src/index.ts', 'src/main.ts', 'src/app.ts', 'src/server.ts', 'index.js', 'server.js', 'app.js', 'main.py', 'app/main.py', 'main.go', 'cmd', 'src/main.rs', 'manage.py', 'src/App.tsx', 'app/layout.tsx']) {\n if (has(cand) || [...files].some((f) => f.startsWith(cand + '/'))) entryHints.push(cand);\n }\n\n const commands = buildContract({\n nodePackages: nodePkgs,\n ecosystems,\n has,\n pythonEvidence: py.evidence,\n files,\n });\n\n const languages = languagesFrom(scan.byExtension).slice(0, 12);\n if (ecosystems.size === 0 && languages.length > 0) {\n warnings.push(\n `No ecosystem was recognised although source files were found (${languages.slice(0, 3).map((l) => l.name).join(', ')}). Package manifests may be missing or unsupported; record verification commands by hand in .devworkspace/context/commands.json.`,\n );\n }\n if (ecosystems.size > 0 && !commands.some((c) => c.available)) {\n warnings.push('No verification commands (tests, lint, typecheck, build) were found in the package manifests.');\n }\n if (scan.truncated) warnings.push('Scan hit its file or depth limit; discovery is partial.');\n if (scan.sensitiveFiles.length > 0) warnings.push('Credential-like files exist; their contents were not read.');\n if (!has('README.md') && !docs.some((d) => /^readme/i.test(d))) warnings.push('No README found.');\n\n return {\n schemaVersion: 1,\n project: { name: rootPkg?.name ?? input.projectName },\n scan: {\n fileCount: scan.fileCount,\n dirCount: scan.dirCount,\n truncated: scan.truncated,\n skippedSymlinks: scan.skippedSymlinks,\n ignoredEntries: scan.ignoredEntries,\n },\n languages,\n topDirs: scan.topDirs,\n ecosystems: [...ecosystems].sort(),\n packageManager,\n frameworks: [...frameworks.values()].sort((a, b) => a.name.localeCompare(b.name)),\n monorepo: { tool: monoTool, packages },\n commands,\n manifests: [...nodePkgs.map((p) => p.manifest), ...['pyproject.toml', 'requirements.txt', 'Pipfile', 'go.mod', 'Cargo.toml', 'pom.xml', 'build.gradle', 'build.gradle.kts', 'composer.json', 'Gemfile'].filter(has)].sort(),\n testConfigs,\n ci,\n docker,\n deployment,\n aiInstructions,\n docs,\n sensitiveFilesPresent: scan.sensitiveFiles.filter((f) => isSensitiveFile(f)),\n entryHints,\n warnings,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/discovery/detect.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { safeReadText } from '../security/files.js';\nimport { isSensitiveFile } from '../security/files.js';\nimport type { ScanResult } from './scan.js';\nimport { buildContract, type NodePackageInput } from './commands.js';\nimport type { CommandEntry } from '../config/schemas.js';\nimport { detectDocs, MAX_DOCS } from './docs.js';\nimport { discoverEntryPoints, type EntryPoint } from './entrypoints.js';\n\nexport interface Detected {\n name: string;\n category: 'framework' | 'test' | 'tool' | 'database' | 'runtime';\n evidence: string;\n}\n\nexport interface SubProject {\n path: string;\n name: string;\n ecosystem: string;\n frameworks: string[];\n packageManager?: string;\n}\n\nexport interface PackageInfo {\n rel: string;\n name?: string;\n scripts: Record<string, string>;\n deps: Record<string, string>;\n workspaces: string[];\n packageManagerField?: string;\n hasTypes: boolean;\n type?: string;\n /** `main` field and `bin` targets, used as evidence for entry points. */\n main?: string;\n bin?: string[];\n}\n\nexport interface DiscoveryReport {\n schemaVersion: 1;\n project: { name: string };\n scan: {\n fileCount: number;\n dirCount: number;\n truncated: boolean;\n skippedSymlinks: number;\n ignoredEntries: number;\n };\n languages: { name: string; files: number }[];\n topDirs: { name: string; files: number }[];\n ecosystems: string[];\n packageManager: string | null;\n frameworks: Detected[];\n monorepo: { tool: string | null; packages: SubProject[] };\n commands: CommandEntry[];\n /** Recognised package manifests (project-relative). Used as evidence for derived facts. */\n manifests: string[];\n testConfigs: string[];\n ci: string[];\n docker: string[];\n deployment: string[];\n aiInstructions: string[];\n docs: string[];\n /** Names of credential-like files that exist. Their content is never read. */\n sensitiveFilesPresent: string[];\n entryHints: string[];\n /** Entry points a package itself declares (start-like scripts, `main`, `bin`), with the evidence for each. */\n entryPoints: EntryPoint[];\n warnings: string[];\n}\n\nconst EXT_LANG: Record<string, string> = {\n '.ts': 'TypeScript',\n '.tsx': 'TypeScript',\n '.mts': 'TypeScript',\n '.cts': 'TypeScript',\n '.js': 'JavaScript',\n '.jsx': 'JavaScript',\n '.mjs': 'JavaScript',\n '.cjs': 'JavaScript',\n '.py': 'Python',\n '.go': 'Go',\n '.rs': 'Rust',\n '.java': 'Java',\n '.kt': 'Kotlin',\n '.php': 'PHP',\n '.rb': 'Ruby',\n '.cs': 'C#',\n '.swift': 'Swift',\n '.c': 'C',\n '.h': 'C',\n '.cpp': 'C++',\n '.cc': 'C++',\n '.hpp': 'C++',\n '.vue': 'Vue',\n '.svelte': 'Svelte',\n '.sql': 'SQL',\n};\n\nconst NODE_DEP_MAP: Record<string, { name: string; category: Detected['category'] }> = {\n express: { name: 'Express', category: 'framework' },\n fastify: { name: 'Fastify', category: 'framework' },\n koa: { name: 'Koa', category: 'framework' },\n hono: { name: 'Hono', category: 'framework' },\n '@nestjs/core': { name: 'NestJS', category: 'framework' },\n next: { name: 'Next.js', category: 'framework' },\n react: { name: 'React', category: 'framework' },\n vue: { name: 'Vue', category: 'framework' },\n nuxt: { name: 'Nuxt', category: 'framework' },\n svelte: { name: 'Svelte', category: 'framework' },\n '@sveltejs/kit': { name: 'SvelteKit', category: 'framework' },\n '@angular/core': { name: 'Angular', category: 'framework' },\n astro: { name: 'Astro', category: 'framework' },\n electron: { name: 'Electron', category: 'framework' },\n '@remix-run/react': { name: 'Remix', category: 'framework' },\n vite: { name: 'Vite', category: 'tool' },\n typescript: { name: 'TypeScript', category: 'tool' },\n eslint: { name: 'ESLint', category: 'tool' },\n prettier: { name: 'Prettier', category: 'tool' },\n tailwindcss: { name: 'Tailwind CSS', category: 'tool' },\n webpack: { name: 'webpack', category: 'tool' },\n '@biomejs/biome': { name: 'Biome', category: 'tool' },\n jest: { name: 'Jest', category: 'test' },\n vitest: { name: 'Vitest', category: 'test' },\n mocha: { name: 'Mocha', category: 'test' },\n '@playwright/test': { name: 'Playwright', category: 'test' },\n cypress: { name: 'Cypress', category: 'test' },\n prisma: { name: 'Prisma', category: 'database' },\n '@prisma/client': { name: 'Prisma', category: 'database' },\n typeorm: { name: 'TypeORM', category: 'database' },\n mongoose: { name: 'Mongoose', category: 'database' },\n sequelize: { name: 'Sequelize', category: 'database' },\n 'drizzle-orm': { name: 'Drizzle', category: 'database' },\n knex: { name: 'Knex', category: 'database' },\n pg: { name: 'PostgreSQL client', category: 'database' },\n redis: { name: 'Redis client', category: 'database' },\n ioredis: { name: 'Redis client', category: 'database' },\n};\n\nconst PY_DEP_MAP: Record<string, { name: string; category: Detected['category'] }> = {\n fastapi: { name: 'FastAPI', category: 'framework' },\n django: { name: 'Django', category: 'framework' },\n flask: { name: 'Flask', category: 'framework' },\n starlette: { name: 'Starlette', category: 'framework' },\n celery: { name: 'Celery', category: 'framework' },\n pydantic: { name: 'Pydantic', category: 'tool' },\n sqlalchemy: { name: 'SQLAlchemy', category: 'database' },\n alembic: { name: 'Alembic', category: 'database' },\n pytest: { name: 'pytest', category: 'test' },\n ruff: { name: 'Ruff', category: 'tool' },\n mypy: { name: 'mypy', category: 'tool' },\n black: { name: 'Black', category: 'tool' },\n};\n\nconst TEST_CONFIG_RE =\n /(^|\\/)(jest\\.config\\.[cm]?[jt]s|jest\\.config\\.json|vitest\\.config\\.[cm]?[jt]s|vitest\\.workspace\\.[cm]?[jt]s|playwright\\.config\\.[cm]?[jt]s|cypress\\.config\\.[cm]?[jt]s|\\.mocharc\\.[a-z]+|pytest\\.ini|tox\\.ini|conftest\\.py|phpunit\\.xml(\\.dist)?|karma\\.conf\\.[cm]?js)$/;\n\nconst AI_FILES = [\n 'CLAUDE.md',\n 'CLAUDE.local.md',\n '.claude/CLAUDE.md',\n 'AGENTS.md',\n 'GEMINI.md',\n '.cursorrules',\n '.github/copilot-instructions.md',\n '.windsurfrules',\n];\n\n/** Directories that hold samples or test data rather than the project's own code; they must not define its stack. */\nconst AUX_DIRS = new Set(['fixtures', 'fixture', '__fixtures__', 'examples', 'example', 'samples', 'sample', 'testdata', 'test-data', 'demo', 'demos', 'docs', 'doc', 'third_party', 'thirdparty']);\n\nexport function isAuxPath(rel: string): boolean {\n return rel.split('/').slice(0, -1).some((s) => AUX_DIRS.has(s.toLowerCase()));\n}\n\nfunction parseJsonLoose(text: string | null): Record<string, unknown> | null {\n if (!text) return null;\n try {\n const v = JSON.parse(text);\n return typeof v === 'object' && v !== null && !Array.isArray(v) ? (v as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nfunction strMap(v: unknown): Record<string, string> {\n const out: Record<string, string> = {};\n if (typeof v === 'object' && v !== null) {\n for (const [k, val] of Object.entries(v as Record<string, unknown>)) if (typeof val === 'string') out[k] = val;\n }\n return out;\n}\n\nexport async function readPackageJson(root: string, rel: string): Promise<PackageInfo | null> {\n let text: string | null;\n try {\n text = await safeReadText(root, rel, 1024 * 1024);\n } catch {\n return null;\n }\n const j = parseJsonLoose(text);\n if (!j) return null;\n const ws = j.workspaces;\n const workspaces = Array.isArray(ws)\n ? ws.filter((x): x is string => typeof x === 'string')\n : typeof ws === 'object' && ws !== null && Array.isArray((ws as { packages?: unknown }).packages)\n ? ((ws as { packages: unknown[] }).packages.filter((x) => typeof x === 'string') as string[])\n : [];\n const deps = { ...strMap(j.dependencies), ...strMap(j.devDependencies), ...strMap(j.peerDependencies) };\n return {\n rel,\n name: typeof j.name === 'string' ? j.name : undefined,\n scripts: strMap(j.scripts),\n deps,\n workspaces,\n packageManagerField: typeof j.packageManager === 'string' ? j.packageManager : undefined,\n hasTypes: 'typescript' in deps,\n type: typeof j.type === 'string' ? j.type : undefined,\n main: typeof j.main === 'string' ? j.main : undefined,\n bin: typeof j.bin === 'string' ? [j.bin] : Object.values(strMap(j.bin)),\n };\n}\n\nfunction nodeFrameworks(pkg: PackageInfo): Detected[] {\n const out = new Map<string, Detected>();\n for (const dep of Object.keys(pkg.deps)) {\n const hit = NODE_DEP_MAP[dep];\n if (hit && !out.has(hit.name)) out.set(hit.name, { ...hit, evidence: pkg.rel });\n }\n return [...out.values()];\n}\n\nasync function pythonText(root: string, scan: ScanResult): Promise<{ text: string; evidence: Record<string, string> }> {\n const names = [...scan.files].filter((f) => {\n const b = path.posix.basename(f);\n const depth = f.split('/').length;\n return depth <= 3 && !isAuxPath(f) && (b === 'pyproject.toml' || /^requirements.*\\.txt$/.test(b) || b === 'Pipfile' || b === 'setup.py' || b === 'setup.cfg');\n });\n let text = '';\n const evidence: Record<string, string> = {};\n for (const n of names.slice(0, 12)) {\n const t = await safeReadText(root, n, 256 * 1024).catch(() => null);\n if (t) {\n text += `\\n${t.toLowerCase()}`;\n for (const key of Object.keys(PY_DEP_MAP)) {\n if (!evidence[key] && new RegExp(`(^|[\\\\s\"'\\\\[,=<>~!-])${key}(?![a-z0-9_])`, 'm').test(t.toLowerCase())) evidence[key] = n;\n }\n }\n }\n return { text, evidence };\n}\n\nfunction parseWorkspaceYaml(text: string): string[] {\n const out: string[] = [];\n for (const line of text.split(/\\r?\\n/)) {\n const m = /^\\s*-\\s*['\"]?([^'\"#]+?)['\"]?\\s*(?:#.*)?$/.exec(line);\n if (m && m[1] && !m[1].startsWith('!')) out.push(m[1].trim());\n }\n return out;\n}\n\n/** Expand simple workspace globs (\"packages/*\", \"apps/**\" treated as one level, or a literal directory). */\nexport function expandWorkspaceGlobs(patterns: string[], files: Set<string>, manifest: string): string[] {\n const dirs = new Set<string>();\n for (const f of files) {\n if (path.posix.basename(f) === manifest && f.includes('/')) dirs.add(path.posix.dirname(f));\n }\n const out = new Set<string>();\n for (const pat of patterns) {\n const clean = pat.replace(/^\\.\\//, '').replace(/\\/$/, '');\n if (!clean.includes('*')) {\n if (dirs.has(clean)) out.add(clean);\n continue;\n }\n const prefix = clean.slice(0, clean.indexOf('*')).replace(/\\/$/, '');\n const deep = clean.includes('**');\n for (const d of dirs) {\n if (!d.startsWith(prefix + '/')) continue;\n const rest = d.slice(prefix.length + 1);\n if (deep || !rest.includes('/')) out.add(d);\n }\n }\n return [...out].sort();\n}\n\nfunction languagesFrom(byExt: Record<string, number>): { name: string; files: number }[] {\n const acc = new Map<string, number>();\n for (const [ext, n] of Object.entries(byExt)) {\n const lang = EXT_LANG[ext];\n if (lang) acc.set(lang, (acc.get(lang) ?? 0) + n);\n }\n return [...acc.entries()].map(([name, files]) => ({ name, files })).sort((a, b) => b.files - a.files || a.name.localeCompare(b.name));\n}\n\nexport interface DetectInput {\n root: string;\n projectName: string;\n scan: ScanResult;\n}\n\nconst LOCKFILES: [string, string][] = [\n ['pnpm-lock.yaml', 'pnpm'],\n ['yarn.lock', 'yarn'],\n ['bun.lockb', 'bun'],\n ['bun.lock', 'bun'],\n ['package-lock.json', 'npm'],\n ['npm-shrinkwrap.json', 'npm'],\n];\n\nconst MAX_NODE_PACKAGES = 200;\nconst MAX_MANIFEST_DEPTH = 5;\n\n/** A package.json that only sets {\"type\":\"module\"} (a marker file) is not a package. */\nfunction isRealManifest(p: PackageInfo): boolean {\n return !!p.name || Object.keys(p.scripts).length > 0 || Object.keys(p.deps).length > 0 || p.workspaces.length > 0;\n}\n\nfunction lockfilePm(files: Set<string>, dir: string): string | null {\n for (const [lock, pm] of LOCKFILES) if (files.has(dir ? `${dir}/${lock}` : lock)) return pm;\n return null;\n}\n\nexport interface FoundNodePackage extends NodePackageInput {\n manifest: string;\n /** Where the package manager came from, for transparency in discovery.json consumers. */\n pmSource: 'lockfile' | 'packageManager field' | 'inherited from root' | 'default';\n}\n\n/**\n * Find every Node.js package, not just the root one. Each package gets its own package manager from its own lockfile\n * (falling back to the packageManager field, then the root lockfile, then npm). No script is ever executed.\n */\nexport async function discoverNodePackages(root: string, files: Set<string>): Promise<{ packages: FoundNodePackage[]; unparsable: string[] }> {\n const manifests = [...files]\n .filter((f) => path.posix.basename(f) === 'package.json' && !isAuxPath(f) && f.split('/').length <= MAX_MANIFEST_DEPTH)\n .sort((a, b) => a.split('/').length - b.split('/').length || a.localeCompare(b))\n .slice(0, MAX_NODE_PACKAGES);\n const rootLockPm = lockfilePm(files, '');\n const packages: FoundNodePackage[] = [];\n const unparsable: string[] = [];\n for (const manifest of manifests) {\n const pkg = await readPackageJson(root, manifest);\n if (!pkg) {\n unparsable.push(manifest);\n continue;\n }\n if (!isRealManifest(pkg)) continue;\n const dir = path.posix.dirname(manifest) === '.' ? '' : path.posix.dirname(manifest);\n const own = lockfilePm(files, dir);\n const field = pkg.packageManagerField?.split('@')[0] ?? null;\n let packageManager: string;\n let pmSource: FoundNodePackage['pmSource'];\n if (own) {\n packageManager = own;\n pmSource = 'lockfile';\n } else if (field) {\n packageManager = field;\n pmSource = 'packageManager field';\n } else if (rootLockPm && dir !== '') {\n packageManager = rootLockPm;\n pmSource = 'inherited from root';\n } else {\n packageManager = 'npm';\n pmSource = 'default';\n }\n packages.push({ dir, pkg, packageManager, hasTsconfig: files.has(dir ? `${dir}/tsconfig.json` : 'tsconfig.json'), manifest, pmSource });\n }\n return { packages, unparsable };\n}\n\nexport async function detectProject(input: DetectInput): Promise<DiscoveryReport> {\n const { root, scan } = input;\n const files = scan.files;\n const has = (rel: string): boolean => files.has(rel);\n const warnings: string[] = [];\n const ecosystems = new Set<string>();\n const frameworks = new Map<string, Detected>();\n const addFw = (d: Detected): void => {\n if (!frameworks.has(d.name)) frameworks.set(d.name, d);\n };\n\n // Node / JS: every package.json, not only the one at the root\n const { packages: nodePkgs, unparsable } = await discoverNodePackages(root, files);\n for (const m of unparsable.slice(0, 5)) warnings.push(`${m} exists but could not be parsed.`);\n const rootNode = nodePkgs.find((p) => p.dir === '');\n const rootPkg = rootNode?.pkg ?? null;\n if (nodePkgs.length > 0) {\n ecosystems.add('node');\n for (const p of nodePkgs) nodeFrameworks(p.pkg).forEach(addFw);\n }\n let packageManager: string | null = null;\n const pms = [...new Set(nodePkgs.map((p) => p.packageManager))].sort();\n if (pms.length === 1) packageManager = pms[0]!;\n else if (pms.length > 1) packageManager = `mixed (${pms.join(', ')})`;\n\n // Python\n const py = await pythonText(root, scan);\n const hasPy = has('pyproject.toml') || has('requirements.txt') || has('Pipfile') || has('setup.py') || [...files].some((f) => f.endsWith('.py') && !isAuxPath(f));\n if (hasPy) {\n ecosystems.add('python');\n for (const [k, ev] of Object.entries(py.evidence)) {\n const m = PY_DEP_MAP[k];\n if (m) addFw({ ...m, evidence: ev });\n }\n if (!packageManager) {\n if (has('poetry.lock') || py.text.includes('[tool.poetry]')) packageManager = 'poetry';\n else if (has('uv.lock')) packageManager = 'uv';\n else if (has('Pipfile')) packageManager = 'pipenv';\n else if (has('requirements.txt') || has('pyproject.toml')) packageManager = 'pip';\n }\n }\n\n const simple: [string, string, string][] = [\n ['go.mod', 'go', 'go'],\n ['Cargo.toml', 'rust', 'cargo'],\n ['pom.xml', 'java', 'maven'],\n ['build.gradle', 'java', 'gradle'],\n ['build.gradle.kts', 'java', 'gradle'],\n ['composer.json', 'php', 'composer'],\n ['Gemfile', 'ruby', 'bundler'],\n ];\n for (const [file, eco, pm] of simple) {\n if (has(file)) {\n ecosystems.add(eco);\n if (!packageManager) packageManager = pm;\n }\n }\n if ([...files].some((f) => /\\.csproj$/.test(f) && f.split('/').length <= 3)) ecosystems.add('dotnet');\n\n // Monorepo\n let monoTool: string | null = null;\n let workspacePatterns: string[] = [];\n let manifest = 'package.json';\n if (has('pnpm-workspace.yaml')) {\n monoTool = 'pnpm-workspaces';\n workspacePatterns = parseWorkspaceYaml((await safeReadText(root, 'pnpm-workspace.yaml', 64 * 1024).catch(() => null)) ?? '');\n } else if (rootPkg && rootPkg.workspaces.length > 0) {\n monoTool = rootNode?.packageManager === 'yarn' ? 'yarn-workspaces' : 'npm-workspaces';\n workspacePatterns = rootPkg.workspaces;\n } else if (has('lerna.json')) monoTool = 'lerna';\n else if (has('nx.json')) monoTool = 'nx';\n else if (has('turbo.json')) monoTool = 'turborepo';\n else if (has('Cargo.toml')) {\n const cargo = (await safeReadText(root, 'Cargo.toml', 64 * 1024).catch(() => null)) ?? '';\n if (/^\\[workspace\\]/m.test(cargo)) {\n monoTool = 'cargo-workspace';\n manifest = 'Cargo.toml';\n workspacePatterns = [...cargo.matchAll(/\"([^\"]+)\"/g)].map((m) => m[1]!).filter((s) => !s.includes(' '));\n }\n } else if (has('go.work')) monoTool = 'go-work';\n\n const packages: SubProject[] = [];\n for (const p of nodePkgs) {\n if (p.dir === '') continue;\n packages.push({ path: p.dir, name: p.pkg.name ?? path.posix.basename(p.dir), ecosystem: 'node', frameworks: nodeFrameworks(p.pkg).map((f) => f.name), packageManager: p.packageManager });\n }\n if (monoTool === 'cargo-workspace') {\n for (const d of expandWorkspaceGlobs(workspacePatterns, files, manifest).slice(0, 100)) {\n packages.push({ path: d, name: path.posix.basename(d), ecosystem: 'rust', frameworks: [] });\n }\n }\n // Several packages without any workspace tooling (e.g. backend/ + frontend/ and no root package.json) is still one repository of many packages.\n if (!monoTool && nodePkgs.length >= 2) monoTool = 'multi-package';\n\n const testConfigs = [...files].filter((f) => TEST_CONFIG_RE.test(f) && f.split('/').length <= 4 && !isAuxPath(f)).sort().slice(0, 30);\n const ci = [\n ...[...files].filter((f) => f.startsWith('.github/workflows/')),\n ...['.gitlab-ci.yml', 'azure-pipelines.yml', 'Jenkinsfile', '.travis.yml', 'bitbucket-pipelines.yml', '.circleci/config.yml'].filter(has),\n ].sort();\n const docker = [...files].filter((f) => !isAuxPath(f) && /(^|\\/)(Dockerfile(\\..+)?|docker-compose[^/]*\\.ya?ml|compose\\.ya?ml)$/.test(f) && f.split('/').length <= 3).sort();\n const deployment = [\n 'vercel.json',\n 'netlify.toml',\n 'fly.toml',\n 'render.yaml',\n 'Procfile',\n 'app.yaml',\n 'serverless.yml',\n 'wrangler.toml',\n 'railway.json',\n 'firebase.json',\n 'Chart.yaml',\n ]\n .filter(has)\n .concat([...files].filter((f) => /^(k8s|kubernetes|deploy|infra|terraform)\\//.test(f)).slice(0, 5))\n .sort();\n // Instruction files only: CLAUDE.md, settings and each skill's SKILL.md. A skill's reference documents are tool-managed noise.\n const claudeFiles = [...files].filter((f) => /^\\.claude\\/(?:[^/]+\\.(?:md|json)|skills\\/[^/]+\\/SKILL\\.md)$/.test(f)).slice(0, 20);\n const aiInstructions = [...new Set([...AI_FILES.filter(has), ...claudeFiles])].sort();\n const { docs, omitted: docsOmitted } = detectDocs(files, nodePkgs.map((p) => p.dir));\n const entryPoints = discoverEntryPoints(nodePkgs, files);\n\n const entryHints: string[] = [];\n for (const cand of ['src/index.ts', 'src/main.ts', 'src/app.ts', 'src/server.ts', 'index.js', 'server.js', 'app.js', 'main.py', 'app/main.py', 'main.go', 'cmd', 'src/main.rs', 'manage.py', 'src/App.tsx', 'app/layout.tsx']) {\n if (has(cand) || [...files].some((f) => f.startsWith(cand + '/'))) entryHints.push(cand);\n }\n\n const commands = buildContract({\n nodePackages: nodePkgs,\n ecosystems,\n has,\n pythonEvidence: py.evidence,\n files,\n });\n\n const languages = languagesFrom(scan.byExtension).slice(0, 12);\n if (ecosystems.size === 0 && languages.length > 0) {\n warnings.push(\n `No ecosystem was recognised although source files were found (${languages.slice(0, 3).map((l) => l.name).join(', ')}). Package manifests may be missing or unsupported; record verification commands by hand in .devworkspace/context/commands.json.`,\n );\n }\n if (ecosystems.size > 0 && !commands.some((c) => c.available)) {\n warnings.push('No verification commands (tests, lint, typecheck, build) were found in the package manifests.');\n }\n if (docsOmitted > 0) warnings.push(`${docsOmitted} more documentation file(s) were found than are listed (limit ${MAX_DOCS}).`);\n if (scan.truncated) warnings.push('Scan hit its file or depth limit; discovery is partial.');\n if (scan.sensitiveFiles.length > 0) warnings.push('Credential-like files exist; their contents were not read.');\n if (!has('README.md') && !docs.some((d) => /^readme/i.test(d))) warnings.push('No README found.');\n\n return {\n schemaVersion: 1,\n project: { name: rootPkg?.name ?? input.projectName },\n scan: {\n fileCount: scan.fileCount,\n dirCount: scan.dirCount,\n truncated: scan.truncated,\n skippedSymlinks: scan.skippedSymlinks,\n ignoredEntries: scan.ignoredEntries,\n },\n languages,\n topDirs: scan.topDirs,\n ecosystems: [...ecosystems].sort(),\n packageManager,\n frameworks: [...frameworks.values()].sort((a, b) => a.name.localeCompare(b.name)),\n monorepo: { tool: monoTool, packages },\n commands,\n manifests: [...nodePkgs.map((p) => p.manifest), ...['pyproject.toml', 'requirements.txt', 'Pipfile', 'go.mod', 'Cargo.toml', 'pom.xml', 'build.gradle', 'build.gradle.kts', 'composer.json', 'Gemfile'].filter(has)].sort(),\n testConfigs,\n ci,\n docker,\n deployment,\n aiInstructions,\n docs,\n sensitiveFilesPresent: scan.sensitiveFiles.filter((f) => isSensitiveFile(f)),\n entryHints,\n entryPoints,\n warnings,\n };\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const MAX_DOCS = 40;
|
|
2
|
+
/**
|
|
3
|
+
* Documentation worth pointing an agent at: top-level READMEs and notes, Markdown in docs/adr/architecture directories
|
|
4
|
+
* (also inside packages such as backend/docs), and READMEs of packages. Pure function of the scanned file set, so it is
|
|
5
|
+
* deterministic; generated and dependency directories were already excluded by the scan.
|
|
6
|
+
*/
|
|
7
|
+
export declare function detectDocs(files: Iterable<string>, packageDirs: string[]): {
|
|
8
|
+
docs: string[];
|
|
9
|
+
omitted: number;
|
|
10
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
const DOC_FILE = /\.(?:md|mdx|rst)$/i;
|
|
3
|
+
const DOC_DIR = /^(?:docs?|documentation|adrs?|architecture|decisions?)$/i;
|
|
4
|
+
const TOP_LEVEL = /^(?:readme(?:\.[a-z]+)?|contributing\.md|architecture\.md|changelog\.md)$/i;
|
|
5
|
+
const PACKAGE_LEVEL = /^(?:readme|architecture|contributing)\.(?:md|mdx|rst)$/i;
|
|
6
|
+
/** Directories whose Markdown is sample data, not the project's own documentation. */
|
|
7
|
+
const SAMPLE_DIRS = new Set(['fixtures', 'fixture', '__fixtures__', 'examples', 'example', 'samples', 'sample', 'testdata', 'test-data', 'demo', 'demos', 'third_party', 'thirdparty']);
|
|
8
|
+
export const MAX_DOCS = 40;
|
|
9
|
+
const MAX_DEPTH = 6;
|
|
10
|
+
const MAX_DOC_DIR_INDEX = 2; // docs/ may sit at most two directories below the root: backend/docs, apps/api/docs
|
|
11
|
+
/** Files that matter most when the list has to be cut: indexes, architecture notes, ADRs and READMEs. */
|
|
12
|
+
function priority(file) {
|
|
13
|
+
const name = path.posix.basename(file);
|
|
14
|
+
if (/^readme/i.test(name))
|
|
15
|
+
return 0;
|
|
16
|
+
if (/(?:^|[/_-])(?:index|architecture|overview|quick[_-]?start|adrs?[-_]?\d*)(?=[/_.-]|$)/i.test(file))
|
|
17
|
+
return 1;
|
|
18
|
+
return 2;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Documentation worth pointing an agent at: top-level READMEs and notes, Markdown in docs/adr/architecture directories
|
|
22
|
+
* (also inside packages such as backend/docs), and READMEs of packages. Pure function of the scanned file set, so it is
|
|
23
|
+
* deterministic; generated and dependency directories were already excluded by the scan.
|
|
24
|
+
*/
|
|
25
|
+
export function detectDocs(files, packageDirs) {
|
|
26
|
+
const pkgReadmes = new Set(packageDirs.filter((d) => d !== '').map((d) => d));
|
|
27
|
+
const found = new Set();
|
|
28
|
+
for (const f of files) {
|
|
29
|
+
if (!DOC_FILE.test(f))
|
|
30
|
+
continue;
|
|
31
|
+
const segs = f.split('/');
|
|
32
|
+
if (segs.length > MAX_DEPTH)
|
|
33
|
+
continue;
|
|
34
|
+
const dirs = segs.slice(0, -1);
|
|
35
|
+
const name = segs[segs.length - 1];
|
|
36
|
+
if (dirs.length === 0) {
|
|
37
|
+
if (TOP_LEVEL.test(name))
|
|
38
|
+
found.add(f);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const docIdx = dirs.findIndex((s) => DOC_DIR.test(s));
|
|
42
|
+
if (docIdx !== -1 && docIdx <= MAX_DOC_DIR_INDEX && !dirs.slice(0, docIdx).some((s) => SAMPLE_DIRS.has(s.toLowerCase()))) {
|
|
43
|
+
found.add(f);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (PACKAGE_LEVEL.test(name) && pkgReadmes.has(dirs.join('/')) && !dirs.some((s) => SAMPLE_DIRS.has(s.toLowerCase())))
|
|
47
|
+
found.add(f);
|
|
48
|
+
}
|
|
49
|
+
const all = [...found].sort((a, b) => priority(a) - priority(b) || a.localeCompare(b));
|
|
50
|
+
return { docs: all.slice(0, MAX_DOCS).sort(), omitted: Math.max(0, all.length - MAX_DOCS) };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=docs.js.map
|