Skip to content

Commit 600cfee

Browse files
WhatsYourWhyclaude
andcommitted
cleanup: remove legacy_density mode, compat/, and validate_packet alias
Single-code-path simplification pass. v0.2 carried a `legacy_density` salience-mode branch as "one-release migration support"; that release never came. Removing it. Removed: - `temporal_gradient/compat/` — CANONICAL_MODE / LEGACY_DENSITY_MODE constants, legacy packet fallback keys, density-to-psi normalizer, schema-version coercer. - `ClockRateModulator.salience_mode`, `legacy_density_scale`, and `input_context` kwargs; `calculate_information_density()` and `_psi_from_legacy_density()` helpers. - `ConfigClock.salience_mode` / `legacy_density_scale` fields and the matching keys from `DEFAULTS` and `tg.yaml`. - `validate_packet_schema(salience_mode=...)` kwarg — there is now one mode. - `validate_packet()` compatibility alias (use `validate_packet_schema`). - `ChronometricVector.from_packet(salience_mode=...)` and its legacy branch that read `t_obj` / `r` / `legacy_density` keys. - `normalize_schema_version("1")` legacy migration — only `"1.0"` now. - `tests/fixtures/packets/legacy.jsonl`. - `ClockTickRequest.input_context` field. Callers updated: `anomaly_poc.py`, `sanity_harness.py`, `calibration_harness.py`, `README.md`, `docs/usage.md`. Tests updated/simplified: 13 test files touched to drop `salience_mode="canonical"` kwargs, `legacy_density_scale` params, and the schema-version "1" legacy-migration cases. 166 tests passing (was 170; 4 removed tests exercised legacy-only code paths). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e6a1105 commit 600cfee

30 files changed

Lines changed: 156 additions & 562 deletions

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ salience = tg.salience.SaliencePipeline(
4545
clock = tg.clock.ClockRateModulator(
4646
base_dilation_factor=config.clock.base_dilation_factor,
4747
min_clock_rate=config.clock.min_clock_rate,
48-
salience_mode=config.clock.salience_mode,
4948
)
5049
cooldown = ComputeCooldownPolicy(cooldown_tau=config.policies.cooldown_tau)
5150

@@ -63,7 +62,7 @@ packet = tg.telemetry.ChronometricVector(
6362
memory_strength=0.0,
6463
).to_packet()
6564

66-
validate_packet_schema(packet, salience_mode=config.clock.salience_mode)
65+
validate_packet_schema(packet)
6766

6867
if cooldown.allows_compute(elapsed_tau=clock.tau):
6968
... # downstream work

anomaly_poc.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,6 @@ def run_poc(
7474
clock = tg.clock.ClockRateModulator(
7575
base_dilation_factor=cfg.clock.base_dilation_factor,
7676
min_clock_rate=cfg.clock.min_clock_rate,
77-
salience_mode=cfg.clock.salience_mode,
78-
legacy_density_scale=cfg.clock.legacy_density_scale,
7977
)
8078

8179
decay = DecayEngine(
@@ -125,11 +123,7 @@ def run_poc(
125123
provenance_hash=compute_provenance_hash(s.provenance) if strict_replay_mode else None,
126124
).to_packet()
127125

128-
validate_packet_schema(
129-
packet,
130-
salience_mode=cfg.clock.salience_mode,
131-
require_provenance_hash=strict_replay_mode,
132-
)
126+
validate_packet_schema(packet, require_provenance_hash=strict_replay_mode)
133127
packet["EVENT_KIND"] = event.kind
134128
packet["ENCODED"] = bool(encoded)
135129
packet["COMPUTE_ALLOWED"] = bool(compute_allowed)

calibration_harness.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ def run_calibration(config_path: str = "tg.yaml"):
4848
clock = ClockRateModulator(
4949
base_dilation_factor=config.clock.base_dilation_factor,
5050
min_clock_rate=config.clock.min_clock_rate,
51-
salience_mode=config.clock.salience_mode,
52-
legacy_density_scale=config.clock.legacy_density_scale,
5351
)
5452
decay = DecayEngine(
5553
half_life=config.memory.half_life,

docs/usage.md

Lines changed: 57 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,28 @@
1-
# How to Read the Logs
2-
The Temporal Gradient outputs **Internal State Telemetry** rather than conventional debug lines. The goal is to show how internal time (τ) and memory retention respond to salience.
3-
Canonical module references and compatibility shims are listed in [`docs/CANONICAL_SURFACES.md`](docs/CANONICAL_SURFACES.md).
1+
# Usage
42

3+
Temporal Gradient outputs **internal state telemetry** — packets that show
4+
how internal time (τ) and memory retention respond to salience. This guide
5+
covers the packet contract, configuration knobs, and the salience
6+
components shipped by default.
57

6-
## 0. Telemetry contract (canonical vs extended)
7-
The telemetry packet is versioned and split into **required** vs **optional** keys.
8-
For canonical symbol/module ownership (including telemetry validators and compatibility aliases), see [`docs/CANONICAL_SURFACES.md`](docs/CANONICAL_SURFACES.md).
8+
See [`architecture.md`](architecture.md) for the data-flow diagram and
9+
public API surface.
910

10-
### Packet API contract
11-
- `to_packet()` => returns the packet as a `dict` mapping for schema checks and in-memory processing.
12-
- `to_packet_json()` => returns serialized JSON `str` for transport/logging boundaries.
13-
- Avoid `json.loads(to_packet())`; parse only the JSON text returned by `to_packet_json()`.
11+
## Telemetry packet contract
1412

15-
**Required keys (canonical schema):**
16-
- `SCHEMA_VERSION`
17-
- `WALL_T`
18-
- `TAU`
19-
- `SALIENCE`
20-
- `CLOCK_RATE`
21-
- `MEMORY_S`
22-
- `DEPTH`
13+
- `to_packet()` returns a `dict` for schema checks and in-memory processing.
14+
- `to_packet_json()` returns a JSON string for transport or logging.
2315

24-
**Optional keys (extended telemetry):**
25-
- `H`
26-
- `V`
16+
**Required keys:** `SCHEMA_VERSION`, `WALL_T`, `TAU`, `SALIENCE`,
17+
`CLOCK_RATE`, `MEMORY_S`, `DEPTH`.
2718

28-
`CLOCK_RATE` and `MEMORY_S` are always present in canonical packets. If unset at construction time, serialization currently emits numeric fallbacks (`0.0`), not `null`.
19+
**Optional keys:** `H`, `V`, `entropy_cost`, `PROVENANCE_HASH`.
2920

30-
`SCHEMA_VERSION` policy is strict: canonical serialization must emit exactly `"1.0"`. For migration input only, validators accept legacy `"1"` and normalize it to `"1.0"` on canonical re-serialization.
21+
`SCHEMA_VERSION` must be exactly `"1.0"`. `CLOCK_RATE` and `MEMORY_S` fall
22+
back to `0.0` when unset at construction time.
3123

32-
CLI tables should print **only canonical columns** by default (`WALL_T`, `TAU`, `SALIENCE`, `CLOCK_RATE`, `MEMORY_S`, `DEPTH`). Extended fields like `H` and `V` are intended for verbose/debug output, not the base schema. Demo scripts may also include an `INPUT` column for readability; it is not part of the canonical packet schema.
24+
### Example packet
3325

34-
### Legacy mode compatibility (`legacy_density`)
35-
`legacy_density` is a migration-only mode. It is not the canonical telemetry contract.
36-
37-
Behavior summary:
38-
- Salience is derived from entropy density and clamped into `[0,1]`.
39-
- Canonical telemetry schema strictness is intentionally bypassed.
40-
41-
Compatibility entry points referenced in this section are cataloged in [`docs/CANONICAL_SURFACES.md`](docs/CANONICAL_SURFACES.md).
42-
43-
Packet-shape examples:
44-
45-
Canonical packet (preferred):
4626
```json
4727
{
4828
"SCHEMA_VERSION": "1.0",
@@ -57,19 +37,7 @@ Canonical packet (preferred):
5737
}
5838
```
5939

60-
Legacy compatibility packet (allowed only in `legacy_density` mode):
61-
```json
62-
{
63-
"WALL_T": 1.0,
64-
"TAU": 0.15,
65-
"SALIENCE": 0.9,
66-
"DEPTH": 0
67-
}
68-
```
69-
70-
See `docs/CANONICAL_VS_LEGACY.md` for the full migration guidance and deprecation horizon.
71-
72-
## Minimal packet round-trip example (canonical)
40+
### Round-trip
7341

7442
```python
7543
import temporal_gradient as tg
@@ -84,66 +52,61 @@ packet = tg.telemetry.ChronometricVector(
8452
memory_strength=0.2,
8553
).to_packet()
8654

87-
validate_packet_schema(packet, salience_mode="canonical")
88-
print(packet["SCHEMA_VERSION"], packet["SALIENCE"])
55+
validate_packet_schema(packet)
8956
```
9057

91-
This prints canonical packet fields (`SCHEMA_VERSION` and `SALIENCE`) from the in-memory `dict` returned by `to_packet()`.
92-
93-
94-
## 1. The clock-rate table
95-
This table shows how the internal clock-rate is reparameterized by salience load (surprise × value).
58+
## Reading clock-rate output
9659

9760
```text
98-
WALL_T | TAU | INPUT | SALIENCE | CLOCK_RATE (dτ/dt)
99-
============================================================================================
100-
1.0 | 0.15 | "CRITICAL: SECURITY BREACH..." | 0.9 | 0.15x
101-
2.0 | 1.15 | "Checking local weather..." | 0.4 | 1.00x
61+
WALL_T | TAU | INPUT | SALIENCE | CLOCK_RATE
62+
==============================================================================
63+
1.0 | 0.15 | "CRITICAL: SECURITY BREACH..." | 0.9 | 0.15
64+
2.0 | 1.15 | "Checking local weather..." | 0.4 | 1.00
10265
```
10366

104-
Key metrics:
105-
- **WALL_T:** External time elapsed (seconds).
106-
- **TAU:** Internal time accumulator after clock-rate reparameterization.
107-
- **SALIENCE:** Surprise×value score from the valuator.
108-
- **CLOCK_RATE (dτ/dt):** Internal clock multiplier after salience modulation.
109-
110-
Interpretation:
111-
- A CLOCK RATE below 1.0x means the internal clock slowed to process a high-load event (reduced internal clock rate), not “bullet time.”
112-
- 1.0x indicates the baseline clock rate.
67+
- **WALL_T** — external time elapsed (seconds).
68+
- **TAU** — internal time accumulator after clock-rate reparameterization.
69+
- **SALIENCE** — Ψ = H × V from the salience pipeline.
70+
- **CLOCK_RATE** — dτ/dt. Below 1.0 means the internal clock slowed to
71+
process a high-load event. 1.0 is the baseline.
11372

114-
## 2. The entropy sweep (memory audit)
115-
At the end of the simulation, the decay engine reports which memories stayed above the retention threshold.
73+
## Memory audit (post-simulation)
11674

11775
```
118-
>>> MEMORY AUDIT (Post-Simulation)
119-
[ALIVE] Strength: 1.42 | Content: "My name is Sentinel."
120-
[PRUNED ] Content: "Rain. Water. Liquid."
76+
[ALIVE] Strength: 1.42 | Content: "My name is Sentinel."
77+
[PRUNED] Content: "Rain. Water. Liquid."
12178
```
12279

123-
- **ALIVE:** The memory stayed above the pruning threshold because it started with high salience or was reconsolidated.
124-
- **PRUNED:** The memory decayed below the threshold and was pruned.
80+
- **ALIVE** above the pruning threshold.
81+
- **PRUNED** decayed below the threshold and removed by the entropy sweep.
12582

126-
## 3. Configuration hints
127-
Adjust these parameters in `simulation_run.py` and the supporting modules to shape the simulation (canonical policy surface: `temporal_gradient.policies.compute_cooldown`):
128-
- `base_dilation_factor` and `min_clock_rate` in `ClockRateModulator` to control the clock-rate floor and sensitivity to salience load.
129-
- `half_life` in `DecayEngine` to control decay speed.
130-
- Reconsolidation cooldowns and diminishing returns in `EntropicMemory.reconsolidate` to avoid runaway reinforcement.
83+
## Configuration knobs
13184

132-
## 4. Salience components (H/V)
133-
The salience pipeline currently decomposes **H (novelty)** and **V (value)** into two concrete components with constrained inputs and normalized outputs.
85+
- `clock.base_dilation_factor`, `clock.min_clock_rate` — clock-rate floor
86+
and sensitivity to salience load.
87+
- `memory.half_life`, `memory.decay_lambda` — decay speed.
88+
- `memory.s_max`, `memory.initial_strength_max` — reconsolidation bounds.
89+
- `policies.cooldown_tau` — compute eligibility window on internal time.
90+
91+
## Salience components
13492

13593
### RollingJaccardNovelty (H)
136-
- **Operational definition:** Compute tokens from the incoming text, compare against a rolling history window, and take `1 - max_jaccard_similarity` across the window. The history stores the most recent **5** token sets (default `window_size=5`).
137-
- **Tokenization:** Lowercase and split on the regex pattern `[a-z0-9']+` to form a unique token set.
138-
- **Allowed inputs:** Current message text **plus** the internal rolling history (no external context).
139-
- **Normalization:** Jaccard similarity is in `[0,1]`, so novelty output is normalized to `[0,1]`.
140-
- **Swap-friendly note:** This component can be replaced with an embedding-based novelty scorer, provided the output stays normalized to `[0,1]` and only uses the current text plus an internal memory of prior text.
94+
95+
Tokenize the incoming text, compare against a rolling history window of
96+
recent token sets, return `1 - max_jaccard_similarity`. Default
97+
`window_size=5`. Tokenization: lowercase, split on `[a-z0-9']+`.
98+
99+
Output is in `[0, 1]`. Swap-friendly: any novelty scorer that takes the
100+
current text plus internal history and returns a normalized score works.
141101

142102
### KeywordImperativeValue (V)
143-
- **Operational definition:** Count keyword hits in the current text, then compute `min(max_value, base_value + hit_value * hits)`.
144-
- **Default keyword list:** `["must", "never", "critical", "always", "don't", "stop", "urgent"]`.
145-
- **Default weights:** `base_value=0.1`, `hit_value=0.2`, `max_value=1.0`.
146-
- **Allowed inputs:** Current message text **only** (no access to memory or external context).
147-
- **Normalization:** Value output is clamped to `[0,1]` via `max_value`.
148103

149-
Both components are expected to output normalized scores in `[0,1]`. The combined salience `psi = H × V` inherits the same normalization range.
104+
Count keyword hits in the current text, return
105+
`min(max_value, base_value + hit_value * hits)`.
106+
107+
- Default keywords: `["must", "never", "critical", "always", "don't",
108+
"stop", "urgent"]`.
109+
- Default weights: `base_value=0.1`, `hit_value=0.2`, `max_value=1.0`.
110+
111+
Output is clamped to `[0, 1]`. The combined salience `Ψ = H × V`
112+
inherits the same range.

sanity_harness.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ def run_harness(
2929
clock = ClockRateModulator(
3030
base_dilation_factor=active_config.clock.base_dilation_factor,
3131
min_clock_rate=active_config.clock.min_clock_rate,
32-
salience_mode=active_config.clock.salience_mode,
33-
legacy_density_scale=active_config.clock.legacy_density_scale,
3432
)
3533
decay = DecayEngine(
3634
half_life=active_config.memory.half_life,

0 commit comments

Comments
 (0)