@massu/core 1.10.7 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1303 -0
- package/dist/adapter.js +6 -4
- package/dist/cli.js +559 -400
- package/dist/detect/adapters/.bundle-shasums.json +4 -7
- package/dist/detect/adapters/rails.js +6 -4
- package/dist/detect/adapters/spring.js +6 -4
- package/dist/detect/adapters/tree-sitter-loader.js +6 -4
- package/dist/hooks/auto-learning-pipeline.js +24 -1
- package/dist/hooks/classify-failure.js +32 -3
- package/dist/hooks/cost-tracker.js +24 -0
- package/dist/hooks/fix-detector.js +97 -1
- package/dist/hooks/incident-pipeline.js +30 -1
- package/dist/hooks/intent-suggester.js +6 -3
- package/dist/hooks/post-edit-context.js +24 -1
- package/dist/hooks/post-tool-use.js +66 -18
- package/dist/hooks/pre-compact.js +27 -2
- package/dist/hooks/pre-delete-check.js +48 -22
- package/dist/hooks/pre-tool-use-gate.js +962 -0
- package/dist/hooks/quality-event.js +24 -0
- package/dist/hooks/rule-enforcement-pipeline.js +24 -1
- package/dist/hooks/security-gate.js +29 -16
- package/dist/hooks/session-end.js +24 -0
- package/dist/hooks/session-start.js +8710 -8460
- package/dist/hooks/user-prompt.js +24 -0
- package/package.json +15 -18
- package/commands/README.md +0 -134
- package/src/adapter.ts +0 -121
- package/src/adr-generator.ts +0 -292
- package/src/analytics.ts +0 -373
- package/src/audit-trail.ts +0 -450
- package/src/backfill-sessions.ts +0 -182
- package/src/changelog-generator.ts +0 -178
- package/src/cli.ts +0 -246
- package/src/cloud-sync.ts +0 -234
- package/src/commands/adapters.ts +0 -824
- package/src/commands/changelog.ts +0 -165
- package/src/commands/config-check-drift.ts +0 -133
- package/src/commands/config-refresh.ts +0 -396
- package/src/commands/config-upgrade.ts +0 -127
- package/src/commands/doctor.ts +0 -485
- package/src/commands/hook-runner.ts +0 -145
- package/src/commands/init.ts +0 -1823
- package/src/commands/install-commands.ts +0 -692
- package/src/commands/install-hooks.ts +0 -27
- package/src/commands/permissions.ts +0 -150
- package/src/commands/refresh-log.ts +0 -37
- package/src/commands/show-template.ts +0 -65
- package/src/commands/template-engine.ts +0 -301
- package/src/commands/watch.ts +0 -430
- package/src/config.ts +0 -765
- package/src/cost-tracker.ts +0 -355
- package/src/db.ts +0 -370
- package/src/dependency-scorer.ts +0 -337
- package/src/detect/adapters/aspnet.ts +0 -4
- package/src/detect/adapters/discover.ts +0 -469
- package/src/detect/adapters/file-sampler.ts +0 -225
- package/src/detect/adapters/go-chi.ts +0 -4
- package/src/detect/adapters/index.ts +0 -51
- package/src/detect/adapters/nextjs-trpc.ts +0 -166
- package/src/detect/adapters/parse-guard.ts +0 -133
- package/src/detect/adapters/phoenix.ts +0 -4
- package/src/detect/adapters/python-django.ts +0 -208
- package/src/detect/adapters/python-fastapi.ts +0 -223
- package/src/detect/adapters/python-flask.ts +0 -235
- package/src/detect/adapters/query-helpers.ts +0 -170
- package/src/detect/adapters/rails.ts +0 -4
- package/src/detect/adapters/runner.ts +0 -284
- package/src/detect/adapters/spring.ts +0 -4
- package/src/detect/adapters/swift-swiftui.ts +0 -171
- package/src/detect/adapters/tree-sitter-loader.ts +0 -517
- package/src/detect/adapters/types.ts +0 -191
- package/src/detect/codebase-introspector.ts +0 -210
- package/src/detect/domain-inferrer.ts +0 -197
- package/src/detect/drift.ts +0 -199
- package/src/detect/framework-detector.ts +0 -307
- package/src/detect/index.ts +0 -209
- package/src/detect/manifest-registry.ts +0 -261
- package/src/detect/migrate.ts +0 -362
- package/src/detect/monorepo-detector.ts +0 -348
- package/src/detect/package-detector.ts +0 -828
- package/src/detect/passthrough.ts +0 -108
- package/src/detect/regex-fallback.ts +0 -449
- package/src/detect/source-dir-detector.ts +0 -297
- package/src/detect/vr-command-map.ts +0 -167
- package/src/docs-map.json +0 -100
- package/src/docs-tools.ts +0 -519
- package/src/domains.ts +0 -182
- package/src/hooks/auto-learning-pipeline.ts +0 -228
- package/src/hooks/classify-failure.ts +0 -259
- package/src/hooks/cost-tracker.ts +0 -66
- package/src/hooks/fix-detector.ts +0 -186
- package/src/hooks/incident-pipeline.ts +0 -190
- package/src/hooks/intent-suggester.ts +0 -131
- package/src/hooks/post-edit-context.ts +0 -91
- package/src/hooks/post-tool-use.ts +0 -413
- package/src/hooks/pre-compact.ts +0 -168
- package/src/hooks/pre-delete-check.ts +0 -243
- package/src/hooks/quality-event.ts +0 -127
- package/src/hooks/rule-enforcement-pipeline.ts +0 -159
- package/src/hooks/security-gate.ts +0 -153
- package/src/hooks/session-end.ts +0 -467
- package/src/hooks/session-start.ts +0 -436
- package/src/hooks/user-prompt.ts +0 -157
- package/src/import-resolver.ts +0 -226
- package/src/knowledge-db.ts +0 -176
- package/src/knowledge-indexer.ts +0 -708
- package/src/knowledge-tools.ts +0 -1414
- package/src/lib/fileLock.ts +0 -203
- package/src/lib/gitToplevel.ts +0 -22
- package/src/lib/hook-registry.ts +0 -43
- package/src/lib/installLock.ts +0 -66
- package/src/lib/memory-path.ts +0 -49
- package/src/lib/pidLiveness.ts +0 -67
- package/src/lib/settings-local.ts +0 -110
- package/src/lib/sql-table-names.ts +0 -71
- package/src/license.ts +0 -547
- package/src/lsp/auto-detect.ts +0 -98
- package/src/lsp/client.ts +0 -776
- package/src/lsp/enrich.ts +0 -127
- package/src/lsp/types.ts +0 -221
- package/src/memory-db.ts +0 -1614
- package/src/memory-file-ingest.ts +0 -128
- package/src/memory-tools.ts +0 -424
- package/src/middleware-tree.ts +0 -71
- package/src/observability-tools.ts +0 -343
- package/src/observation-extractor.ts +0 -418
- package/src/page-deps.ts +0 -285
- package/src/permissions.ts +0 -422
- package/src/prompt-analyzer.ts +0 -332
- package/src/python/coupling-detector.ts +0 -125
- package/src/python/domain-enforcer.ts +0 -84
- package/src/python/impact-analyzer.ts +0 -96
- package/src/python/import-parser.ts +0 -244
- package/src/python/import-resolver.ts +0 -136
- package/src/python/migration-indexer.ts +0 -116
- package/src/python/migration-parser.ts +0 -332
- package/src/python/model-indexer.ts +0 -71
- package/src/python/model-parser.ts +0 -279
- package/src/python/route-indexer.ts +0 -59
- package/src/python/route-parser.ts +0 -317
- package/src/python-tools.ts +0 -630
- package/src/regression-detector.ts +0 -319
- package/src/rules.ts +0 -57
- package/src/schema-mapper.ts +0 -232
- package/src/security/adapter-origin.ts +0 -130
- package/src/security/adapter-verifier.ts +0 -319
- package/src/security/atomic-write.ts +0 -164
- package/src/security/fetcher.ts +0 -200
- package/src/security/install-tracking.ts +0 -319
- package/src/security/license-pubkey.generated.ts +0 -30
- package/src/security/license-response-verifier.ts +0 -149
- package/src/security/local-fingerprint.ts +0 -225
- package/src/security/manifest-cache.ts +0 -333
- package/src/security/manifest-schema.ts +0 -129
- package/src/security/registry-pubkey.generated.ts +0 -35
- package/src/security/telemetry.ts +0 -320
- package/src/security-scorer.ts +0 -405
- package/src/security-utils.ts +0 -133
- package/src/sentinel-db.ts +0 -580
- package/src/sentinel-scanner.ts +0 -406
- package/src/sentinel-tools.ts +0 -513
- package/src/sentinel-types.ts +0 -140
- package/src/server-dispatch.ts +0 -225
- package/src/server.ts +0 -107
- package/src/session-archiver.ts +0 -111
- package/src/session-state-generator.ts +0 -174
- package/src/team-knowledge.ts +0 -407
- package/src/tool-db-needs.ts +0 -232
- package/src/tools.ts +0 -1205
- package/src/transcript-parser.ts +0 -458
- package/src/trpc-index.ts +0 -215
- package/src/validate-features-runner.ts +0 -107
- package/src/validation-engine.ts +0 -358
- package/src/watch/daemon.ts +0 -385
- package/src/watch/lockfile-detector.ts +0 -65
- package/src/watch/paths.ts +0 -279
- package/src/watch/state.ts +0 -178
package/src/detect/index.ts
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026 Massu. All rights reserved.
|
|
2
|
-
// Licensed under BSL 1.1 - see LICENSE file for details.
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Detection Orchestrator (P1-007)
|
|
6
|
-
* ===============================
|
|
7
|
-
*
|
|
8
|
-
* Single entry point: `runDetection(projectRoot, configOverrides?)`.
|
|
9
|
-
*
|
|
10
|
-
* Composes P1-001..P1-006 results into a fully-typed `DetectionResult`.
|
|
11
|
-
* All callers (massu init, config refresh, doctor, drift) should import
|
|
12
|
-
* from here — no direct imports of individual detectors into init/CLI code.
|
|
13
|
-
*
|
|
14
|
-
* Filesystem-only. No DB handles. No network. No child processes.
|
|
15
|
-
*
|
|
16
|
-
* Usage:
|
|
17
|
-
* ```ts
|
|
18
|
-
* import { runDetection } from './detect/index.ts';
|
|
19
|
-
* const result = await runDetection('/repo');
|
|
20
|
-
* result.monorepo.type // 'turbo' | 'pnpm' | 'single' | ...
|
|
21
|
-
* result.frameworks.python // { framework: 'fastapi', test_framework: 'pytest', ... }
|
|
22
|
-
* result.verificationCommands.python.test // 'cd apps/ai-service && python3 -m pytest -q'
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
import type { DomainConfig } from '../config.ts';
|
|
27
|
-
import {
|
|
28
|
-
detectPackageManifests,
|
|
29
|
-
type PackageManifest,
|
|
30
|
-
type PackageDetectionResult,
|
|
31
|
-
type SupportedLanguage,
|
|
32
|
-
type DetectionWarning,
|
|
33
|
-
} from './package-detector.ts';
|
|
34
|
-
import {
|
|
35
|
-
detectFrameworks,
|
|
36
|
-
type FrameworkMap,
|
|
37
|
-
type FrameworkInfo,
|
|
38
|
-
type UserDetectionRules,
|
|
39
|
-
} from './framework-detector.ts';
|
|
40
|
-
import {
|
|
41
|
-
detectSourceDirs,
|
|
42
|
-
type SourceDirMap,
|
|
43
|
-
type SourceDirInfo,
|
|
44
|
-
} from './source-dir-detector.ts';
|
|
45
|
-
import {
|
|
46
|
-
detectMonorepo,
|
|
47
|
-
type MonorepoInfo,
|
|
48
|
-
type MonorepoKind,
|
|
49
|
-
type WorkspacePackage,
|
|
50
|
-
} from './monorepo-detector.ts';
|
|
51
|
-
import {
|
|
52
|
-
getVRCommands,
|
|
53
|
-
type VRCommandSet,
|
|
54
|
-
type UserVerificationEntry,
|
|
55
|
-
} from './vr-command-map.ts';
|
|
56
|
-
import { inferDomains } from './domain-inferrer.ts';
|
|
57
|
-
import {
|
|
58
|
-
introspect,
|
|
59
|
-
type DetectedConventions,
|
|
60
|
-
} from './codebase-introspector.ts';
|
|
61
|
-
|
|
62
|
-
export type {
|
|
63
|
-
PackageManifest,
|
|
64
|
-
PackageDetectionResult,
|
|
65
|
-
SupportedLanguage,
|
|
66
|
-
DetectionWarning,
|
|
67
|
-
FrameworkMap,
|
|
68
|
-
FrameworkInfo,
|
|
69
|
-
UserDetectionRules,
|
|
70
|
-
SourceDirMap,
|
|
71
|
-
SourceDirInfo,
|
|
72
|
-
MonorepoInfo,
|
|
73
|
-
MonorepoKind,
|
|
74
|
-
WorkspacePackage,
|
|
75
|
-
VRCommandSet,
|
|
76
|
-
UserVerificationEntry,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
/** Shape a caller passes in to plug user overrides. */
|
|
80
|
-
export interface DetectionConfigOverrides {
|
|
81
|
-
/** `config.detection` — user additions to the framework detection rule table. */
|
|
82
|
-
detection?: UserDetectionRules;
|
|
83
|
-
/** `config.verification` — per-language VR-* command overrides. */
|
|
84
|
-
verification?: Record<string, UserVerificationEntry>;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface DetectionResult {
|
|
88
|
-
/** Absolute project root that was scanned. */
|
|
89
|
-
projectRoot: string;
|
|
90
|
-
/** All package manifests discovered (P1-001). */
|
|
91
|
-
manifests: PackageManifest[];
|
|
92
|
-
/** Inferred framework/test/ORM/router/ui per language (P1-002). */
|
|
93
|
-
frameworks: FrameworkMap;
|
|
94
|
-
/** Source + test directories per language (P1-003). */
|
|
95
|
-
sourceDirs: SourceDirMap;
|
|
96
|
-
/** Monorepo layout info (P1-004). */
|
|
97
|
-
monorepo: MonorepoInfo;
|
|
98
|
-
/** Suggested domains (P1-006). */
|
|
99
|
-
domains: DomainConfig[];
|
|
100
|
-
/** VR-* commands per language (P1-005). */
|
|
101
|
-
verificationCommands: Partial<Record<SupportedLanguage, VRCommandSet>>;
|
|
102
|
-
/** Non-fatal warnings collected across all detectors. */
|
|
103
|
-
warnings: DetectionWarning[];
|
|
104
|
-
/** Plan #2 P3-001: per-language conventions sampled from existing source. */
|
|
105
|
-
detected?: DetectedConventions;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** Plan #2 P3-002: opt-out of the codebase introspector. */
|
|
109
|
-
export interface RunDetectionOptions {
|
|
110
|
-
/**
|
|
111
|
-
* When true, skip the codebase introspector pass. Used by the session-start
|
|
112
|
-
* hook (P4-006) to keep its 5-second budget intact — the drift banner only
|
|
113
|
-
* needs the fingerprint, not introspection detail.
|
|
114
|
-
*/
|
|
115
|
-
skipIntrospect?: boolean;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function dominantDir(
|
|
119
|
-
lang: SupportedLanguage,
|
|
120
|
-
sourceDirs: SourceDirMap,
|
|
121
|
-
monorepo: MonorepoInfo
|
|
122
|
-
): string {
|
|
123
|
-
const info = sourceDirs[lang];
|
|
124
|
-
if (info && info.source_dirs.length > 0) return info.source_dirs[0];
|
|
125
|
-
// Fall back to the first monorepo workspace path if present.
|
|
126
|
-
if (monorepo.packages.length > 0) return monorepo.packages[0].path;
|
|
127
|
-
return '.';
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Run all detectors in order and compose a `DetectionResult`.
|
|
132
|
-
*
|
|
133
|
-
* Order (per plan):
|
|
134
|
-
* 1. packages
|
|
135
|
-
* 2. frameworks (depends on packages)
|
|
136
|
-
* 3. sourceDirs + monorepo (parallel, independent)
|
|
137
|
-
* 4. domains + verificationCommands (depend on 1-3)
|
|
138
|
-
*/
|
|
139
|
-
export async function runDetection(
|
|
140
|
-
projectRoot: string,
|
|
141
|
-
overrides?: DetectionConfigOverrides,
|
|
142
|
-
options?: RunDetectionOptions,
|
|
143
|
-
): Promise<DetectionResult> {
|
|
144
|
-
// 1. packages
|
|
145
|
-
const pkg = detectPackageManifests(projectRoot);
|
|
146
|
-
|
|
147
|
-
// 2. frameworks (depends on packages)
|
|
148
|
-
const frameworks = detectFrameworks(pkg.manifests, overrides?.detection);
|
|
149
|
-
|
|
150
|
-
// 3a. sourceDirs (depends on the language list discovered in packages)
|
|
151
|
-
const languages = Array.from(
|
|
152
|
-
new Set(pkg.manifests.map((m) => m.language))
|
|
153
|
-
) as SupportedLanguage[];
|
|
154
|
-
|
|
155
|
-
// P1-002: when the repo has a `javascript` manifest but NO `typescript`
|
|
156
|
-
// manifest, still glob `.ts`/`.tsx` for the javascript slot. This fixes
|
|
157
|
-
// plain-JS monorepos (e.g. turbo + next in a package.json with no
|
|
158
|
-
// `typescript` dep and no `tsconfig.json`) that contain `.tsx` files
|
|
159
|
-
// under `apps/*/`. Without this, `init --ci` falls back to the nonexistent
|
|
160
|
-
// `src/` and rolls back with a validation error.
|
|
161
|
-
const fallbackTsForJs =
|
|
162
|
-
languages.includes('javascript') && !languages.includes('typescript');
|
|
163
|
-
|
|
164
|
-
// 3b. run source-dir + monorepo detection in parallel (both pure fs).
|
|
165
|
-
const [sourceDirs, monorepo] = await Promise.all([
|
|
166
|
-
Promise.resolve(detectSourceDirs(projectRoot, languages, { fallbackTsForJs })),
|
|
167
|
-
Promise.resolve(detectMonorepo(projectRoot)),
|
|
168
|
-
]);
|
|
169
|
-
|
|
170
|
-
// 4a. domains
|
|
171
|
-
const domains = inferDomains(projectRoot, monorepo, sourceDirs);
|
|
172
|
-
|
|
173
|
-
// 4b. VR commands per language
|
|
174
|
-
const verificationCommands: Partial<Record<SupportedLanguage, VRCommandSet>> =
|
|
175
|
-
{};
|
|
176
|
-
for (const lang of languages) {
|
|
177
|
-
const fw: FrameworkInfo = frameworks[lang] ?? {
|
|
178
|
-
framework: null,
|
|
179
|
-
version: null,
|
|
180
|
-
test_framework: null,
|
|
181
|
-
orm: null,
|
|
182
|
-
ui_library: null,
|
|
183
|
-
router: null,
|
|
184
|
-
};
|
|
185
|
-
const dir = dominantDir(lang, sourceDirs, monorepo);
|
|
186
|
-
const userOverride = overrides?.verification?.[lang];
|
|
187
|
-
verificationCommands[lang] = getVRCommands(lang, fw, dir, userOverride);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const result: DetectionResult = {
|
|
191
|
-
projectRoot,
|
|
192
|
-
manifests: pkg.manifests,
|
|
193
|
-
frameworks,
|
|
194
|
-
sourceDirs,
|
|
195
|
-
monorepo,
|
|
196
|
-
domains,
|
|
197
|
-
verificationCommands,
|
|
198
|
-
warnings: pkg.warnings,
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
// P3-002: codebase introspector pass. Skipped when the caller opts out
|
|
202
|
-
// (the session-start hook at hooks/session-start.ts:272 passes
|
|
203
|
-
// `{ skipIntrospect: true }` to keep its 5s budget intact — see P4-006).
|
|
204
|
-
if (!options?.skipIntrospect) {
|
|
205
|
-
result.detected = introspect(result, projectRoot);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return result;
|
|
209
|
-
}
|
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026 Massu. All rights reserved.
|
|
2
|
-
// Licensed under BSL 1.1 - see LICENSE file for details.
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Canonical manifest registry — Plan 1.5.1 §3 deliverable.
|
|
6
|
-
*
|
|
7
|
-
* Single source-of-truth for "what manifest files we recognize and how we
|
|
8
|
-
* read them." Both `package-detector.ts` (init's framework-detection layer)
|
|
9
|
-
* and `adapters/runner.ts:buildDetectionSignals` (AST adapter signal layer)
|
|
10
|
-
* consume from THIS registry. Adding a new manifest type = ONE entry; both
|
|
11
|
-
* consumers automatically pick it up.
|
|
12
|
-
*
|
|
13
|
-
* Pre-registry state (1.5.0) had TWO parallel lists that drifted:
|
|
14
|
-
* - `package-detector.ts:MANIFEST_FILES` — 11 entries (legacy)
|
|
15
|
-
* - `runner.ts:buildDetectionSignals` — 9 manifest reads (extended Phase 7)
|
|
16
|
-
* Phoenix + ASP.NET were unreachable via `npx massu init` because their
|
|
17
|
-
* manifest files (mix.exs, *.csproj) were in the runner's list but missing
|
|
18
|
-
* from package-detector's list. CR-39 violation; closed by this registry.
|
|
19
|
-
*
|
|
20
|
-
* Per CR-46 Rule 0 self-attest #3 ("does this add an N+1th alias map?"):
|
|
21
|
-
* this REPLACES the duplicated lists with one canonical map. The drift-
|
|
22
|
-
* prevention test `manifest-registry-drift.test.ts` fails the build if a
|
|
23
|
-
* registry entry is consumed by only one of the two layers.
|
|
24
|
-
*
|
|
25
|
-
* Plan 1.5.1 reference:
|
|
26
|
-
* `~/massu-internal/docs/plans/2026-05-08-1.5.1-init-end-to-end.md`.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
import type { PackageManifest, DetectionWarning, SupportedLanguage } from './package-detector.ts';
|
|
30
|
-
import type { DetectionSignals } from './adapters/types.ts';
|
|
31
|
-
import * as parsers from './package-detector.ts';
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* The pattern by which the registry recognizes a manifest file:
|
|
35
|
-
* - exact filename: `'Gemfile'`, `'mix.exs'`, `'package.json'`
|
|
36
|
-
* - extension-glob: `'*.csproj'` (matches any file ending in `.csproj`)
|
|
37
|
-
* Only these two shapes are supported; arbitrary glob patterns are
|
|
38
|
-
* intentionally rejected to keep matching cheap and predictable.
|
|
39
|
-
*/
|
|
40
|
-
export type ManifestPattern = string;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Match a candidate filename against a registry pattern.
|
|
44
|
-
* Returns true if `name` matches `pattern`.
|
|
45
|
-
*/
|
|
46
|
-
export function matchManifestPattern(name: string, pattern: ManifestPattern): boolean {
|
|
47
|
-
if (pattern.startsWith('*')) {
|
|
48
|
-
const suffix = pattern.slice(1);
|
|
49
|
-
if (suffix.includes('*')) {
|
|
50
|
-
throw new Error(
|
|
51
|
-
`[manifest-registry] pattern "${pattern}" has more than one wildcard. ` +
|
|
52
|
-
`Only "*.<ext>" extension-globs are supported.`,
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
return name.endsWith(suffix);
|
|
56
|
-
}
|
|
57
|
-
return name === pattern;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Parser function signature — matches the existing parse* fns in
|
|
62
|
-
* package-detector.ts. Returns null on file-not-found or parse failure
|
|
63
|
-
* (with a warning pushed to `warnings`).
|
|
64
|
-
*/
|
|
65
|
-
export type ManifestParser = (
|
|
66
|
-
path: string,
|
|
67
|
-
directory: string,
|
|
68
|
-
root: string,
|
|
69
|
-
warnings: DetectionWarning[],
|
|
70
|
-
) => PackageManifest | null;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Single registry entry. One per manifest type.
|
|
74
|
-
*/
|
|
75
|
-
export interface ManifestEntry {
|
|
76
|
-
/** Recognition pattern (see `ManifestPattern`). */
|
|
77
|
-
pattern: ManifestPattern;
|
|
78
|
-
/** Canonical manifest-type tag (matches `PackageManifest.manifestType`). */
|
|
79
|
-
manifestType: PackageManifest['manifestType'];
|
|
80
|
-
/** Default language this manifest implies. */
|
|
81
|
-
language: SupportedLanguage;
|
|
82
|
-
/** Runtime family hint. */
|
|
83
|
-
runtime: string;
|
|
84
|
-
/** Function that reads + parses the file into a `PackageManifest`. */
|
|
85
|
-
parse: ManifestParser;
|
|
86
|
-
/**
|
|
87
|
-
* The DetectionSignals key the runner uses to expose this manifest's
|
|
88
|
-
* contents to AST adapters. `null` when this manifest doesn't surface
|
|
89
|
-
* to the AST tier (e.g., requirements.txt is captured via pyprojectToml
|
|
90
|
-
* sibling already; Package.swift has no AST adapter consumer yet).
|
|
91
|
-
*/
|
|
92
|
-
signalKey: keyof DetectionSignals | null;
|
|
93
|
-
/**
|
|
94
|
-
* Shape the runner stores under `signalKey`. Drives whether the runner
|
|
95
|
-
* calls `tryReadString` (string) or `tryReadToml` (toml) or
|
|
96
|
-
* `tryReadJson` (json) when populating signals. Ignored when
|
|
97
|
-
* `signalKey === null`.
|
|
98
|
-
*/
|
|
99
|
-
signalShape: 'string' | 'toml' | 'json';
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* The canonical registry — the SINGLE source-of-truth for "what manifests
|
|
104
|
-
* we recognize."
|
|
105
|
-
*
|
|
106
|
-
* Lazy initializer: package-detector.ts re-exports the parsers we
|
|
107
|
-
* reference here, so eager top-level evaluation would risk an ESM
|
|
108
|
-
* circular-import undefined-symbol. Resolution: build the registry on
|
|
109
|
-
* first call (after both modules' top-level evaluations have completed).
|
|
110
|
-
*
|
|
111
|
-
* Adding a new manifest type:
|
|
112
|
-
* 1. Author a new `parseXxx()` function in `package-detector.ts`.
|
|
113
|
-
* 2. Add an entry to MANIFEST_REGISTRY referencing it.
|
|
114
|
-
* 3. (If needed) extend `SupportedLanguage` and
|
|
115
|
-
* `PackageManifest.manifestType` unions.
|
|
116
|
-
* 4. Add the new signal field to `DetectionSignals` if the AST adapter
|
|
117
|
-
* pipeline needs to read it.
|
|
118
|
-
* 5. The drift-prevention test will fail until both consumers see the
|
|
119
|
-
* new entry.
|
|
120
|
-
*/
|
|
121
|
-
let _registryCache: ManifestEntry[] | null = null;
|
|
122
|
-
|
|
123
|
-
export function getManifestRegistry(): ManifestEntry[] {
|
|
124
|
-
if (_registryCache !== null) return _registryCache;
|
|
125
|
-
_registryCache = [
|
|
126
|
-
{
|
|
127
|
-
pattern: 'package.json',
|
|
128
|
-
manifestType: 'package.json',
|
|
129
|
-
language: 'typescript',
|
|
130
|
-
runtime: 'node',
|
|
131
|
-
parse: parsers.parsePackageJson,
|
|
132
|
-
signalKey: 'packageJson',
|
|
133
|
-
signalShape: 'json',
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
pattern: 'pyproject.toml',
|
|
137
|
-
manifestType: 'pyproject.toml',
|
|
138
|
-
language: 'python',
|
|
139
|
-
runtime: 'python3',
|
|
140
|
-
parse: parsers.parsePyproject,
|
|
141
|
-
signalKey: 'pyprojectToml',
|
|
142
|
-
signalShape: 'toml',
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
pattern: 'requirements.txt',
|
|
146
|
-
manifestType: 'requirements.txt',
|
|
147
|
-
language: 'python',
|
|
148
|
-
runtime: 'python3',
|
|
149
|
-
parse: parsers.parseRequirementsTxt,
|
|
150
|
-
// Captured via pyprojectToml sibling already; no separate signal.
|
|
151
|
-
signalKey: null,
|
|
152
|
-
signalShape: 'string',
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
pattern: 'Pipfile',
|
|
156
|
-
manifestType: 'Pipfile',
|
|
157
|
-
language: 'python',
|
|
158
|
-
runtime: 'python3',
|
|
159
|
-
parse: parsers.parsePipfile,
|
|
160
|
-
// Captured via pyprojectToml sibling already; no separate signal.
|
|
161
|
-
signalKey: null,
|
|
162
|
-
signalShape: 'string',
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
pattern: 'Cargo.toml',
|
|
166
|
-
manifestType: 'Cargo.toml',
|
|
167
|
-
language: 'rust',
|
|
168
|
-
runtime: 'cargo',
|
|
169
|
-
parse: parsers.parseCargoToml,
|
|
170
|
-
signalKey: 'cargoToml',
|
|
171
|
-
signalShape: 'toml',
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
pattern: 'Package.swift',
|
|
175
|
-
manifestType: 'Package.swift',
|
|
176
|
-
language: 'swift',
|
|
177
|
-
runtime: 'xcode',
|
|
178
|
-
parse: parsers.parsePackageSwift,
|
|
179
|
-
// No AST adapter consumer yet (swift-swiftui doesn't need it).
|
|
180
|
-
signalKey: null,
|
|
181
|
-
signalShape: 'string',
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
pattern: 'go.mod',
|
|
185
|
-
manifestType: 'go.mod',
|
|
186
|
-
language: 'go',
|
|
187
|
-
runtime: 'go',
|
|
188
|
-
parse: parsers.parseGoMod,
|
|
189
|
-
signalKey: 'goMod',
|
|
190
|
-
signalShape: 'string',
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
pattern: 'pom.xml',
|
|
194
|
-
manifestType: 'pom.xml',
|
|
195
|
-
language: 'java',
|
|
196
|
-
runtime: 'jvm',
|
|
197
|
-
parse: parsers.parsePomXml,
|
|
198
|
-
signalKey: 'pomXml',
|
|
199
|
-
signalShape: 'string',
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
pattern: 'build.gradle',
|
|
203
|
-
manifestType: 'build.gradle',
|
|
204
|
-
language: 'java',
|
|
205
|
-
runtime: 'jvm',
|
|
206
|
-
parse: parsers.parseBuildGradle,
|
|
207
|
-
signalKey: 'gradleBuild',
|
|
208
|
-
signalShape: 'string',
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
pattern: 'build.gradle.kts',
|
|
212
|
-
manifestType: 'build.gradle',
|
|
213
|
-
language: 'java',
|
|
214
|
-
runtime: 'jvm',
|
|
215
|
-
parse: parsers.parseBuildGradle,
|
|
216
|
-
signalKey: 'gradleBuild',
|
|
217
|
-
signalShape: 'string',
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
pattern: 'Gemfile',
|
|
221
|
-
manifestType: 'Gemfile',
|
|
222
|
-
language: 'ruby',
|
|
223
|
-
runtime: 'ruby',
|
|
224
|
-
parse: parsers.parseGemfile,
|
|
225
|
-
signalKey: 'gemfile',
|
|
226
|
-
signalShape: 'string',
|
|
227
|
-
},
|
|
228
|
-
// Plan 1.5.1 — closes CR-39 violation (1.5.0 init failed for Phoenix
|
|
229
|
-
// + ASP.NET fixtures). Both rely on AST adapters that already work
|
|
230
|
-
// in introspect; the gap was solely package-detector unaware of the
|
|
231
|
-
// manifest filenames.
|
|
232
|
-
{
|
|
233
|
-
pattern: 'mix.exs',
|
|
234
|
-
manifestType: 'mix.exs',
|
|
235
|
-
language: 'elixir',
|
|
236
|
-
runtime: 'beam',
|
|
237
|
-
parse: parsers.parseMixExs,
|
|
238
|
-
signalKey: 'mixExs',
|
|
239
|
-
signalShape: 'string',
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
pattern: '*.csproj',
|
|
243
|
-
manifestType: '*.csproj',
|
|
244
|
-
language: 'csharp',
|
|
245
|
-
runtime: 'dotnet',
|
|
246
|
-
parse: parsers.parseCsproj,
|
|
247
|
-
signalKey: 'csproj',
|
|
248
|
-
signalShape: 'string',
|
|
249
|
-
},
|
|
250
|
-
];
|
|
251
|
-
return _registryCache;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Filename list for direct iteration callers (e.g., the existing
|
|
256
|
-
* package-detector.ts `MANIFEST_FILES` const). Derived from the registry
|
|
257
|
-
* so it stays in lockstep automatically.
|
|
258
|
-
*/
|
|
259
|
-
export function getManifestPatterns(): ManifestPattern[] {
|
|
260
|
-
return getManifestRegistry().map((e) => e.pattern);
|
|
261
|
-
}
|