@thomasminh1995/depverdict 0.6.0-alpha.1
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/LICENSE +21 -0
- package/README.md +518 -0
- package/bin/depverdict.js +7 -0
- package/bin/upgradelens.js +7 -0
- package/docs/GR-01-Semantic-Grounding-Failure-Analysis.md +309 -0
- package/docs/GR-02-Versioned-Action-Evaluation-Criteria.md +187 -0
- package/docs/GR-03-Extractive-Contract-Safety-Experiment.md +242 -0
- package/docs/GR-04-Versioned-Production-Extractive-Contract.md +154 -0
- package/docs/IA-01-Repository-Usage-Discovery.md +122 -0
- package/docs/IA-02-Repository-Impact-Analysis.md +118 -0
- package/docs/IA-03-Repository-Impact-Evidence.md +160 -0
- package/docs/IA-04-CLI-Orchestration.md +235 -0
- package/docs/IA-05-Real-Provider-Validation.md +235 -0
- package/docs/IA-05-VinGrade-Validation.md +339 -0
- package/docs/MVP-01.md +48 -0
- package/docs/MVP-02-Architecture.md +536 -0
- package/docs/MVP-02-CLI-HTTP-Runtime.md +50 -0
- package/docs/MVP-02-HTTP-Lifecycle.md +37 -0
- package/docs/MVP-02-Knowledge-Manifest-Generation.md +75 -0
- package/docs/MVP-02-Knowledge-Manifest.md +279 -0
- package/docs/MVP-02-Knowledge-Research-Orchestration.md +62 -0
- package/docs/MVP-02-Knowledge-Store.md +87 -0
- package/docs/MVP-02-PyPI-Registry-Adapter.md +97 -0
- package/docs/MVP-02-Research-Planning.md +196 -0
- package/docs/MVP-02-Source-Provenance.md +81 -0
- package/docs/MVP-02-npm-Registry-Adapter.md +99 -0
- package/docs/RR-01-End-to-End-and-Real-Provider-Validation.md +393 -0
- package/docs/RR-01-RERUN-Extractive-Contract-Validation.md +566 -0
- package/docs/RR-02-Full-Product-Workflow-and-Developer-CLI-UX-Review.md +35 -0
- package/docs/RR02-FIX-01-Persistent-Qualification-Resolution.md +32 -0
- package/docs/RR02-FIX-02-Stage-aware-CLI-Progress-and-Heartbeat.md +28 -0
- package/docs/RR02-FIX-03-npm-Capture-Evidence-Exclusion.md +33 -0
- package/docs/RR02-FIX-03A-Complete-Package-Exclusion-and-Evidence-Commit.md +223 -0
- package/docs/RR02-FIX-04-Event-loop-safe-Heartbeat.md +393 -0
- package/docs/RR02-FIX-05-Materialize-Persisted-Qualification.md +207 -0
- package/docs/RR02-RERUN-CLI-Qualification-Progress-UX-and-Package-Validation.md +342 -0
- package/docs/VinGrade-MVP-02-Validation.md +480 -0
- package/docs/VinGrade-RC02-Live-Validation.md +273 -0
- package/docs/ai-capability-discovery.md +573 -0
- package/docs/ai-engineering-production-readiness.md +390 -0
- package/docs/ai-engineering-review.md +251 -0
- package/docs/ai-runtime-governance-discovery.md +754 -0
- package/docs/architecture-overview.md +78 -0
- package/docs/cli-progress.md +111 -0
- package/docs/decisions/diff-01-brand-distribution-identity.md +450 -0
- package/docs/decisions/diff-02-identity-compatibility-contract.md +274 -0
- package/docs/decisions/diff-03-repository-docs-community-migration.md +165 -0
- package/docs/decisions/diff-04-release-evidence-gap-acceptance.md +110 -0
- package/docs/discovery/mvp-05-ai-migration-planning-discovery.md +350 -0
- package/docs/gateway-runtime-discovery.md +614 -0
- package/docs/live-ai-validation.md +299 -0
- package/docs/migration-planning-qualification-resolution.md +99 -0
- package/docs/migrations/upgradelens-to-depverdict.md +97 -0
- package/docs/mp-r03-deterministic-upgrade-decision-architecture.md +135 -0
- package/docs/mp-r04-evidence-bounded-migration-handoff-architecture.md +116 -0
- package/docs/mp-r05-product-completion-and-decision-first-cli-architecture.md +162 -0
- package/docs/mvp-05-deterministic-context-runtime.md +127 -0
- package/docs/mvp-05-migration-checklist-contract.md +166 -0
- package/docs/mvp-05-migration-checklist-orchestration.md +105 -0
- package/docs/mvp-05-migration-evaluation-and-qualification.md +135 -0
- package/docs/mvp-05-provider-neutral-generator.md +79 -0
- package/docs/ollama-local-smoke-validation.md +156 -0
- package/docs/openai-compatible-runtime-discovery.md +789 -0
- package/docs/openrouter-one-dependency-validation.md +205 -0
- package/docs/oss-02-package-guard-hardening-architecture.md +131 -0
- package/docs/oss-04-public-ci-package-metadata-architecture.md +142 -0
- package/docs/package-content-policy.md +98 -0
- package/docs/releases/v0.5.0-technical-preview.md +114 -0
- package/docs/releases/v0.6.0-alpha.1-depverdict-preview.md +101 -0
- package/docs/reviews/diff-02-identity-contract-compatibility.md +413 -0
- package/docs/reviews/diff-03-repository-docs-community-migration.md +364 -0
- package/docs/reviews/diff-04-depverdict-distribution-identity-readiness-rereview.md +453 -0
- package/docs/reviews/diff-04-fix-post-rename-identity-release-remediation.md +310 -0
- package/docs/reviews/diff-05-final-preview-distribution-qualification.md +561 -0
- package/docs/reviews/mvp-05-final-product-value-workflow-rereview.md +471 -0
- package/docs/reviews/mvp-05-product-workflow-review.md +605 -0
- package/docs/reviews/oss-01-duplicate-artifact-investigation-cleanup.md +411 -0
- package/docs/reviews/oss-02-package-guard-hardening.md +303 -0
- package/docs/reviews/oss-03-community-scaffolding.md +378 -0
- package/docs/reviews/oss-04-public-ci-package-metadata.md +439 -0
- package/docs/reviews/oss-05-technical-preview-qualification.md +482 -0
- package/docs/reviews/upgradelens-vs-upgradedepdetective-source-comparison.md +355 -0
- package/docs/reviews/v0.5.0-pre-release-smoke.md +263 -0
- package/docs/reviews/v0.5.0-version-bump-release-verification.md +306 -0
- package/docs/runtime-contract-discovery.md +521 -0
- package/docs/structured-output-compatibility-report.md +100 -0
- package/docs/ts-fix-01-exact-duplicate-occurrence-target-selection-architecture.md +111 -0
- package/docs/version-analysis-architecture.md +827 -0
- package/eval/README.md +86 -0
- package/eval/datasets/generic/declared-constraint.json +59 -0
- package/eval/datasets/generic/evidence-conflict.json +73 -0
- package/eval/datasets/generic/major-breaking-release.json +66 -0
- package/eval/datasets/generic/missing-evidence.json +46 -0
- package/eval/datasets/generic/patch-release-low.json +59 -0
- package/eval/datasets/node/axios-patch-low.json +59 -0
- package/eval/datasets/node/react-major-breaking.json +66 -0
- package/eval/datasets/node/react-minor-compatibility.json +66 -0
- package/eval/datasets/python/fastapi-deprecation.json +66 -0
- package/eval/datasets/python/pydantic-major-breaking.json +66 -0
- package/eval/migration-planning/golden-dataset-v2.json +306 -0
- package/eval/migration-planning/golden-dataset.json +214 -0
- package/eval/schemas/expected-result.schema.json +88 -0
- package/eval/schemas/golden-case.schema.json +181 -0
- package/package.json +57 -0
- package/schemas/ai-scorecard.schema.json +132 -0
- package/schemas/benchmark-report.schema.json +189 -0
- package/schemas/benchmark.schema.json +55 -0
- package/schemas/capability-profile.schema.json +44 -0
- package/schemas/conformance-report.schema.json +150 -0
- package/schemas/deployment-profile.schema.json +64 -0
- package/schemas/evaluation-report.schema.json +158 -0
- package/schemas/knowledge-evidence-bundle.schema.json +150 -0
- package/schemas/knowledge-manifest.schema.json +548 -0
- package/schemas/metrics.schema.json +178 -0
- package/schemas/migration-checklist-extractive-candidate.schema.json +42 -0
- package/schemas/migration-checklist.schema.json +706 -0
- package/schemas/migration-evaluation-dataset-v2.schema.json +208 -0
- package/schemas/migration-evaluation-dataset.schema.json +204 -0
- package/schemas/migration-planning-qualification-record.schema.json +234 -0
- package/schemas/project-manifest.schema.json +308 -0
- package/schemas/qualification-record.schema.json +56 -0
- package/schemas/repository-impact-evidence.schema.json +232 -0
- package/schemas/repository-impact.schema.json +202 -0
- package/schemas/upgrade-decision.schema.json +273 -0
- package/schemas/usage-index.schema.json +179 -0
- package/schemas/version-analysis.schema.json +449 -0
- package/src/ai-runtime-debug.js +325 -0
- package/src/ai-runtime-error.js +42 -0
- package/src/ai-runtime.js +174 -0
- package/src/ai-scorecard.js +204 -0
- package/src/ai-version-analysis.js +484 -0
- package/src/artifact-root-compatibility.js +91 -0
- package/src/benchmark-report.js +111 -0
- package/src/benchmark-runner.js +191 -0
- package/src/canonical-json.js +69 -0
- package/src/cli.js +1299 -0
- package/src/conformance-report.js +158 -0
- package/src/conformance-runner.js +253 -0
- package/src/constants.js +73 -0
- package/src/cooperative-scheduler.js +79 -0
- package/src/dependencies.js +44 -0
- package/src/dependency-ai-context.js +625 -0
- package/src/detectors.js +253 -0
- package/src/discovery.js +234 -0
- package/src/ecosystem-version-adapter.js +294 -0
- package/src/environment-compatibility.js +77 -0
- package/src/evaluation-comparator.js +158 -0
- package/src/evaluation-report.js +76 -0
- package/src/evaluation-runner.js +248 -0
- package/src/evidence-source-adapter.js +472 -0
- package/src/files.js +89 -0
- package/src/governance-diagnostics.js +64 -0
- package/src/governance-loader.js +63 -0
- package/src/governance-metadata.js +346 -0
- package/src/governance-validator.js +360 -0
- package/src/http/bounded-fetch.js +278 -0
- package/src/http/cli-http-runtime.js +44 -0
- package/src/impact/input-loader.js +157 -0
- package/src/impact/matcher.js +40 -0
- package/src/impact/repository-impact.js +199 -0
- package/src/impact/runtime.js +24 -0
- package/src/impact/status.js +62 -0
- package/src/impact/writer.js +30 -0
- package/src/impact-evidence/input-loader.js +202 -0
- package/src/impact-evidence/repository-impact-evidence.js +234 -0
- package/src/impact-evidence/runtime.js +16 -0
- package/src/impact-evidence/writer.js +30 -0
- package/src/index.js +563 -0
- package/src/installed-version-baseline.js +196 -0
- package/src/knowledge-cache.js +324 -0
- package/src/knowledge-evidence-bundle.js +101 -0
- package/src/knowledge-evidence-producer.js +233 -0
- package/src/knowledge-manifest-builder.js +188 -0
- package/src/knowledge-manifest-writer.js +32 -0
- package/src/knowledge-manifest.js +255 -0
- package/src/knowledge-research.js +615 -0
- package/src/metrics-engine.js +205 -0
- package/src/migration-checklist/ai-candidate.js +320 -0
- package/src/migration-checklist/assembler.js +37 -0
- package/src/migration-checklist/context-runtime.js +828 -0
- package/src/migration-checklist/evaluation/action-criteria.js +244 -0
- package/src/migration-checklist/evaluation/comparator-v2.js +332 -0
- package/src/migration-checklist/evaluation/comparator.js +279 -0
- package/src/migration-checklist/evaluation/dataset-v2.js +227 -0
- package/src/migration-checklist/evaluation/dataset.js +336 -0
- package/src/migration-checklist/evaluation/extractive-fixtures-v2.js +148 -0
- package/src/migration-checklist/evaluation/metrics-v2.js +226 -0
- package/src/migration-checklist/evaluation/metrics.js +158 -0
- package/src/migration-checklist/evaluation/qualification-v2.js +321 -0
- package/src/migration-checklist/evaluation/qualification.js +239 -0
- package/src/migration-checklist/evaluation/runner-v2.js +294 -0
- package/src/migration-checklist/evaluation/runner.js +194 -0
- package/src/migration-checklist/evaluation/scorecard-v2.js +106 -0
- package/src/migration-checklist/evaluation/scorecard.js +86 -0
- package/src/migration-checklist/extractive-candidate.js +166 -0
- package/src/migration-checklist/extractive-prompt.js +62 -0
- package/src/migration-checklist/generator.js +702 -0
- package/src/migration-checklist/grounding-policy.js +117 -0
- package/src/migration-checklist/input-loader.js +613 -0
- package/src/migration-checklist/migration-checklist.js +635 -0
- package/src/migration-checklist/presentation.js +292 -0
- package/src/migration-checklist/progress.js +96 -0
- package/src/migration-checklist/prompt.js +83 -0
- package/src/migration-checklist/qualification-guard.js +462 -0
- package/src/migration-checklist/qualification-resolution.js +122 -0
- package/src/migration-checklist/qualification-store.js +225 -0
- package/src/migration-checklist/runtime.js +205 -0
- package/src/migration-checklist/verification.js +134 -0
- package/src/migration-checklist/writer.js +35 -0
- package/src/openai-compatible-provider.js +451 -0
- package/src/orchestration/failure-log.js +32 -0
- package/src/orchestration/pipeline.js +200 -0
- package/src/orchestration/progress-events.js +337 -0
- package/src/orchestration/progress-reporter.js +131 -0
- package/src/orchestration/text-writer.js +22 -0
- package/src/portable.js +13 -0
- package/src/product-completion.js +249 -0
- package/src/project-manifest-input.js +90 -0
- package/src/project-manifest.js +141 -0
- package/src/python-requirements.js +137 -0
- package/src/registry/npm-packument.js +256 -0
- package/src/registry/npm-registry-adapter.js +262 -0
- package/src/registry/pypi-project.js +300 -0
- package/src/registry/pypi-registry-adapter.js +235 -0
- package/src/registry/sanitize-registry-body.js +51 -0
- package/src/renderers/console.js +160 -0
- package/src/renderers/impact-presentation.js +278 -0
- package/src/renderers/markdown.js +172 -0
- package/src/research-plan.js +455 -0
- package/src/runtime-conformance.js +275 -0
- package/src/source-provenance.js +393 -0
- package/src/source-url.js +62 -0
- package/src/structured-output-schema.js +66 -0
- package/src/target-selector.js +306 -0
- package/src/upgrade-decision/input-loader.js +107 -0
- package/src/upgrade-decision/presentation.js +43 -0
- package/src/upgrade-decision/runtime.js +21 -0
- package/src/upgrade-decision/upgrade-decision.js +626 -0
- package/src/upgrade-decision/writer.js +30 -0
- package/src/usage/analyzer-registry.js +63 -0
- package/src/usage/coverage.js +116 -0
- package/src/usage/input-loader.js +139 -0
- package/src/usage/js/analyzer.js +240 -0
- package/src/usage/js/parser.js +21 -0
- package/src/usage/runtime.js +187 -0
- package/src/usage/scope.js +44 -0
- package/src/usage/source-files.js +50 -0
- package/src/usage/usage-index.js +217 -0
- package/src/usage/writer.js +31 -0
- package/src/version-analysis-loader.js +203 -0
- package/src/version-analysis-manifest.js +314 -0
- package/src/version-analysis-writer.js +30 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# MVP-02 Research Planning
|
|
2
|
+
|
|
3
|
+
MVP-02-02 creates the deterministic bridge between an MVP-01 Project Manifest and later knowledge research. It reads a Project Manifest once, validates it, fingerprints its exact bytes, and produces an internal `ResearchPlan`.
|
|
4
|
+
|
|
5
|
+
The Research Plan is internal. The [Knowledge Manifest](MVP-02-Knowledge-Manifest.md) is the portable public artifact produced only after later MVP-02 collection work completes.
|
|
6
|
+
|
|
7
|
+
## Boundary
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Project Manifest bytes
|
|
11
|
+
│
|
|
12
|
+
▼
|
|
13
|
+
Parse + validate + exact-byte SHA-256
|
|
14
|
+
│
|
|
15
|
+
▼
|
|
16
|
+
Extract dependency occurrences
|
|
17
|
+
│
|
|
18
|
+
▼
|
|
19
|
+
Resolve public npm/PyPI identities
|
|
20
|
+
│
|
|
21
|
+
▼
|
|
22
|
+
Group + canonicalize + validate
|
|
23
|
+
│
|
|
24
|
+
▼
|
|
25
|
+
Internal Research Plan
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This stage does not scan the repository. It does not read `package.json`, `requirements.txt`, lockfiles, or source files. It performs no network request, registry lookup, cache operation, source resolution, version comparison, or Knowledge Manifest generation.
|
|
29
|
+
|
|
30
|
+
## Input and lineage
|
|
31
|
+
|
|
32
|
+
`loadProjectManifestInput` accepts either:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
await loadProjectManifestInput('/path/to/project-manifest.json');
|
|
36
|
+
|
|
37
|
+
await loadProjectManifestInput({
|
|
38
|
+
bytes: exactManifestBytes,
|
|
39
|
+
artifact: '.upgradelens/project-manifest.json'
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The file form reads the manifest once. The byte form is intended for controlled tests and internal callers. In both cases UpgradeLens hashes the exact byte sequence with SHA-256 before parsing it. It never hashes a reserialized JavaScript object.
|
|
44
|
+
|
|
45
|
+
The resulting lineage is compatible with the future Knowledge Manifest input contract:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"projectManifest": {
|
|
50
|
+
"schemaVersion": "2.0.0",
|
|
51
|
+
"artifact": ".upgradelens/project-manifest.json",
|
|
52
|
+
"artifactDigest": "sha256:<64 lowercase hexadecimal characters>",
|
|
53
|
+
"repository": { "name": "example-project", "root": "." }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Artifact paths must be portable repository-relative paths. Absolute paths, drive-qualified paths, backslashes, and parent traversal are rejected. Invalid JSON, a non-`2.0.0` schema version, JSON Schema violations, and Project Manifest dependency-summary invariant violations are fatal input errors; they never produce a partial plan.
|
|
59
|
+
|
|
60
|
+
## Project Manifest validation
|
|
61
|
+
|
|
62
|
+
The loader uses `schemas/project-manifest.schema.json` with Ajv Draft 2020-12 strict mode. It also validates runtime relationships relevant to MVP-01 dependency inventories:
|
|
63
|
+
|
|
64
|
+
- project, workspace, dependency-manifest paths are portable;
|
|
65
|
+
- project and ecosystem summary counts match projects;
|
|
66
|
+
- parsed dependency declaration, unique, and duplicate counts match inventory records;
|
|
67
|
+
- Node `byType` counts match Node dependency types;
|
|
68
|
+
- unsupported or failed dependency parsers have no inventory entries.
|
|
69
|
+
|
|
70
|
+
The planner canonicalizes its own output, so a valid input with projects or dependencies in a different array order still produces the same package plan.
|
|
71
|
+
|
|
72
|
+
## Internal Research Plan
|
|
73
|
+
|
|
74
|
+
The internal plan is serializable for debugging and tests but is not written by default and has no public JSON Schema:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"planVersion": "1",
|
|
79
|
+
"input": { "projectManifest": {} },
|
|
80
|
+
"summary": {
|
|
81
|
+
"inputProjectCount": 2,
|
|
82
|
+
"inputOccurrenceCount": 47,
|
|
83
|
+
"researchableOccurrenceCount": 46,
|
|
84
|
+
"uniqueResearchPackageCount": 45,
|
|
85
|
+
"invalidOccurrenceCount": 1,
|
|
86
|
+
"unsupportedOccurrenceCount": 0
|
|
87
|
+
},
|
|
88
|
+
"packages": [],
|
|
89
|
+
"invalidOccurrences": [],
|
|
90
|
+
"unsupported": [],
|
|
91
|
+
"warnings": []
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`planVersion` is independent from both Project Manifest and Knowledge Manifest schema versions. The plan has no timestamp, network/cache state, store detail, credentials, source content, or registry metadata.
|
|
96
|
+
|
|
97
|
+
`inputOccurrenceCount` means every dependency declaration present in the valid Project Manifest inventories that planning examines: researchable and invalid Node/Python declarations plus declarations from unsupported ecosystems. Duplicate and multi-project declarations count separately. Parsed Node/Python inventories provide those records today; other ecosystems only contribute when a future Project Manifest contains an inventory for them.
|
|
98
|
+
|
|
99
|
+
## Research identity
|
|
100
|
+
|
|
101
|
+
MVP-02-02 supports only these public lookup identities:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
node → npm:<normalized-name>
|
|
105
|
+
python → pypi:<normalized-name>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Normal npm names and scoped names such as `@vitejs/plugin-react` are valid. Python identities use the existing PEP 503-style normalization already used by MVP-01: lowercase and collapse runs of `.`, `_`, and `-` to `-`.
|
|
109
|
+
|
|
110
|
+
Each research package is package-centric:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"id": "npm:react",
|
|
115
|
+
"registry": "npm",
|
|
116
|
+
"ecosystem": "node",
|
|
117
|
+
"normalizedName": "react",
|
|
118
|
+
"observedDeclaredNames": ["react"],
|
|
119
|
+
"occurrences": []
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Researchable occurrences group only by `(registry, normalizedName)`. Grouping preserves every declaration, declared version/reference, dependency type, manifest path, project ID, and project path. It keeps duplicate declarations and declarations from separate projects; only the external lookup identity is deduplicated.
|
|
124
|
+
|
|
125
|
+
Node ranges, tags, and other ordinary npm version declarations remain opaque. Python version declarations remain opaque as well: MVP-02-02 does not parse SemVer or PEP 440.
|
|
126
|
+
|
|
127
|
+
## Eligibility and invalid references
|
|
128
|
+
|
|
129
|
+
Node dependencies are researchable when their normalized name is a public npm name and their declaration is not a local path, workspace-only reference, file/link reference, npm alias, URL, Git reference, or similar unsupported reference.
|
|
130
|
+
|
|
131
|
+
Python dependencies are researchable when they have an explicit named PyPI identity. A named direct reference such as `package-name @ https://…` is researchable using `package-name`. Unnamed URLs, unnamed Git references, and local editable paths without an explicit name are not guessed into a registry identity.
|
|
132
|
+
|
|
133
|
+
Invalid Node/Python occurrences remain in `invalidOccurrences` with one stable reason:
|
|
134
|
+
|
|
135
|
+
- `empty-name`
|
|
136
|
+
- `invalid-npm-name`
|
|
137
|
+
- `invalid-pypi-name`
|
|
138
|
+
- `unnamed-direct-reference`
|
|
139
|
+
- `local-path-reference`
|
|
140
|
+
- `unsupported-reference`
|
|
141
|
+
|
|
142
|
+
Each invalid occurrence produces an internal `INVALID_PACKAGE_REFERENCE` warning. URL user information, query strings, fragments, and local paths are sanitized before the Research Plan is serialized. UpgradeLens never guesses a package name from a URL, Git repository, path, or name similarity.
|
|
143
|
+
|
|
144
|
+
## Unsupported ecosystems
|
|
145
|
+
|
|
146
|
+
Java, .NET, Go, Rust, Ruby, PHP, AL, and other non-Node/non-Python dependencies are outside MVP-02-02. Their declarations are aggregated by ecosystem rather than copied into package records:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"ecosystem": "java",
|
|
151
|
+
"projectIds": ["java:backend"],
|
|
152
|
+
"occurrenceCount": 12
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
An ecosystem with one or more such declarations receives one internal `UNSUPPORTED_RESEARCH_ECOSYSTEM` warning. Valid dependencies from unsupported ecosystems are not reported as `INVALID_PACKAGE_REFERENCE`. No new public Knowledge Manifest warning code is introduced by this internal planning detail.
|
|
157
|
+
|
|
158
|
+
## Determinism and invariants
|
|
159
|
+
|
|
160
|
+
The plan uses code-unit lexical order:
|
|
161
|
+
|
|
162
|
+
1. packages by ID;
|
|
163
|
+
2. observed names lexically;
|
|
164
|
+
3. occurrences by project ID, manifest, dependency type, declared name, then declared version (`null` sorts as an empty string);
|
|
165
|
+
4. invalid occurrences by the same key and then reason;
|
|
166
|
+
5. unsupported records by ecosystem and their project IDs lexically;
|
|
167
|
+
6. warnings by scope, code, and message.
|
|
168
|
+
|
|
169
|
+
`createResearchPlan` calls `validateResearchPlan` before returning. The validator fails fast when an internal implementation bug violates any of these relationships:
|
|
170
|
+
|
|
171
|
+
- unique package count equals package records;
|
|
172
|
+
- package occurrence total equals researchable occurrence count;
|
|
173
|
+
- invalid and unsupported counts equal their records;
|
|
174
|
+
- researchable + invalid + unsupported equals input occurrences;
|
|
175
|
+
- package IDs match registry and normalized name;
|
|
176
|
+
- package occurrences match their package identity;
|
|
177
|
+
- warning references correspond to invalid or unsupported records;
|
|
178
|
+
- IDs are unique, references are portable, output is sorted, and serialized values contain no URL credentials.
|
|
179
|
+
|
|
180
|
+
## Public API
|
|
181
|
+
|
|
182
|
+
The package exports only the planning entry points required by later MVP-02 implementation:
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
import {
|
|
186
|
+
loadProjectManifestInput,
|
|
187
|
+
createResearchPlan,
|
|
188
|
+
validateResearchPlan
|
|
189
|
+
} from 'upgradelens';
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Call `loadProjectManifestInput` first, pass its result to `createResearchPlan`, and use `validateResearchPlan` to fail fast when inspecting or constructing an internal plan.
|
|
193
|
+
|
|
194
|
+
## Deferred work
|
|
195
|
+
|
|
196
|
+
This task deliberately does not implement npm/PyPI requests, GitHub API use, source resolution, Knowledge Store persistence, cache behavior, Knowledge Manifest creation, latest-version lookup, release metadata, version analysis, AI/LLM behavior, MCP, agent runtime, or a new CLI command.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# MVP-02 Source Provenance Resolution
|
|
2
|
+
|
|
3
|
+
MVP-02-06 converts URL metadata already returned by the npm and PyPI registry adapters into a small, deterministic internal source graph. It does not fetch, crawl, or verify source content. It only structures and attributes source metadata already collected from registries.
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
npm / PyPI registry result
|
|
7
|
+
│
|
|
8
|
+
▼
|
|
9
|
+
Extract source candidates
|
|
10
|
+
│
|
|
11
|
+
▼
|
|
12
|
+
Canonicalize and classify public URLs
|
|
13
|
+
│
|
|
14
|
+
▼
|
|
15
|
+
Merge compatible candidates per package
|
|
16
|
+
│
|
|
17
|
+
▼
|
|
18
|
+
Attach provenance, trust, and conflicts
|
|
19
|
+
│
|
|
20
|
+
▼
|
|
21
|
+
Internal source graph
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For example:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
npm Registry
|
|
28
|
+
│
|
|
29
|
+
├── documentation candidate ──► npm:react:documentation:<sha256>
|
|
30
|
+
└── repository candidate ─────► npm:react:repository:<sha256>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The source graph is internal composition data. It is not a Knowledge Manifest, a cache format, or a graph database. Later orchestration can assemble compatible source records into the versioned Knowledge Manifest without exposing adapter payloads, source-candidate field paths, or cache details.
|
|
34
|
+
|
|
35
|
+
## URL evidence and provenance
|
|
36
|
+
|
|
37
|
+
A URL alone is not proof that a project controls the destination. Registry metadata provides a publisher assertion about a relationship; it does not establish domain or repository ownership. Each non-registry source records its source kind, supported roles, authority, trust, status, one deterministic upstream `discoveredFrom` source ID, and all upstream source IDs in `trustEvidenceSourceIds`.
|
|
38
|
+
|
|
39
|
+
The public Knowledge Manifest contract permits one `discoveredFrom` source ID rather than a field-path object. The resolver chooses it by canonical source ID and field-path ordering. Field paths are retained only while resolving candidates and do not become a public artifact. This preserves portability while still retaining all distinct upstream source IDs as trust evidence.
|
|
40
|
+
|
|
41
|
+
## Roles, kinds, and status
|
|
42
|
+
|
|
43
|
+
| Candidate role | Knowledge Manifest kind | `supports` value |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| homepage | `officialDocumentation` | `homepage` |
|
|
46
|
+
| documentation | `officialDocumentation` | `documentation` |
|
|
47
|
+
| repository | `sourceRepository` | `repository` |
|
|
48
|
+
| issues | `sourceRepository` | `issues` |
|
|
49
|
+
| changelog | `officialDocumentation` | `changelog` |
|
|
50
|
+
| release notes | `officialDocumentation` | `releaseNotes` |
|
|
51
|
+
| releases | `releaseFeed` | `releases` |
|
|
52
|
+
|
|
53
|
+
Registry sources remain adapter-owned, such as `npm:react:registry`, with `registryAuthoritative` authority and `publisher` trust. Registry facts are authoritative for their registry, but publisher-entered URL fields default to `publisherProvided`, `publisher`, and `unverified`. No URL is labelled `official` or `officialProject` from package name, organization name, or domain similarity.
|
|
54
|
+
|
|
55
|
+
`verified` is possible only when two distinct registry source IDs assert the same canonical relationship for the same package ID. Duplicate fields in one registry record are not independent corroboration. Package IDs are intentionally not merged across npm and PyPI merely because their URLs match; cross-ecosystem project equivalence is deferred.
|
|
56
|
+
|
|
57
|
+
## Canonical public URLs and source IDs
|
|
58
|
+
|
|
59
|
+
Only portable HTTPS URLs are emitted. Resolution rejects malformed values, HTTP, non-web schemes, embedded credentials, query strings, localhost, loopback, link-local and private IP literals. Fragments are removed. Hosts are normalized by the URL parser, root and path trailing slashes are normalized consistently, `git+https:` repository values become HTTPS, and a GitHub repository `.git` suffix is removed. No DNS lookup, redirect, or request occurs. Meaningful paths remain distinct: a GitHub repository and its `/issues` page are separate records.
|
|
60
|
+
|
|
61
|
+
Non-registry IDs are package-scoped and role-qualified:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
npm:react:documentation:<sha256(canonical-url)>
|
|
65
|
+
npm:react:repository:<sha256(canonical-url)>
|
|
66
|
+
pypi:fastapi:changelog:<sha256(canonical-url)>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
They contain no local path, cache key, timestamp, credential, or random value. The same package, compatible role group, and canonical URL always produce the same ID. Homepage and documentation use one compatible documentation group when the URL is identical, preserving both sorted support roles. Repository and issue URLs remain separate even when hosted by the same service.
|
|
70
|
+
|
|
71
|
+
## Deduplication and conflict behavior
|
|
72
|
+
|
|
73
|
+
Candidates merge only when package ID, canonical URL, and compatible role group match. Different roles do not conflict automatically. If the same package asserts two distinct URLs for the same role, the resolver keeps both records, adds symmetric sorted `conflictsWith` references, and emits a non-retryable `SOURCE_CONFLICT` warning for each conflicting record. It never chooses one URL silently or attempts semantic conflict resolution.
|
|
74
|
+
|
|
75
|
+
All packages, source IDs, sources, supports, trust evidence, conflict references, and warnings use code-unit lexical ordering. The graph therefore does not depend on adapter completion order.
|
|
76
|
+
|
|
77
|
+
## Privacy, safety, and limitations
|
|
78
|
+
|
|
79
|
+
The graph contains normalized public URLs and no raw registry payload, response headers, source content, credentials, query tokens, local paths, or cache implementation details. Unsafe candidates are omitted without a public warning because no fetch occurred to establish that a source is missing.
|
|
80
|
+
|
|
81
|
+
MVP-02-06 intentionally does not fetch websites, crawl documentation, call GitHub APIs or Releases, follow redirects, verify ownership, discover community resources, calculate numeric trust scores, assemble a Knowledge Manifest, add a CLI command, compare versions, analyze breaking changes, or perform AI/LLM reasoning.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# MVP-02 npm-Compatible Registry Adapter
|
|
2
|
+
|
|
3
|
+
MVP-02-04 adds the internal adapter that collects facts for Node package identities in the npm-compatible registry ecosystem. It accepts a research package from the deterministic Research Plan and returns internal package, registry-source, cache-outcome, and warning records. It does not assemble or write a Knowledge Manifest.
|
|
4
|
+
|
|
5
|
+
> The `npm:` package identity identifies the npm-compatible registry ecosystem. It does not mean that the source repository uses the npm CLI.
|
|
6
|
+
|
|
7
|
+
## Package managers and registry identity
|
|
8
|
+
|
|
9
|
+
Projects using npm, Yarn, pnpm, or Bun commonly resolve the same public Node package identity through an npm-compatible registry. The adapter therefore works only from:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
registry: npm
|
|
13
|
+
packageId: npm:<normalized-package-name>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
It does not invoke a package-manager CLI, inspect lockfiles, or read `.npmrc`, `.yarnrc.yml`, or `bunfig.toml`. Package-manager origin is intentionally absent from both the registry request and the cache identity. Equivalent `npm:react` Research Plan records produce the same request, cache entry, and normalized facts regardless of whether their source project used npm, Yarn, pnpm, or Bun.
|
|
17
|
+
|
|
18
|
+
## Public Registry scope and requests
|
|
19
|
+
|
|
20
|
+
The default approved Registry base is `https://registry.npmjs.org`. Internal callers may supply another explicit HTTPS base for tests or a future approved policy. HTTP, credentialed URLs, query-bearing bases, and repository-derived registry selection are rejected.
|
|
21
|
+
|
|
22
|
+
The adapter requests the full packument representation with one deterministic `GET`:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
<registry-base>/<encodeURIComponent(normalized-package-name)>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
https://registry.npmjs.org/react
|
|
32
|
+
https://registry.npmjs.org/%40vitejs%2Fplugin-react
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The adapter uses `Accept: application/json`, a stable UpgradeLens user agent, `credentials: omit`, and disabled redirects. It sends no authorization or cookie headers. npm search is never used as an identity fallback.
|
|
36
|
+
|
|
37
|
+
## Cache integration
|
|
38
|
+
|
|
39
|
+
The adapter uses the private [Lightweight Knowledge Store](MVP-02-Knowledge-Store.md) with this identity:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"adapter": "npm",
|
|
44
|
+
"resourceKind": "registry-package",
|
|
45
|
+
"packageId": "npm:react",
|
|
46
|
+
"resourceVariant": "full-packument",
|
|
47
|
+
"adapterVersion": "1"
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The default adapter TTL is 24 hours, but callers may provide a policy TTL. The store itself remains registry-agnostic.
|
|
52
|
+
|
|
53
|
+
| Cache state | Adapter behavior |
|
|
54
|
+
| --- | --- |
|
|
55
|
+
| Fresh | Normalize the cached packument; no request is made. |
|
|
56
|
+
| Missing | Fetch, validate, atomically cache, then normalize. |
|
|
57
|
+
| Expired | Fetch and replace on success. Fetch failure returns unavailable facts; stale data is not silently used. |
|
|
58
|
+
| Corrupted | Treat as unusable, fetch a replacement, and overwrite only after validation succeeds. |
|
|
59
|
+
|
|
60
|
+
The internal result records `hit`, `miss`, `revalidated`, or a corruption-replacement outcome without exposing filenames, cache keys, or store paths.
|
|
61
|
+
|
|
62
|
+
## Packument facts and normalization
|
|
63
|
+
|
|
64
|
+
The adapter validates that the response has the requested exact package name, `dist-tags`, `versions`, and `time` objects before caching it. A scoped name must match exactly; a response for another package is rejected. Optional malformed publisher metadata is omitted rather than causing a crash.
|
|
65
|
+
|
|
66
|
+
It normalizes these facts when safely present:
|
|
67
|
+
|
|
68
|
+
- description and license;
|
|
69
|
+
- HTTPS homepage, repository, and issue URLs;
|
|
70
|
+
- package-level deprecation message/status when explicitly reported;
|
|
71
|
+
- `dist-tags.latest` as a registry fact;
|
|
72
|
+
- a minimal release index with opaque version, valid publication time, npm release URL, and explicit deprecation state.
|
|
73
|
+
|
|
74
|
+
Repository strings and `{ "url": "..." }` objects are supported. `git+https:` is normalized to HTTPS, GitHub `.git` suffixes are removed, and credentialed repository URLs are dropped. URL queries and fragments are not retained.
|
|
75
|
+
|
|
76
|
+
`latest` is taken only from `dist-tags.latest`; the adapter never chooses a lexical or semantic maximum. If that tag is absent or references a version missing from `versions`, no alternative version is selected and the result is partial. Release versions are sorted by code-unit lexical order. The adapter does not parse SemVer, infer prereleases, or treat a version as yanked without an explicit registry fact.
|
|
77
|
+
|
|
78
|
+
Each successful result creates one internal registry source record such as `npm:react:registry`, with registry authority, publisher trust, package/API URLs, source roles, content digest, retrieval timestamp, and `fresh` snapshot state. This record is shaped for later Knowledge Manifest assembly but is not itself a manifest.
|
|
79
|
+
|
|
80
|
+
## Response limits and error mapping
|
|
81
|
+
|
|
82
|
+
Full npm packuments contain complete metadata for every published version and can be several megabytes. The adapter therefore owns a default bounded limit of **16 MiB** (`16 * 1024 * 1024`). Callers may set `maxResponseBytes` explicitly for tests or a future execution policy; it must be a positive safe integer and may not exceed the documented 64 MiB safety ceiling. The setting is execution configuration, not Knowledge Manifest policy.
|
|
83
|
+
|
|
84
|
+
Response bodies are read through a bounded streaming reader; the adapter never calls `response.json()` directly. It requires a JSON media type and rejects a body larger than the configured maximum without caching it. An oversized body retains the internal `NPM_RESPONSE_TOO_LARGE` code and maps to the existing public `REGISTRY_RESPONSE_INVALID` warning.
|
|
85
|
+
|
|
86
|
+
Every response body is fully consumed or explicitly cancelled. Unused non-200 bodies, wrong-media bodies, and oversized streams are cancelled; oversized readers are cancelled and release their lock. The request timeout covers the complete fetch/read lifecycle and is cleared in `finally` on every outcome. Online CLI research injects a scoped, CLI-owned fetch and closes its Agent after completion; direct callers retain ownership of injected fetch resources.
|
|
87
|
+
|
|
88
|
+
| Condition | Package status | Warning |
|
|
89
|
+
| --- | --- | --- |
|
|
90
|
+
| Registry `404` | `notFound` | `PACKAGE_NOT_FOUND` |
|
|
91
|
+
| Registry `429` | `unavailable` | `REGISTRY_RATE_LIMITED` |
|
|
92
|
+
| `5xx`, timeout, or transport failure | `unavailable` | `REGISTRY_UNAVAILABLE` |
|
|
93
|
+
| Invalid JSON/media/size/packument shape/name mismatch | `unavailable` | `REGISTRY_RESPONSE_INVALID` |
|
|
94
|
+
|
|
95
|
+
Negative responses, rate-limit responses, invalid payloads, and transport failures are not cached.
|
|
96
|
+
|
|
97
|
+
## Intentional limitations
|
|
98
|
+
|
|
99
|
+
This adapter does not implement private registries, authentication, package-manager configuration, package-manager CLI execution, lockfile parsing, Yarn/pnpm/Bun-specific adapters, PyPI, GitHub Releases, documentation crawling, conditional HTTP requests, retries, Knowledge Manifest orchestration, a research CLI command, version comparison, breaking-change analysis, or AI behavior.
|