✨ feat: 測資產生器新增 distinct 與 prefix_count 參數欄位 - #2
Merged
Conversation
## 📋 變更細節分析 - ParamSpec 全部變體新增 `distinct` / `prefix_count` 頂層欄位(預設 false,未宣告時行為完全不變):`distinct: true` 保證同行值兩兩相異(int / enum 支援,字串型別與 faker 於建構期報錯);`prefix_count: true` 以 join 語意在行首輸出實際個數 n(APCS 格式,n = 0 時輸出恰為 `0`) - 建構期驗證擴充:值域大小以 i128 寬運算計算並驗證 ≥ count.max(全 i64 範圍不溢位)、enum values 去重後驗證,失敗即回傳描述性錯誤,不默默生出重複值 - 不放回抽樣採門檻式混合策略:值域 ≤ 4 × count.max 走展開 + partial Fisher–Yates(緊繃情境輸出隨機排列);值域大走 rejection sampling + HashSet(單次碰撞機率 < 1/4) - conformance 測試改為「JSON 資料檔 + Rust harness」形態:26 個 fixtures 對應需求追溯矩陣 M1–M22 與硬化案例,params 與宣告式期望為語言中立資料,為未來多實作共用預留 - 品質檢查(固定 seed):Q1 輸出順序 smoke test(兩組參數)、Q2 選值均勻性卡方檢定(df=19、臨界值 43.82)、Q3 效能參考測試(release 組態、單行 < 100 ms) - Round 1 audit + 三方 adversarial review 硬化:ParamSpec 與 CountSpec 加 `deny_unknown_fields`(拼錯欄位名建構期報錯,不再靜默停用保證);`pub mod` 收回改開窄 API `generate(params_json, count, rng) -> Result`(消除繞過驗證的 panic 路徑);`generate_challenge` 的 count 參數加 10^4 上限;rng 內部 positional tuple 改具名 CommonFields 存取器 - 移除 rng.rs 兩處 `debug_assert!`(release 被 strip 的假安全),驗證全數由 parse 層以 Result 承擔;CI 兩個 Rust 測試步驟加 `--all-features` 並新增 `cargo test --release` 步驟 - 新增 crate README(欄位規格、逐型別支援表、全部邊界行為、separator 責任註記)與 changeset(minor) - Spectra change artifacts:proposal / design(含 Round 1 硬化決策紀錄)/ spec delta(含 Unknown parameter fields are rejected requirement)/ tasks 17 項全數完成 ## 🔧 技術影響 - `@cxphoenix/vp-wasm-coding` 將出 minor 版:params schema 新增兩個向後相容欄位;帶未知鍵的 params 從靜默忽略改為建構期報錯(M22 窄讀下的有意收緊,conforming params 不受影響) - Rust crate 公開 API 新增 native 入口 `generate`;`generate_challenge` WASM 簽名不變 - `deny_unknown_fields` 與 serde `flatten` 互斥——未來 R3 若需 flatten 須另行提供此保證(已記錄於 design.md)
## 📋 變更細節分析 - `.github/workflows/ci.yml` 補回 `cargo test`(default features)步驟,形成 default / `--all-features` / `--release --all-features` 三步:Round 1 以 `--all-features` 取代 bare test 造成出貨組態(wasm-pack 以 faker off 建置)在 CI 零覆蓋,`cfg(not(feature = "faker"))` 的拒絕測試也不再執行 - `lib.rs` 的 `MAX_TESTCASES` doc comment 改為誠實敘明僅上界輸入筆數,不再宣稱防住 unbounded allocation(aggregate byte budget 依審查裁決進 backlog,須先補需求 I.5 錯誤列) - `rng.rs` 的 `partial_shuffle_take` 加 release 生效的自我描述 `assert!`(與現行 panic 行為等價,僅將 rand 內部的模糊訊息換成指明違反不變量的訊息) - README separator 責任註記補 enum values 含分隔字元的情形 - design.md 記錄 Round 2 裁決與 backlog(aggregate budget、重複 param key 拒絕、useWasmGenerator discriminated result、WASM 效能量測);tasks.md 補 7.1–7.2 硬化條目 ## 🔧 技術影響 - 無行為變更:合法輸入輸出位元級不變,僅 CI 覆蓋率、診斷訊息與文件正確性 - Round 2 審查確認:rejection 迴圈上限、separator 建構期拒絕、distinct 改名等提案為 Round 1 已否決案重提,維持不採納;useWasmGenerator 吞錯經查證 UI 實有錯誤訊息(audit 高估),列 JS 端後續獨立 change
## 📋 變更細節分析 - `rng.rs` 的 distinct 抽樣分支由「值域 ≤ 4 × count.max」改為「≤ 4 × n(實際抽出個數)」:count 區間寬、實際只抽少量值時不再展開整個值域(如 count 1..10^4、值域 3×10^4 抽 1 值原需展開 3×10^4 筆)。對外契約不變(需求明文演算法不指定),既有固定 seed 測試因參數組皆 count.min = count.max 而位元不變 - `generate_distinct` 的 `_ =>` 萬用臂展開為顯式 variant 列表:新增 ParamSpec 型別時 rng 端成為編譯錯誤而非 release 期 panic(與 CommonFields 同一原則) - `random_len` 與 parser 的 `validate_len` 統一使用 `div_ceil`(消除潛在溢位不對稱) - CI 補第四步 `cargo test --release`(default features = wasm-pack 出貨組態)滿足 AC-C1-5「正式發行組態產物」字面要求;release 步驟註解改掛 AC-C1-5 論據(src 已無 debug_assert,舊論據過時) - `quality.rs` 修正 Q1 secondary 的錯誤路徑註解(實走 rejection 而非展開),並增列第三組 shuffle-path 順序守門(值域 [1,50]、n=20)——需求 Part II 的兩組參數在本實作門檻策略下皆落 rejection 分支,展開洗牌分支原本沒有系統性排序守門 - README 補「`multiple_of` < 1 視同 1」註記;design.md/tasks.md 同步 Round 3 決策與否決紀錄(multiple_of: 0 建構期拒絕依凍結判例否決進 backlog) ## 🔧 技術影響 - 無對外行為變更:輸出契約、公開 API、fixtures 期望全數不動;效能在寬 count 區間情境改善 - 兩處測試/程式註解的數學錯誤修正,避免後續 reviewer 誤判路徑覆蓋
## 📋 變更細節分析 - `.changeset/distinct-prefix-count.md` 補記「未知欄位名從靜默忽略改為建構期報錯」的行為收緊警示(升級端唯一會讀到的 artifact,原本漏記此 breaking 收緊) - root README 補 `generatorParams` schema 指引連結(JS 使用者原本沒有可達路徑讀到「未知鍵拒絕」說明) - fixtures m14/m15 補 `error_contains` 錨定(原本任何錯誤都能通過,追溯宣稱未被驗證) - design.md 修正兩處與實作不符的過時敘述(門檻 4 × count.max → 4 × n;飽和運算 → i128 寬型別),backlog 補 harness deny_unknown_fields struct 化與 rejection 路徑均勻性測試兩項 - rng.rs 緊繃情境註解由 domain == count.max 改述為 domain == n ## 🔧 技術影響 - 無程式行為變更;四種測試組態全綠
## 📋 變更細節分析 - change 目錄移入 `openspec/changes/archive/2026-07-27-add-distinct-prefix-count/`(含 proposal / design / spec delta / tasks 與 unarchive snapshot) - delta spec 套用回主規格 `openspec/specs/random-input-generator/spec.md`:新增 5 條 requirements(Distinct values within a line、Prefix count line format、Construction-time validation for distinct feasibility、Backward compatibility of new fields、Unknown parameter fields are rejected),含 @trace 注入 ## 🔧 技術影響 - Spectra workflow 完結:propose → apply → 3 輪 audit/adversarial review → archive;主規格自此為 distinct / prefix_count 行為的單一真相來源
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎯 動機與背景 (Motivation & Context)
資料結構系列示範題(deque / stack 模擬)需要「一行 n 個相異數字」與 APCS 慣例的「行首宣告個數」輸入格式。現行
random-input-generator的count抽樣為獨立抽選——無相異保證、也無法在行首自動輸出個數;當題目的答案公式依賴元素相異性時(如數字重組計數題的2^N − 2),含重複值的測資會把寫「符合題意暴力解」的學生誤判為 WA,是公平性問題。需求規格經四輪 adversarial review 收斂(v4.1,追溯矩陣 M1–M22),本 PR 依 Spectra workflow 落地:propose → apply(TDD)→ 三輪 audit + multi-agent adversarial review → archive。
📝 變更內容 (What Changed)
distinct: true(參數規格頂層欄位,預設false):同行值兩兩相異。int與enum(values 先去重)支援;字串型別與faker於建構期報錯。抽樣採門檻式混合策略:值域 ≤ 4 × n 走展開 + partial Fisher–Yates(緊繃情境輸出隨機排列),否則 rejection sampling + HashSet(碰撞機率 < 1/4)。prefix_count: true(預設false):行首以count.separatorjoin 語意輸出實際個數n(APCS 的n x1 … xn格式);適用所有型別;n = 0時該行輸出恰為0。count.max(全 i64 範圍不溢位);驗證於 release 組態同樣生效。deny_unknown_fields(拼錯欄位名報錯,不再靜默停用保證)、窄公開 APIgenerate()取代pub mod(消除繞過驗證的 panic 路徑)、generate_challenge的count參數加 10^4 上限、內部不變式編譯期化(具名CommonFields、顯式 match 臂)。--all-features/--release/--release --all-features),release + default 即 wasm-pack 出貨組態。openspec/changes/archive/2026-07-27-add-distinct-prefix-count/。🔀 變更類型 (Type of Change)
🧪 測試方式 (How to Test)
cd crates/random-input-generatorcargo test(default,81+ 測試)與cargo test --release(含 Q3 效能)cargo test --all-features與cargo test --release --all-features(faker 路徑){"n":{"type":"int","min":1,"max":5,"count":{"min":5,"max":5},"distinct":true,"prefix_count":true}}→ 輸出形如5 3 1 5 2 4(行首個數 + 1..5 的隨機排列)✅ 自我檢查清單 (Checklist)
🔗 相關連結 (References)
.spectra/requirements/testcase-generator-distinct-prefix-count.md(v4.1)openspec/changes/archive/2026-07-27-add-distinct-prefix-count/(含三輪審查決策紀錄與 backlog)