rename identify packages to new workflow name and only do single items at a time

This commit is contained in:
2026-05-26 22:44:43 -06:00
parent 8fca79e968
commit a2d191d7a7
4 changed files with 92 additions and 50 deletions
@@ -1,9 +1,9 @@
# Workflow Decomposition: Identify Vendored Packages
# Workflow Decomposition: Identify Next Vendored Package Decision From Source
- Bounded context: `dependency-recovery`
- Workflow slug: `identify-vendored-packages`
- Trigger: `Identify vendored packages from ingest artifacts`
- Success outcome: Vendored candidates receive accepted, rejected, or unresolved dependency decisions with evidence and rationale.
- Workflow slug: `identify-next-vendored-package-decision-from-source`
- Trigger: `Identify next vendored package decision from source`
- Success outcome: The next plausible vendored candidate from one source yields either a single accepted, rejected, or unresolved dependency decision, or an explicit no-more-candidates outcome.
## Inputs Owned by This Context
@@ -1,20 +1,20 @@
# Slice Discovery: Identify Vendored Packages
# Slice Discovery: Identify Next Vendored Package Decision From Source
- Bounded context: `dependency-recovery`
- Workflow slug: `identify-vendored-packages`
- Workflow slug: `identify-next-vendored-package-decision-from-source`
## Happy Path
- The workflow receives deterministic ingest artifacts from `ingest-snapshot`, including the run manifest, segment records, and canonical source projection.
- The workflow scans segment and segment-group candidates for vendored-package evidence.
- The workflow recovers probable package boundaries when one vendored package spans multiple related segments.
- The workflow computes a deterministic confidence score for each candidate match by combining the configured evidence signals.
- The workflow compares each confidence score against the configurable acceptance threshold.
- Candidates at or above the acceptance threshold become `accepted` dependency decisions.
- Candidates that remain plausible but are below threshold, colliding, or ambiguous become `unresolved` dependency decisions.
- Candidates whose evidence deterministically supports that they are not vendored package matches become `rejected` dependency decisions.
- The workflow emits a manifest of accepted, rejected, and unresolved dependency decisions with evidence, rationale, boundary notes, and replacement planning hints.
- Downstream `externalize-accepted-dependencies` consumes only the accepted decisions for externalization while preserving unresolved and rejected records for review and summaries.
- The workflow inspects the source snapshot and deterministically recovers the next plausible vendored candidate boundary that has not already been decided.
- The workflow computes a deterministic confidence ranking for package matches on that next candidate by combining the configured evidence signals.
- The workflow compares the strongest candidate match against the configurable acceptance threshold.
- If the strongest candidate is at or above the acceptance threshold, the workflow records one `accepted` dependency decision.
- If the strongest candidate remains plausible but is below threshold, colliding, or ambiguous, the workflow records one `unresolved` dependency decision.
- If the candidate evidence deterministically supports that it is not a vendored package match, the workflow records one `rejected` dependency decision.
- The workflow emits one decision record with evidence, rationale, boundary notes, and replacement planning hints.
- When no plausible undecided vendored candidates remain for the source under the current rules, the workflow emits an explicit no-more-candidates outcome.
- Downstream `externalize-accepted-dependencies` consumes the accumulated accepted decisions for externalization while preserving unresolved and rejected records for review and summaries.
## Edge Cases
@@ -1,12 +1,12 @@
# Core Sketch: Identify Vendored Packages
# Core Sketch: Identify Next Vendored Package Decision From Source
- Bounded context: `dependency-recovery`
- Workflow slug: `identify-vendored-packages`
- Workflow slug: `identify-next-vendored-package-decision-from-source`
## Command
- `IdentifyVendoredPackage`
- Meaning: evaluate one recovered vendored candidate boundary against deterministic evidence so this context can record a single `Dependency Decision` for later `Externalization`.
- `IdentifyNextVendoredPackageDecisionFromSource`
- Meaning: inspect one source snapshot, deterministically recover the next plausible vendored candidate if one remains, and record exactly one `Dependency Decision` or an explicit no-more-candidates outcome for later `Externalization`.
## Required State
@@ -32,22 +32,28 @@ State owned by `dependency-recovery` and required to decide this workflow:
Snapshots or handoffs read but not owned by this context:
- one recovered `Vendored Package` candidate boundary derived from `ingest-snapshot` artifacts by outer orchestration
- the relevant `Run Manifest` facts and canonical source projection from `ingest-snapshot` for that candidate boundary
- optional runtime traces for that candidate boundary used only as additional or tie-break evidence
- optional registry, tarball, or CDN package evidence used to compare matches for that candidate boundary
- one source snapshot from `ingest-snapshot`, plus the current decision cursor for that source
- the relevant `Run Manifest` facts and canonical source projection from `ingest-snapshot`
- optional runtime traces from that source used only as additional or tie-break evidence
- optional registry, tarball, or CDN package evidence used to compare matches for the next recovered candidate
## Policy Signature (Pseudo)
```text
recoverNextCandidateBoundary :
SourceSnapshot
-> SourceDecisionCursor
-> VendoredCandidateDiscoveryRules
-> Result<NextCandidateBoundary, NoMoreVendoredCandidates>
scoreVendoredCandidate :
VendoredCandidateBoundary
NextCandidateBoundary
-> CandidateEvidenceSources
-> ConfidenceScoringRules
-> RankedCandidateMatches
decideDependencyDecision :
VendoredCandidateBoundary
NextCandidateBoundary
-> RankedCandidateMatches
-> AcceptanceThresholdPolicy
-> DependencyDecision
@@ -57,23 +63,31 @@ validateDecisionRecord :
-> DependencyDecisionRequirements
-> Result<DependencyDecisionRecorded, DependencyDecisionRejected>
performVendoredPackageIdentification :
IdentifyVendoredPackage
performNextVendoredPackageDecisionFromSource :
IdentifyNextVendoredPackageDecisionFromSource
-> DependencyRecoveryState
-> Result<VendoredPackageIdentified, VendoredPackageIdentificationHardStopped>
-> Result<NextVendoredPackageDecisionFromSourceCompleted, VendoredPackageIdentificationHardStopped>
```
## Events
### Success Event
- `VendoredPackageIdentified`
- `NextVendoredPackageDecisionFromSourceCompleted`
- run identity reference
- evaluated candidate boundary reference
- source reference
- next decision cursor
- emitted single dependency decision
- emitted decision record reference
- evidence artifact references for that candidate
### Exhaustion Event
- `NoMoreVendoredCandidatesRemain`
- run identity reference
- source reference
- final decision cursor
### Failure Event
- `VendoredPackageIdentificationHardStopped`
@@ -83,8 +97,8 @@ performVendoredPackageIdentification :
## Boundary Notes
- The `dependency-recovery` context decides one candidate boundary's package candidacy, confidence ranking, and dependency decision state per workflow invocation.
- Outer orchestration is responsible for discovering, selecting, and iterating across multiple candidate boundaries; this slice must not batch those decisions itself.
- The `dependency-recovery` context decides the next vendored-package decision for one source per workflow invocation.
- Outer orchestration may repeat the workflow for the same source using the returned decision cursor until the slice emits `NoMoreVendoredCandidatesRemain`.
- This slice does not externalize accepted packages; that belongs to `dependency-recovery/externalize-accepted-dependencies`.
- `ingest-snapshot` remains the source of truth for run manifest, segment boundaries, and canonical projection; this slice must not reopen ingest decisions.
- Optional runtime traces and package-source comparisons act only as evidence inputs here and must not turn this slice into cross-context orchestration.
@@ -1,4 +1,4 @@
module DependencyRecovery.IdentifyVendoredPackages
module DependencyRecovery.IdentifyNextVendoredPackageDecisionFromSource
open DependencyRecovery.SharedModel
@@ -90,24 +90,32 @@ type AuditabilityRule =
// 2. Commands (Inputs)
type SourceDecisionCursor = SourceDecisionCursor of string
type TaintedSourceReference = TaintedSourceReference of string
type TrustedSourceReference = TrustedSourceReference of string
type TaintedCandidateBoundaryReference = TaintedCandidateBoundaryReference of string
type TrustedCandidateBoundaryReference = TrustedCandidateBoundaryReference of string
type IdentifyVendoredPackage = {
type IdentifyNextVendoredPackageDecisionFromSource = {
runManifest: TaintedRunManifestReference
canonicalProjection: TaintedCanonicalProjectionReference
candidateBoundary: TaintedCandidateBoundaryReference
source: TaintedSourceReference
decisionCursor: SourceDecisionCursor
runtimeTraces: TaintedRuntimeTraceReference option
}
// 3. Observed inputs and owned state
type TrustedCandidateInput = {
type TrustedSourceInput = {
runIdentity: RunIdentity
runManifest: TrustedRunManifestReference
canonicalProjection: TrustedCanonicalProjectionReference
candidateBoundary: TrustedCandidateBoundaryReference
source: TrustedSourceReference
decisionCursor: SourceDecisionCursor
runtimeTraces: TrustedRuntimeTraceReference option
}
@@ -143,16 +151,29 @@ type DependencyRecoveryState = {
// 4. Events (Facts)
type NextCandidateBoundary = {
source: TrustedSourceReference
candidateBoundary: TrustedCandidateBoundaryReference
nextCursor: SourceDecisionCursor
}
type DecisionRecordReference = DecisionRecordReference of string
type VendoredPackageIdentified = {
type NextVendoredPackageDecisionFromSourceCompleted = {
runIdentity: RunIdentity
candidateBoundary: TrustedCandidateBoundaryReference
source: TrustedSourceReference
nextCursor: SourceDecisionCursor
dependencyDecision: DependencyDecision
decisionRecord: DecisionRecordReference
evidenceArtifacts: EvidenceReference list
}
type NoMoreVendoredCandidatesRemain = {
runIdentity: RunIdentity
source: TrustedSourceReference
finalCursor: SourceDecisionCursor
}
type VendoredPackageIdentificationStage =
| CandidateInputParsingStage
| CandidateScoringStage
@@ -175,22 +196,29 @@ type VendoredPackageIdentificationHardStopped = {
type DependencyIdentificationState =
| AwaitingVendoredPackageIdentification of DependencyRecoveryState
| VendoredPackageDecisionRecorded of VendoredPackageIdentified
| NextVendoredPackageDecisionRecorded of NextVendoredPackageDecisionFromSourceCompleted
| VendoredCandidateDiscoveryExhausted of NoMoreVendoredCandidatesRemain
// 6. Parse and decision contracts
val parseCandidateInput :
IdentifyVendoredPackage
-> Result<TrustedCandidateInput, VendoredPackageIdentificationHardStopped>
val parseSourceInput :
IdentifyNextVendoredPackageDecisionFromSource
-> Result<TrustedSourceInput, VendoredPackageIdentificationHardStopped>
val recoverNextCandidateBoundary :
TrustedSourceInput
-> VendoredCandidateDiscoveryRules
-> Result<NextCandidateBoundary, NoMoreVendoredCandidatesRemain>
val scoreCandidateMatches :
TrustedCandidateInput
NextCandidateBoundary
-> TrustedSourceInput
-> ConfidenceScoringRules
-> Result<CandidateMatch list, VendoredPackageIdentificationHardStopped>
val decideDependencyDecision :
AcceptanceThresholdPolicy
-> TrustedCandidateBoundaryReference
-> NextCandidateBoundary
-> CandidateMatch list
-> Result<DependencyDecision, VendoredPackageIdentificationHardStopped>
@@ -201,14 +229,14 @@ val validateDecisionRecord :
val decide :
DependencyIdentificationState
-> IdentifyVendoredPackage
-> Result<VendoredPackageIdentified, VendoredPackageIdentificationHardStopped>
-> IdentifyNextVendoredPackageDecisionFromSource
-> Result<NextVendoredPackageDecisionFromSourceCompleted, VendoredPackageIdentificationHardStopped>
val apply :
DependencyIdentificationState
-> VendoredPackageIdentified
-> NextVendoredPackageDecisionFromSourceCompleted
-> DependencyIdentificationState
val workflow :
IdentifyVendoredPackage
-> Effect.Effect<Result<VendoredPackageIdentified, VendoredPackageIdentificationHardStopped>>
IdentifyNextVendoredPackageDecisionFromSource
-> Effect.Effect<Result<NextVendoredPackageDecisionFromSourceCompleted, VendoredPackageIdentificationHardStopped>>