Skip to content

File-level K-Means archetype classification silently truncates against its own trained models (115-dim global vs. 83-dim live vector) #1158

Closed

Description

@squid-protocol

🛑 Problem Statement

file_data.file_archetype (telemetry["archetype"]) is assigned by _classify_archetype()
(signal_processor.py:139-166) against two separate pre-trained K-Means models, and both are out
of sync with the live feature vector actually fed into them.

The live vector (signal_processor.py:609-633, raw_vector) is built by iterating
SIGNAL_SCHEMA (skipping indent_tabs/indent_spaces/hardware_bridge/cryptography/sec_*
keys) and appending 7 engineered features (cfr, log_logic_loc, log_imports_out,
log_popularity_in, log_max_func_comp, log_avg_func_args, log_churn). Against the current
SIGNAL_SCHEMA, that's:

SIGNAL_SCHEMA length: 93
filtered length: 76
raw_vector length: 76 + 7 = 83

Global model -- GENERAL_FILE_INFERENCE_MODEL (analysis_lens.py:2155, SCALER_MEDIANS /
SCALER_IQRS / 18-cluster ARCHETYPES_K18 centroids) is 115-dimensional:

SCALER_MEDIANS (file) length: 115
GLOBAL_ARCHETYPES cluster count: 18
file_cluster_0 centroid len: 115

_classify_archetype's distance loop (signal_processor.py:156) uses
range(min(len(scaled_vector), len(centroid_vector))), so it silently compares only the first 83
of each centroid's 115 dimensions -- 32 trained dimensions (~28%) are dropped on every file.

Per-language ("local") models -- SPECIFIC_FILE_INFERENCE_MODEL (analysis_lens.py:4501) --
are 74-dimensional and only exist for 5 of the 59 languages this engine parses (python,
javascript, typescript, c, cpp; confirmed via LANGUAGE_DEFINITIONS). Every other language's
files never get a local_archetype at all (signal_processor.py:654's lang_brain lookup
misses), and even the 5 covered languages compare 74-of-83 live dimensions against their own
centroids -- same truncation bug, smaller magnitude.

This also breaks a shipped, published claim. docs/wiki/03-05-claim-5-file-archetypes.md
("Claim 5") states the file archetype model was trained on 74 dimensions across 10
clusters
. The shipped model is now 115 dimensions and 18 clusters (file_cluster_0..17) -- the
model has clearly been retrained since that doc was written, but neither the live raw_vector
construction, the doc, nor (per the sibling repo-level issue) the downstream repo-clustering
feature vocabulary were updated to match.

🎯 Objective

Bring the live per-file feature vector and both trained models (global + per-language) back into
dimensional agreement, and make future drift fail loudly instead of silently truncating.

🛠️ Proposed Implementation

  1. Reconstruct what the 115-dim global / 74-dim local training vectors actually contained (likely
    a superset of today's filtered SIGNAL_SCHEMA -- e.g. sec_* keys currently excluded from
    raw_vector construction may have been included at training time, or SIGNAL_SCHEMA has
    grown new keys since). Either update raw_vector construction to match what the models
    expect, or retrain the models against today's 83-dim vector.
  2. Same loud-failure guard as the function-level issue: assert/log when
    len(raw_vector) != len(SCALER_MEDIANS) instead of relying on min()-truncated comparisons.
  3. Decide + document the per-language model coverage scope: is 5-of-59 languages intentional
    (highest-volume languages only), or a stalled rollout? If intentional, no code change needed
    beyond documenting it; if not, track expanding it as a separate follow-up (not in this issue's
    scope -- retraining models needs a real corpus and offline tooling that doesn't currently live
    in this repo).
  4. Update docs/wiki/03-05-claim-5-file-archetypes.md to reflect the model actually shipped
    today (dimension count, cluster count, and the cluster descriptions/DNA -- all presumably
    stale if the model was retrained since that doc's numbers were captured).

✅ Acceptance Criteria

  • Live raw_vector length matches GENERAL_FILE_INFERENCE_MODEL's trained dimensionality,
    verified by a real test.
  • Per-language coverage scope (5-of-59) is a documented, deliberate decision, not a silent gap.
  • A live/model dimension mismatch fails loudly instead of silently truncating via min().
  • docs/wiki/03-05-claim-5-file-archetypes.md matches the currently shipped model's real
    dimension/cluster counts (or is explicitly marked stale/historical).

Activity

  1. added
    bugUnintended behavior or logic failure in the engine
    ml-opsXGBoost inference, model training, and feature extraction
    metricsHeuristics, risk exposures, and topological math updates
    data-integrityIssues relating to RAM state or SQLite database fidelity
    priority: highCore feature broken, but workarounds exist
    on Aug 9, 2026
  2. squid-protocol commented on Aug 9, 2026

    @squid-protocol
    OwnerAuthor

    Part of epic #1160 (K-Means archetype clustering drift, all 3 tiers). Sibling issue: #1157 (function-level), #1159 (repo-level).

  3. squid-protocol commented on Sep 16, 2026

    @squid-protocol
    OwnerAuthor

    Partial progress — assessed against current main (23d7b8a):

    Fixed: the global-model truncation. #3061 (merged 2026-09-15) moved file_archetype classification to record_keeper._classify_file_archetype(), running it after full metric assembly (mirroring the offline apply_file_clusters) against a rebaked GENERAL_FILE_INFERENCE_MODEL retrained on the 83-feature contract — so the live vector and the trained centroids agree by construction, and a dimension mismatch is now structurally impossible rather than silently truncated. Its own numbers: file_archetype populates for ~97% of code files, up from ~5%.

    Not fixed — still open:

    1. Per-language local model (SPECIFIC_FILE_INFERENCE_MODEL, local_archetype). This is explicitly called out as deferred in fix(archetypes): classify file archetype from a self-describing brain, post-assembly #3061: "Per-language local micro-species model is still on the old contract → local_archetype/report 'File Archetype' pending its retrain." Confirmed on main: signal_processor.py still only sets local_archetype = None as a placeholder, and nothing since fix(archetypes): classify file archetype from a self-describing brain, post-assembly #3061 has touched this. Original bug (74-dim model, only 5-of-59 languages covered, same truncation class) stands as described.
    2. Stale published claim. docs/wiki/03-05-claim-5-file-archetypes.md still says "74 distinct dimensions" / "10 archetypes." The actual global model is now on the 83-feature contract (and, per the original report, was already 18 clusters before this retrain) — the doc still doesn't match either the old or new reality. docs(wiki): compositional archetype tower (functions → files → repos) #3029 added a doc cross-link to the new composition-archetype page but didn't correct these specific numbers.

    Leaving this open, scoped down to items 1 and 2 above. Recommend splitting the remaining local-model retrain into its own tracked follow-up if it isn't already, since it needs the same offline-trainer treatment #3061 did for the global model.

  4. squid-protocol commented on Sep 16, 2026

    @squid-protocol
    OwnerAuthor

    Closing this out. The global-model fix (#3061) is the part of this issue we have the corpus data to do properly right now, and it's done — the primary bug (silent dimension truncation) no longer exists.

    The remaining per-language ("local") model retrain is real, but needs a broader per-language corpus than we currently have to do credibly. Rather than leave that half-open here, split it off as its own tracked issue: #3085, labeled status: blocked until there's enough data to retrain against.

    The stale claim-5 doc numbers ("74 dimensions / 10 clusters") are being corrected separately as a docs fix.

  5. squid-protocol commented on Sep 16, 2026

    @squid-protocol
    OwnerAuthor

    Docs fix: #3086

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugUnintended behavior or logic failure in the enginedata-integrityIssues relating to RAM state or SQLite database fidelitymetricsHeuristics, risk exposures, and topological math updatesml-opsXGBoost inference, model training, and feature extractionpriority: highCore feature broken, but workarounds exist

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions