feat: implement reproducible PROTEAN baseline pipeline

This commit is contained in:
willtanoe committed 2026-09-24 17:39:00 +00:00
1 parent 2cc6a9859e
commit 0aa8e2ba79
93 files changed
+8173 -658

No files matched your search

+197 -262
View File
@@ -1,11 +1,11 @@
# Session Handoff
This is the canonical continuation point for the next agent session. It is written to be
readable without any prior chat history, terminal scrollback, or git history.
readable without prior chat history, terminal scrollback, or git history.
Session date: 2026-09-24
Session type: research study, baseline investigation, architecture planning, dataset
inspection, minimal bootstrap. **No training was run and no experimental sweep was launched.**
Last updated: 2026-09-24 (Session 2, baseline-only checkpoint).
Session 2 type: minimum reproducible baseline implementation + smoke test, then cleanup so
the checkpoint contains **baseline only**. **No full-scale training and no beta sweep.**
---
@@ -13,7 +13,7 @@ inspection, minimal bootstrap. **No training was run and no experimental sweep w
Build the code and experiment infrastructure for a thesis study that modifies **only the
server-side prototype aggregation** of PROTEAN (Chennoufi et al., 2025), a federated
intrusion-detection framework. The proposed mechanism weights each contributing client's
intrusion-detection framework. The planned mechanism weights each contributing client's
class prototype by its class sample support:
```
@@ -22,325 +22,260 @@ S_j = { i | N_ij > 0 and a valid local prototype C_ij exists }
beta in {0.0, 0.25, 0.5, 0.75, 1.0}
```
Goal: characterise when support weighting helps or hurts rare attack detection under
non-IID data, selecting beta on a validation set. `beta = 0` is a control, **not** assumed
identical to the original baseline.
**This checkpoint contains the baseline only.** The proposed beta-weighted aggregation and
the `equal_available` control are intentionally NOT implemented yet; they are deferred to
the later beta/controls phase, which must not start until the baseline is verified.
## 2. Authoritative source
- `planningawal/PROTEAN_Revisi_Lurus.md` — the authoritative research specification.
- The entire `planningawal/` directory is **immutable / read-only**. Do not edit, create,
rename, move, delete, reformat, overwrite, or generate reports inside it. It must not
appear in any "files modified" list.
- Verified unchanged this session: SHA-256
`9ba1d7beb94354db0c4b588199fb1e2823aec8a23be1625ec09a756507fbcb89` (12,050 bytes).
- `planningawal/PROTEAN_Revisi_Lurus.md` — authoritative research specification.
- `planningawal/` is **immutable / read-only**. Verified unchanged:
SHA-256 `9ba1d7beb94354db0c4b588199fb1e2823aec8a23be1625ec09a756507fbcb89`
(only file in `planningawal/`).
## 3. Dataset locations (read-only source data)
- `~/datasets/X-IIoTID/X-IIoTID-dataset.csv`
- `~/datasets/5G-NIDD/5G-NIDD.csv`
- `~/datasets/X-IIoTID/X-IIoTID-dataset.csv` — SHA-256
`7b9290057ee42e784da3c0d84b781815502c9205c74175c96374e71a5ffd98a0` (mtime 2021-10-07)
- `~/datasets/5G-NIDD/5G-NIDD.csv` — SHA-256
`fa36f80859585f474504ca69eb951a079b35145537976c86b00aae3aab46ee59` (mtime 2023-02-18)
Do not move, rename, overwrite, modify, or copy the full raw files into the repository. Use
configurable external paths (`configs/datasets/datasets.yaml`, with env overrides).
Re-verified unchanged. Paths resolve from `configs/datasets/datasets.yaml` with env
overrides (`PROTEAN_XIIOTID_RAW_PATH`, `PROTEAN_5GNIDD_RAW_PATH`). Raw files are never
modified or copied into the repo.
Recorded SHA-256:
## 4. Current repository state
- X-IIoTID: `7b9290057ee42e784da3c0d84b781815502c9205c74175c96374e71a5ffd98a0`
- 5G-NIDD: `fa36f80859585f474504ca69eb951a079b35145537976c86b00aae3aab46ee59`
## 4. Current repository tree
Baseline code:
```
perdalam-protean/
├── README.md
├── pyproject.toml
├── .gitignore
├── planningawal/ # IMMUTABLE (read-only)
│ └── PROTEAN_Revisi_Lurus.md
├── configs/
│ ├── datasets/datasets.yaml
│ ├── experiments/experiment_protocol.yaml
│ └── models/protean_cnn.yaml
├── docs/
│ ├── research/
│ │ ├── RESEARCH_SPEC_INTERPRETATION.md
│ │ ├── DATASET_INSPECTION.md
│ │ ├── IMPLEMENTATION_PLAN.md
│ │ └── EXPERIMENT_PROTOCOL.md
│ ├── baseline/
│ │ └── PROTEAN_BASELINE_INVESTIGATION.md
│ └── handoff/
│ └── SESSION_HANDOFF.md
├── src/protean_research/
│ ├── __init__.py
│ ├── aggregation/
│ │ ├── __init__.py
│ │ └── prototype_aggregation.py
│ └── utils/
│ ├── __init__.py
│ └── config.py
├── tests/
│ └── test_prototype_aggregation.py
├── scripts/ # .gitkeep only (tracked)
├── artifacts/
│ ├── partitions/ # tracked: deterministic manifests (.gitkeep now)
│ ├── analysis/ # tracked: small analysis outputs (.gitkeep now)
│ ├── processed/ # ignored (regenerable)
│ └── checkpoints/ # ignored (regenerable)
└── results/ # ignored (regenerable)
src/protean_research/
├── data/ loading, preprocessing, splits, partition, manifest,
│ characterization, rare_unseen, pipeline
├── models/ protean_cnn, prototypes
├── aggregation/ prototype_aggregation (baseline original_protean ONLY)
├── federated/ client, server, round
├── evaluation/ metrics
└── utils/ config, seeding, integrity
scripts/ run_baseline.py, generate_partitions.py
tests/ 34 baseline-focused tests
artifacts/partitions/ 18 full-data manifests (tracked, small, content-hashed)
artifacts/analysis/ 18 characterization + 18 rare_unseen CSVs (tracked, small)
artifacts/processed/ ignored: preprocessor state + smoke partitions/snapshots
results/ ignored: smoke run outputs
```
`.gitignore` deliberately keeps `artifacts/partitions/` and `artifacts/analysis/`
version-controlled (partition manifests are deterministic, content-hashed, and required for
paired comparisons), while ignoring `artifacts/processed/`, `artifacts/checkpoints/`,
`results/`, `logs/`, and `*.log`. `scripts/` is preserved with a `.gitkeep` placeholder.
`planningawal/` is never ignored.
Environment: `.venv/` exists (gitignored) with numpy 2.5.3, pandas 3.0.6,
torch 2.14.0+cpu, pyyaml 6.0.3, pytest 9.1.1. Use `.venv/bin/python`.
Note: the repository was **not** empty at session start. A partial scaffold already existed
(`configs/*`, `src/protean_research/aggregation/*`, `src/protean_research/utils/config.py`,
`__init__.py` files, and empty `docs/`, `scripts/`, `tests/`, `artifacts/`, `results/`
directories). `docs/` was empty and there was no handoff. That scaffold was kept and verified;
it is not the product of this session.
## 5. What was completed this session
## 5. Work completed this session
1. Froze every previously-PROVISIONAL protocol value in
`configs/experiments/experiment_protocol.yaml` and `docs/research/EXPERIMENT_PROTOCOL.md`.
2. Dataset config: explicit `categorical_columns`, `drop_duplicate_rows`, missing tokens,
fixed 5G-NIDD `Unnamed: 0` (quoted).
3. Data foundation (`data/`): read-only loading, deterministic canonicalisation, leak-free
train-fitted preprocessing, deterministic stratified 70/10/20 split, Dirichlet partition
with content-hashed manifests and `N_ij`, characterization, rare/unseen metadata.
4. Model (`models/`): baseline CNN, parameter averaging, embedding extraction, local
prototypes, global prototype collection, nearest-prototype inference.
5. Baseline aggregation (`aggregation/`): `original_protean` only. The proposed
`support_weighted` and the `equal_available` control were **removed** so the checkpoint
is baseline only; an unavailable-mode guard raises `ValueError`.
6. Federated loop (`federated/`): local update (CE + prototype alignment + model
alignment), server model/prototype aggregation, round orchestration, round-0 snapshot.
7. Evaluation (`evaluation/`): accuracy, macro/weighted F1, per-class P/R/F1, rare/unseen.
8. Scripts: `generate_partitions.py` (18 manifests, full data, reload-verified);
`run_baseline.py` (one baseline condition; no beta/mode options).
9. Tests: 34 baseline-only tests, all passing.
10. Smoke test: baseline-only on both datasets.
11. Docs: `docs/baseline/BASELINE_IMPLEMENTATION.md` rewritten with provenance tags.
1. Read the full specification and produced a tagged interpretation
(`docs/research/RESEARCH_SPEC_INTERPRETATION.md`).
2. Investigated authoritative PROTEAN sources (paper, ESORICS/Springer, HAL, author PhD
thesis) and searched for official code.
3. Established baseline aggregation semantics question-by-question with evidence tags
(`docs/baseline/PROTEAN_BASELINE_INVESTIGATION.md`).
4. Inspected both raw datasets in full (read-only) and recorded shapes, label distributions,
missingness, duplicates, identifiers, and mismatches
(`docs/research/DATASET_INSPECTION.md`).
5. Verified the pre-existing config/path-resolution scaffold and aggregation module by running
them.
6. Wrote the implementation architecture (`docs/research/IMPLEMENTATION_PLAN.md`) and the
experiment protocol (`docs/research/EXPERIMENT_PROTOCOL.md`).
7. Added a minimal bootstrap: `pyproject.toml`, `README.md`, and dependency-free unit tests
for the aggregation math (`tests/test_prototype_aggregation.py`, 9 tests, all passing).
8. Recorded dataset and source hashes for integrity verification.
9. Wrote this handoff.
## 6. Baseline decisions and provenance
## 6. Evidence and findings
Full detail in `docs/baseline/BASELINE_IMPLEMENTATION.md`. Summary:
### 6.1 Official PROTEAN source status
- **No official PROTEAN code exists**, so no decision is source-confirmed by code.
- **PAPER**: architecture, `mu = 0.1`, 10 rounds / 3 local epochs, 80/20 test, equal `1/M`
model averaging, end-of-round mean-embedding prototypes, nearest-prototype inference.
- **REPRODUCTION ASSUMPTION (project decision)**: `original_protean` participant rule is
`S_j` with equal `1/|S_j|` weights. The paper writes `1/M` but is ambiguous for classes
missing on a client; this assumption follows the thesis sentence that prototypes are
shared only for locally observed classes. It is **not** treated as verified.
- **PROJECT DECISION**: `lambda = 1.0`; Adam `lr = 1e-3`; batch size 256; kernel size 3;
stratified 70/10/20 split with an added validation set; seeds `{0,1,2}`;
preprocessing recipe; per-class Dirichlet allocation; per-client eval partitioning.
- **INFERRED**: per-sample prototype alignment (FedProto-style reading of Eq. 3); round-0
handling (no prototypes, prototype term skipped).
- **UNRESOLVED**: whether a literal `1/M` missing-class reading differs from `S_j`.
- **No official code exists publicly (as of 2026-09-24).**
- Author GitHub `sarachn` (Sara Chennoufi) has only `FATE-LLM` (fork) and `SecLLMHolmes` —
neither is PROTEAN.
- GitHub repository search `PROTEAN federated prototype` → 0 results; `grep.app` → none.
- The unrelated GitHub user `Chennoufi` has only a `septembre` repo — do not chase it.
- No code/artifact/supplementary link in the arXiv HTML, HAL record, or thesis text.
- **Consequence: the baseline must be reproduced from the paper/thesis.**
## 7. Seeds (explicit)
Primary sources:
- Exact values: **`{0, 1, 2}`**.
- Rationale: the paper averages over three random seeds but names none, so the values are
**not source-confirmed**. `{0, 1, 2}` is the minimal three-seed set and is an explicit
**project decision**.
- Each seed deterministically controls the split, Dirichlet partition, model
initialisation and batch order, via `protean_research.utils.seeding.derive_seed`.
- The set is identical across all baseline conditions.
- arXiv:2507.05524v1 (7 Jul 2025), ESORICS 2025 pp. 103–125,
DOI `10.1007/978-3-032-07884-1_6`.
- HAL `hal-05379203`.
- Author PhD thesis `tel-05490927` (195 pages, 2025) — restates PROTEAN with extra detail.
## 8. Manifests (18)
### 6.2 Baseline semantics discovered
`artifacts/partitions/` holds **18** manifests from `2 datasets × 3 alphas × 3 seeds`.
They are content-hashed, reload-verified, and reused by later variants for pairing. Sample
indices are regenerated deterministically from the stored recipe/RNG seed and checked
against the stored `N_ij` and hash, keeping manifests small.
Confirmed from the paper/thesis:
## 9. Verification performed this session
- Local prototype (Eq. 1 / 5.4): mean embedding over the client's class-`j` samples.
- Server aggregation (Eq. 2 / 5.5): `omega = (1/M) sum_i omega_i`,
`Cbar_j = (1/M) sum_i C_ij` (equal, no `N_ij`).
- Local loss (Eq. 3 / 5.6): cross-entropy + `lambda * ||C_ij - Cbar_j||^2` +
`(mu/2) * ||omega_i - omega^{t-1}||^2`, with `mu = 0.1`.
- Inference: nearest global prototype by squared L2 (thesis Eqs. 5.11–5.13).
- Model: 2 Conv1D (64, 128 filters) + ReLU + maxpool + dropout (0.2, 0.5), flatten,
dense 128, log-softmax head.
- Setup: 10 clients, 80/20 train/test, 10 rounds, 3 local epochs,
`alpha in {0.75, 0.5, 0.25}`.
- Thesis (Sec. 5.3.6): "prototypes are shared only for locally observed classes".
- `python -m pytest -q` -> **34 passed**.
- Full partition generation on both datasets: 18 manifests, each reload-verified.
- Non-IID check (seed 0): X-IIoTID `alpha=0.75` max 1 missing class/client, `alpha=0.25`
up to 3; 5G-NIDD similar. Qualitatively consistent with the paper setting.
- Baseline-only smoke on X-IIoTID (3000 rows, 4 clients, 2 rounds, 1 epoch): full path
succeeds, ~4.5 s.
- Baseline-only smoke on 5G-NIDD (4000 rows): succeeds.
- No beta/support_weighted code is invoked or present.
- Integrity: `planningawal/` and both raw datasets retain their recorded SHA-256 values.
### 6.3 Missing-class findings (critical)
## 10. Files added this session
- Equation (2)/5.5 sums over all `M` participants, but the paper never states how a missing
class prototype is handled. The thesis implies absent classes are not shared, but the
server denominator (`M` vs number of contributors) is undefined.
- Therefore `beta = 0` over `S_j` is **not** automatically equal to the original baseline;
equality requires the same participant rule. This is the central baseline ambiguity.
- `original_protean` is deliberately **not implemented** in
`src/protean_research/aggregation/prototype_aggregation.py`; it raises
`NotImplementedError` with an explanatory message.
- Additional unknowns: round-0 global-prototype initialisation; how the alignment loss sums
over `j = 1..K` when a client has `N_ij = 0`; per-batch vs end-of-round prototypes;
whether model aggregation is equal `1/M` or FedAvg sample-weighted (the thesis intro says
FedAvg is a weighted average, contradicting Eq. 5.5); numeric value of `lambda`; seed values;
feature preprocessing.
Source: `src/protean_research/data/{__init__,loading,preprocessing,splits,partition,manifest,
characterization,rare_unseen,pipeline}.py`,
`src/protean_research/models/{__init__,protean_cnn,prototypes}.py`,
`src/protean_research/federated/{__init__,client,server,round}.py`,
`src/protean_research/evaluation/{__init__,metrics}.py`,
`src/protean_research/utils/{seeding,integrity}.py`.
### 6.4 Dataset findings
Scripts: `scripts/run_baseline.py`, `scripts/generate_partitions.py`.
- X-IIoTID: 820,834 × 68; labels `class1` (19), `class2` (10 general), `class3` (binary).
`class2` benign = `Normal`. After dropping `crypto-ransomware`: 9 classes. `'-'`
placeholders in 42 columns; 6,222 duplicate rows; label typo `Lateral _movement`.
Identifiers: `Date`, `Timestamp`, `Scr_IP`, `Scr_port`, `Des_IP`, `Des_port`.
- 5G-NIDD: 1,215,890 × 52; `Attack Type` (9 values, benign = `Benign`), `Label` binary,
`Attack Tool` (6). 8 attack classes + Benign = 9. Heavy structural missingness (e.g. `dVid`
99.83%, `dTos` 77.56%); 1 duplicate row. Identifiers: empty-header index, `Seq`, `Offset`.
- Both map to PROTEAN's 9-class setup, but PROTEAN's exact preprocessing is unspecified and
must be frozen here.
Tests: `tests/test_data_pipeline.py`, `tests/test_partition.py`, `tests/test_prototypes.py`,
`tests/test_baseline_aggregation.py`, `tests/test_metrics.py`, `tests/test_federated_smoke.py`.
## 7. Decisions made
Docs: `docs/baseline/BASELINE_IMPLEMENTATION.md`.
1. **Treat `planningawal/` as immutable** and keep all outputs elsewhere.
2. **Do not implement `original_protean` until its semantics are verified.** Encode only the
unambiguous modes (`support_weighted`, `equal_available`). Rationale: avoid silently
assuming baseline behaviour.
3. **Keep `equal_available` as a dormant control**, introduced only if baseline investigation
shows the participant rule differs from `S_j` (per the specification).
4. **Centralise dataset paths** in `configs/datasets/datasets.yaml` with env overrides; never
hardcode in source.
5. **Separate raw and generated data**; generated outputs under `artifacts/`.
6. **Use `class2` for X-IIoTID and `Attack Type` for 5G-NIDD** as the multi-class labels, drop
`crypto-ransomware`, treat `Normal`/`Benign` as benign. Matches the paper.
7. **Keep the pre-existing scaffold** (configs + aggregation + utils) and extend it minimally
rather than restructuring; no evidence justified a different layout.
8. **Add dependency-free unit tests** for aggregation invariants now; defer data/federated
tests until those modules exist.
9. **Do not initialize git during the planning session** (not requested at the time). A
follow-up checkpoint task then initialized Git and added remote `origin`; see Section 11.
10. **Mark seeds, `lambda`, validation fraction, Dirichlet allocation, and preprocessing as
PROVISIONAL**; they must be frozen before any sweep.
Artifacts (tracked, small): `artifacts/partitions/*.json` (18),
`artifacts/analysis/*.csv` (36).
## 8. Unresolved questions
## 11. Files modified this session
1. Baseline missing-class rule and prototype-aggregation denominator (`M` vs `|S_j|`).
2. Round-0 initialisation of global prototypes for all `K` classes.
3. `lambda` value (paper gives `mu = 0.1` only).
4. Whether model-parameter aggregation is equal or FedAvg sample-weighted.
5. How the prototype alignment loss treats `N_ij = 0` classes.
6. Per-batch vs end-of-round local prototype computation.
7. Validation split fraction and procedure (the paper has no validation set).
8. Exact Dirichlet allocation algorithm (affects realised `N_ij`).
9. Exact seed values and whether metrics are averaged per client then per seed.
10. Feature preprocessing: encoding, scaling, `'-'`/NaN handling, duplicate-row policy.
11. ~~Whether to initialize git to protect the immutable source.~~ Resolved: Git was
initialized in the follow-up checkpoint task (see Section 11).
12. Compute budget: no timing measured; a profiling smoke test is required before any sweep.
## 9. Files created this session
- `docs/research/RESEARCH_SPEC_INTERPRETATION.md`
- `docs/research/DATASET_INSPECTION.md`
- `docs/research/IMPLEMENTATION_PLAN.md`
- `configs/datasets/datasets.yaml`
- `configs/experiments/experiment_protocol.yaml`
- `docs/research/EXPERIMENT_PROTOCOL.md`
- `docs/baseline/PROTEAN_BASELINE_INVESTIGATION.md`
- `docs/handoff/SESSION_HANDOFF.md`
- `docs/research/IMPLEMENTATION_PLAN.md`
- `README.md`
- `pyproject.toml`
- `.gitignore`
- `tests/test_prototype_aggregation.py`
- `src/protean_research/aggregation/__init__.py`
- `src/protean_research/aggregation/prototype_aggregation.py`
- `src/protean_research/models/prototypes.py`
- `src/protean_research/federated/server.py`
- `src/protean_research/federated/round.py`
- `scripts/run_baseline.py`
- tests (baseline-only aggregation suite; beta tests removed)
## 10. Files modified this session
`planningawal/` was not touched.
- None. No existing file was edited. `planningawal/` was not touched (and must not be).
## 12. Removed from this checkpoint (deferred to beta/controls phase)
Pre-existing files (present at session start, verified but not modified):
`configs/datasets/datasets.yaml`, `configs/experiments/experiment_protocol.yaml`,
`configs/models/protean_cnn.yaml`, `src/protean_research/__init__.py`,
`src/protean_research/aggregation/__init__.py`,
`src/protean_research/aggregation/prototype_aggregation.py`,
`src/protean_research/utils/__init__.py`, `src/protean_research/utils/config.py`.
- `support_weighted` aggregation code and `beta` parameters.
- `equal_available` mode (redundant with the baseline `S_j` rule; only needed if a later
investigation shows the baseline participant rule differs).
- `--mode` / `--beta` CLI options in `run_baseline.py`.
- Beta-specific tests (`beta = 0/1`, single-contributor/equal-support beta invariance,
normalised beta weights, the `original_protean == support_weighted(beta=0)` equivalence
test). The former `tests/test_prototype_aggregation.py` was removed and folded into a
baseline-only `tests/test_baseline_aggregation.py`.
- Any claim that `original_protean == support_weighted(beta=0)` demonstrates equivalence
with original PROTEAN. That was at most an internal implementation-equivalence check and
is no longer present in code or docs.
## 11. Git status
## 13. Git status
The planning session ran with **no Git repository**. A follow-up checkpoint task then
initialized Git:
Not committed (no commit was requested). `git status --short` shows modified tracked files
(configs, docs, aggregation package, federated modules, README, run script) plus untracked
source/tests/scripts/docs, the 18 partition manifests and 36 analysis CSVs. `AGENTS.md` was
already untracked before this session. `.venv/`, `artifacts/processed/`, `results/`,
`logs/`, and `*.log` are ignored. No checkpoints or raw datasets are tracked.
- Branch: `main`
- Remote `origin`: `git@github.com:willtanoe/prototype-agregation.git`
- Initial checkpoint commit: `chore: checkpoint PROTEAN research planning and architecture`
(exact hash reported in the checkpoint task's terminal summary; deliberately not embedded
here to avoid a recursive "hash inside the commit" loop).
- `.gitkeep` placeholders were added for `scripts/`, `artifacts/partitions/`, and
`artifacts/analysis/`. `artifacts/processed/`, `artifacts/checkpoints/`, `results/`,
`logs/`, and `*.log` are ignored.
- `planningawal/PROTEAN_Revisi_Lurus.md` is tracked exactly as-is and was not modified.
- Raw datasets are outside the repository and are not tracked.
## 14. Unresolved issues / blockers
Because this is the initial commit, `planningawal/` was verified with SHA-256 hashing and
directory listing rather than `git diff`.
1. **Baseline is implemented but not yet VALIDATED.** The `original_protean` participant
rule is a reproduction assumption, not verified behavior.
2. `lambda`, optimiser/schedule, and round-0 handling are unverified.
3. No full-scale run has been timed; compute feasibility of a real sweep is unmeasured
(X-IIoTID ~570k train rows, 5G-NIDD ~851k; CPU-only).
4. Per-client evaluation partitioning is a project decision.
5. Prototype-alignment form (per-sample vs class-mean) is a documented inference.
6. Whether the literal `1/M` missing-class reading differs from the `S_j` assumption is
open; a deliberate control is needed in the verification phase.
## 12. Verification performed
## 15. Exact next task
- Read the full specification (118 lines).
- Read the full paper HTML and extracted the author PhD thesis text (195 pages).
- GitHub API searches (author account, repositories), DuckDuckGo, `grep.app`.
- Full pandas load of both datasets; recorded shape, dtypes, label counts, missingness,
duplicates, identifier columns.
- SHA-256 of both datasets and of `planningawal/PROTEAN_Revisi_Lurus.md`.
- Ran the pre-existing aggregation module and config resolver (modes, weights, path
resolution, `original_protean` raises `NotImplementedError`).
- Ran `python -m pytest -q` in a temporary venv: **9 passed**.
- Confirmed no training or sweep was launched.
- Final check: `planningawal/` contains only `PROTEAN_Revisi_Lurus.md` with the same hash;
raw datasets retain the same hashes and mtimes.
**Baseline validation and reproduction verification — NOT beta weighting.**
Checkpoint task (follow-up):
Next session should:
- `git rev-parse --is-inside-work-tree` before init: not a repository.
- Searched the whole tree for `*.csv`, `*.parquet`, `*.feather`, `*.pkl`, `*.pickle`, model
checkpoints: none present; largest file is the 12 KB spec.
- Scanned tracked text for secret patterns (`API_KEY`, `SECRET`, `TOKEN`, `PASSWORD`,
`PRIVATE KEY`, `BEGIN OPENSSH`, `BEGIN RSA`, `sk-`, `ghp_`, `github_pat_`): none found.
- `find planningawal -maxdepth 2 -type f` → only `PROTEAN_Revisi_Lurus.md`.
- Re-ran `pytest`: 9 passed.
1. Run one full-data baseline condition (e.g. X-IIoTID, `alpha=0.5`, `seed=0`,
`original_protean`) with measured wall-clock and memory; record it.
2. Inspect the run: per-class precision/recall/F1, per-client rare metrics, confusion
matrix. Check plausibility and missing-class-client behavior.
3. Stress-test the `S_j` reproduction assumption: compare against a literal `1/M`
omitted-class reading to quantify the effect of the assumption (introduce the control
only for this investigation, clearly marked).
4. Add a deterministic end-to-end baseline regression test pinning a small result.
5. Only after the baseline is demonstrably verified and recorded, begin the paired beta
comparison on a single `(dataset, alpha, seed)` before any grid.
## 13. Exact next task
Do **not** launch the full grid, and do not change the architecture, loss coefficients, or
inference rule.
**Implement the deterministic data foundation, and freeze the remaining protocol choices
before coding.**
## 16. Important commands
Concretely, the next session should:
```bash
# Tests
.venv/bin/python -m pytest -q
1. In `docs/research/EXPERIMENT_PROTOCOL.md`, replace the PROVISIONAL entries with explicit
frozen decisions and rationale for: preprocessing recipe, duplicate-row policy,
`'-'`/NaN handling, the Dirichlet allocation algorithm, the train/validation/test split
procedure and fraction, the seed set, `lambda`, batch size, and learning rate. These are
project decisions because the paper does not specify them; label them as reproduction
deviations.
2. Create `src/protean_research/data/` with `loading.py`, `preprocessing.py`, `splits.py`,
`partition.py`, `manifest.py`, `characterization.py`, `rare_unseen.py` implementing the
flow in `docs/research/IMPLEMENTATION_PLAN.md` Section 3.
3. Persist one partition manifest per `(dataset, alpha, seed)` under `artifacts/partitions/`
with a content hash, and derive rare/unseen metadata from the training split.
4. Add tests for determinism of partition generation (strategy item 8) and identical manifest
reload (item 9), plus the non-IID characterization fields.
# Generate / verify all partition manifests (full data, ~30 s)
.venv/bin/python scripts/generate_partitions.py
Do **not** start model training or a beta sweep. The baseline missing-class rule is still
unresolved, so `original_protean` remains unimplemented.
# Baseline smoke on both datasets (writes only to ignored dirs)
.venv/bin/python scripts/run_baseline.py --dataset xiiotid --alpha 0.5 --seed 0 \
--max-rows 3000 --sample-from 60000 --clients 4 --rounds 2 --local-epochs 1
.venv/bin/python scripts/run_baseline.py --dataset 5gnidd --alpha 0.25 --seed 1 \
--max-rows 4000 --sample-from 60000 --clients 4 --rounds 2 --local-epochs 1
## 14. Recommended next-session prompt
# Full-data baseline for one condition (next session; expect long CPU runtime)
.venv/bin/python scripts/run_baseline.py --dataset xiiotid --alpha 0.5 --seed 0 \
--clients 10 --rounds 10 --local-epochs 3
```
## 17. Recommended next-session prompt
```
You are continuing the perdalam-protean research repository.
You are continuing the perdalam-protean research repository (Session 3).
FIRST, read these two files completely:
FIRST, read completely:
1. docs/handoff/SESSION_HANDOFF.md
2. planningawal/PROTEAN_Revisi_Lurus.md
2. docs/baseline/BASELINE_IMPLEMENTATION.md
3. docs/research/EXPERIMENT_PROTOCOL.md
Then read, as needed:
- docs/research/IMPLEMENTATION_PLAN.md
- docs/research/EXPERIMENT_PROTOCOL.md
- docs/research/DATASET_INSPECTION.md
Then read as needed:
- planningawal/PROTEAN_Revisi_Lurus.md
- docs/baseline/PROTEAN_BASELINE_INVESTIGATION.md
- docs/research/IMPLEMENTATION_PLAN.md
Critical rules:
- planningawal/ is immutable. Do not edit/create/move/rename/delete anything inside it.
- ~/datasets/X-IIoTID/X-IIoTID-dataset.csv and ~/datasets/5G-NIDD/5G-NIDD.csv are
read-only external source data. Do not modify or copy them into the repo.
- Do NOT run full training or an experimental sweep.
- This checkpoint is BASELINE ONLY. Do NOT add the proposed support_weighted/beta code
or the equal_available control until the baseline is verified.
- Do NOT launch the full alpha x seed x dataset x beta sweep.
Your task is Section 13 of the handoff: first freeze the PROVISIONAL protocol decisions in
docs/research/EXPERIMENT_PROTOCOL.md, then implement the deterministic data foundation in
src/protean_research/data/ with partition-manifest persistence, rare/unseen metadata, and
tests for partition determinism and manifest reload.
Your task is Section 15 of the handoff: BASELINE VALIDATION AND REPRODUCTION
VERIFICATION. Run one full-data baseline condition with measured runtime, inspect its
per-class/per-client behavior, stress-test the S_j participant-rule assumption, and add a
deterministic end-to-end baseline regression test. Record everything in
docs/baseline/BASELINE_IMPLEMENTATION.md and update docs/handoff/SESSION_HANDOFF.md.
Start by reading the handoff, then continue from the documented state. Update
docs/handoff/SESSION_HANDOFF.md at the end of your session.
Use .venv/bin/python for all Python commands.
```