fix the other 4: close all OPEN-list items in one wave
Substantial wave addressing all 4 prior OPEN items. Three closed in full, one partially (the speculative half deliberately deferred). OPEN #1 — Periodic fresh→main index merge (FULL): - POST /v1/vectors/index/{src}/merge with {dest, clear_source} - Idempotent on re-runs (existing-in-dest items skipped) - internal/vectord/index.go: new Index.IDs() snapshot method + i.ids tracker field as canonical ID set, independent of meta map's nil-vs-{} sparseness (was a real bug — IDs() backed by meta alone missed items added with nil metadata) - 4 cmd-level integration tests (happy path drain+clear, dim mismatch, dest not found, self-merge rejection) + 1 unit test - DecodeIndex backward-compat: old envelopes restore i.ids from meta keys (best effort; new items going forward use the tracker) OPEN #2 — Distillation SFT export (SUBSTRATE): - internal/distillation/sft_export.go ports the load-bearing half: IsSftNever predicate + ListScoredRunFiles (data/scored-runs/YYYY/ MM/DD walk) + LoadScoredRunsFromFile + partial ExportSft. - Synthesis (instruction/input/response generation) deferred to a separate wave — too big for this session, but the substrate makes the next wave a port-not-design exercise. - TestSftNever_PinsExpectedSet locks the contamination firewall set: if a future commit adds/removes from SftNever, this test fails — forcing the change through review. - 5 new tests; firewall fires end-to-end through the partial port. OPEN #3 — Distribution drift via PSI (FULL): - internal/drift/drift.go: ComputeDistributionDrift via Population Stability Index. Standard finance/risk metric, well-defined verdict tiers (stable < 0.10, minor 0.10–0.25, major ≥ 0.25). - Equal-width bucketing over combined min/max so neither dist falls outside; epsilon-clamping for empty buckets so log doesn't blow up. Per-bucket breakdown for drilldown. - Pairs with the existing ComputeScorerDrift: scorer drift is categorical, distribution drift is continuous. Different shapes, same package. - 7 new tests covering identical-is-stable, hard-shift-is-major, moderate-detected-not-stable, empty-inputs-safe, all-identical- safe, bucket-counts-conserved, num-buckets-clamping. OPEN #4 — Ops nice-to-haves (PARTIAL — wall-clock done, others deferred): - (a) Real-time wall-clock for stress harness: per-phase elapsed time logged to stdout as it runs (`[stress] phase NAME starting (T+12.3s)` + `[stress] phase NAME done — 8.5s (T+20.8s)`). Output.PhaseTimings + Output.TotalElapsedMs in JSON. - (b) chatd fixture-mode S3 mock + (c) liberal-paraphrase calibration: not actioned — no fired trigger, would be speculative. Documented as deferred-until-need rather than ignored. Per the project's discipline ("don't add features beyond what the task requires"). OPEN list now empty / steady-state. Future items will land as production triggers fire. Build + vet + tests green; 18 new tests across the 4 closures. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -102,6 +102,9 @@ type ResultRef struct {
|
||||
type Event struct {
|
||||
Phase string `json:"phase"`
|
||||
Hour int `json:"hour"` // operational-narrative time label, not real wall clock
|
||||
// Real wall-clock time of the event is in TimestampUnixNano below
|
||||
// (already present pre-OPEN-#4). Consumers can derive
|
||||
// "since run start" from event.TimestampUnixNano - Output.GeneratedAt.
|
||||
Coordinator string `json:"coordinator"`
|
||||
Contract string `json:"contract"`
|
||||
Role string `json:"role"`
|
||||
@@ -127,13 +130,26 @@ type Event struct {
|
||||
}
|
||||
|
||||
type Output struct {
|
||||
Coordinators []string `json:"coordinators"`
|
||||
Contracts []string `json:"contracts"`
|
||||
Events []Event `json:"events"`
|
||||
Diversity Diversity `json:"diversity"`
|
||||
Determinism Determ `json:"determinism"`
|
||||
Learning Learning `json:"learning"`
|
||||
GeneratedAt time.Time `json:"generated_at"`
|
||||
Coordinators []string `json:"coordinators"`
|
||||
Contracts []string `json:"contracts"`
|
||||
Events []Event `json:"events"`
|
||||
Diversity Diversity `json:"diversity"`
|
||||
Determinism Determ `json:"determinism"`
|
||||
Learning Learning `json:"learning"`
|
||||
PhaseTimings []PhaseTiming `json:"phase_timings,omitempty"` // OPEN #4: real wall-clock per phase
|
||||
TotalElapsedMs int64 `json:"total_elapsed_ms,omitempty"`
|
||||
GeneratedAt time.Time `json:"generated_at"`
|
||||
}
|
||||
|
||||
// PhaseTiming records the real wall-clock duration of a single phase.
|
||||
// Closes OPEN #4's "real-time wall-clock for the stress harness" —
|
||||
// operators reading the JSON now see actual phase durations alongside
|
||||
// the operational-narrative Hour labels. Hour is a fictional time
|
||||
// (the simulated 48-hour mock); ElapsedMs is the real one.
|
||||
type PhaseTiming struct {
|
||||
Phase string `json:"phase"`
|
||||
StartUTC time.Time `json:"start_utc"`
|
||||
ElapsedMs int64 `json:"elapsed_ms"`
|
||||
}
|
||||
|
||||
// Diversity = how distinct are top-K worker sets across (coord,
|
||||
@@ -223,6 +239,10 @@ func main() {
|
||||
ctx := context.Background()
|
||||
_ = ctx
|
||||
|
||||
// runStart pinned BEFORE startPhase is defined so the closure
|
||||
// can reference it; output.GeneratedAt picks it up later.
|
||||
runStart := time.Now().UTC()
|
||||
|
||||
// Optional Langfuse client. Best-effort: missing env file or
|
||||
// unreachable Langfuse just means traces don't go anywhere; the
|
||||
// run still proceeds.
|
||||
@@ -255,7 +275,33 @@ func main() {
|
||||
// Subsequent emitSpan calls nest under it. Idempotent — returns
|
||||
// "" when Langfuse isn't configured so callers don't need nil
|
||||
// checks.
|
||||
// Per-phase wall-clock tracker (OPEN #4 closure). Operators see
|
||||
// "phase 2: surge took 8.3s" as the run progresses, not only in
|
||||
// the final JSON. Used by both the stdout log line and the
|
||||
// per-phase EndTime in the Langfuse span (close-on-next-startPhase).
|
||||
var (
|
||||
currentPhaseName string
|
||||
currentPhaseStart time.Time
|
||||
phaseTimings []PhaseTiming
|
||||
)
|
||||
closePhase := func() {
|
||||
if currentPhaseName == "" {
|
||||
return
|
||||
}
|
||||
elapsed := time.Since(currentPhaseStart)
|
||||
phaseTimings = append(phaseTimings, PhaseTiming{
|
||||
Phase: currentPhaseName,
|
||||
StartUTC: currentPhaseStart.UTC(),
|
||||
ElapsedMs: elapsed.Milliseconds(),
|
||||
})
|
||||
log.Printf("[stress] phase %s done — %.2fs (T+%.1fs)", currentPhaseName, elapsed.Seconds(), time.Since(runStart).Seconds())
|
||||
currentPhaseName = ""
|
||||
}
|
||||
startPhase := func(name string, hour int, meta map[string]any) {
|
||||
closePhase()
|
||||
currentPhaseName = name
|
||||
currentPhaseStart = time.Now()
|
||||
log.Printf("[stress] phase %s starting (T+%.1fs)", name, time.Since(runStart).Seconds())
|
||||
if lf == nil {
|
||||
return
|
||||
}
|
||||
@@ -267,7 +313,7 @@ func main() {
|
||||
TraceID: runTraceID,
|
||||
Name: name,
|
||||
Metadata: spanMeta,
|
||||
StartTime: time.Now(),
|
||||
StartTime: currentPhaseStart,
|
||||
})
|
||||
}
|
||||
// emitSpan records one span as a child of the current phase span.
|
||||
@@ -320,7 +366,7 @@ func main() {
|
||||
output := Output{
|
||||
Coordinators: []string{"alice", "bob", "carol"},
|
||||
Contracts: []string{contracts[0].Name, contracts[1].Name, contracts[2].Name},
|
||||
GeneratedAt: time.Now().UTC(),
|
||||
GeneratedAt: runStart,
|
||||
}
|
||||
|
||||
log.Printf("[stress] 3 coords, 3 contracts, k=%d, corpora=%v", *k, corpora)
|
||||
@@ -753,6 +799,11 @@ func main() {
|
||||
log.Printf("[stress] phase 7: diversity analysis")
|
||||
output.Diversity = computeDiversity(output.Events)
|
||||
|
||||
// Close the final phase + record total elapsed (OPEN #4 closure).
|
||||
closePhase()
|
||||
output.PhaseTimings = phaseTimings
|
||||
output.TotalElapsedMs = time.Since(runStart).Milliseconds()
|
||||
|
||||
// ── write ───────────────────────────────────────────────────
|
||||
if err := os.MkdirAll(filepath.Dir(*out), 0o755); err != nil {
|
||||
log.Fatalf("mkdir: %v", err)
|
||||
|
||||
Reference in New Issue
Block a user