feat(pr): offline Prompt Maturity Score in share pr post#152
Conversation
Add src/prompt_score.rs: a no-LLM, classical-NLP score of how well an engineer prompts an AI coding agent. score_prompt()/score_branch() combine seven weighted sub-signals (specificity .24, control .24, context .18, structure .10, lexical diversity .10, clarity .08, adequacy .06) into a 0-100 composite with nascent..exemplary levels. Design locked with the codex agent over i5h. Key properties: - readability is a bounded trapezoid band (not lower=worse) computed on a code-masked copy so paths/identifiers don't corrupt syllable counts - specificity nets a NALABS/Femmer weak-word penalty against concreteness - adaptive MATTR (window min(40,max(10,words/2))) for lexical diversity - anti-gaming: per-category keyword caps, repetition factor, hard length caps, and balance gates (cap 69 if context|control<.35, 79 if spec<.45) - branch roll-up = length-weighted mean + coverage/low-confidence Wire into src/pr.rs: a 'prompt NN/100' headline chip, a style-independent [!NOTE] Prompt maturity section with a collapsible per-signal breakdown, and a per-commit maturity line. 18 module tests + 2 render tests; clippy -D warnings clean.
Apply the v1.1 changes agreed with the codex agent over i5h after a
design critique of the heuristic's form:
- Soften the context balance gate: weak context (<.35) no longer hard-
caps a prompt that is already specific (>=.6) AND bounded (control>=.5).
Such a prompt is a legitimate tactical ask ('run cargo test, fix the
clippy warning in src/foo.rs') and the agent often already holds repo
context. control<.35 stays a hard gate; weak context still shows as a
flag. Extracted the policy into apply_balance_gates() + 5 unit tests.
- Honesty wording in the PR section: add 'Heuristic signal of prompt
craft — not a developer rating' disclaimer and rename the breakdown
from 'maturity breakdown' to 'heuristic breakdown', so the 0-100 number
is never read as an objective engineer rating (Goodhart guard).
- Add a calibration TODO naming h5i's outcome signals (test pass/fail,
review flag, churn, revert) for a future empirical-weights PR. Code/doc
only — no commit-metadata schema change (deferred to its own design).
Deferred to v2 (documented): empirical weight calibration, geometric
combination form, per-author trend/profile dashboard, multi-turn session
scoring. 23 prompt_score tests + 2 pr render tests; clippy -D warnings clean.
🪙 100% AI-authored · 2 files · prompt 31/100
Important 🎯 Goal: Design+implement offline Prompt Maturity Score (classical NLP, no LLM API) and surface it in h5i share pr post body
💬 The ask
📍 What shipped
Note 🪴 Prompt maturity: 31/100 · developing · 3 prompts scored (100% of AI commits) 📊 heuristic breakdown
Readability (display-only): Flesch 54 · FK grade 8.9 · Gunning Fog 11.8 Offline classical-NLP score — no LLM. Higher = more specific, bounded, and grounded prompting. Tip ✅ Security scan cleanNo credentials leaked in this branch's diff. h5i scanned every added line against the secret rule pack and found nothing to rotate. Note Duplicate-code scan clean — no copy-paste blocks introduced. 🧠 Reasoning by file — 5874 nodes across 4 lanes, latest 24 only%%{init: {"flowchart": {"nodeSpacing": 42, "rankSpacing": 48, "diagramPadding": 14}, "themeVariables": {"fontSize": "18px"}} }%%
flowchart TB
subgraph lane_0["💭 Reasoning · 9 steps"]
direction LR
n_lane_0_0["THINK · If Codex doesn't respond (it's another agent and may be idle), I'll let …"]:::t
n_lane_0_1["NOTE · DEFERRAL (~/Dev/h5i/src/prompt_score.rs): er author**, no rank-able head…"]:::n
n_lane_0_2["NOTE · DEFERRAL (~/Dev/h5i/src/prompt_score.rs): real data** — the path from ”n…"]:::n
n_lane_0_3["THINK · Let me find a cleaner (less repetitive, higher-clarity) tactical prompt …"]:::t
n_lane_0_4["THINK · Now let me remove the throwaway probe file (only that file — not the tra…"]:::t
n_lane_0_5["THINK · The design changed, so let me refresh the pinned claim (the old one's ga…"]:::t
n_lane_0_6["NOTE · DEFERRAL (~/Dev/h5i/src/prompt_score.rs): weights PR. **No commit-metada…"]:::n
n_lane_0_7["THINK · Good catch — let me investigate the hook configuration rather than guess…"]:::t
n_lane_0_8["THINK · If your view genuinely shows zero `prompt-score`-branch objects with my …"]:::t
n_lane_0_0 --> n_lane_0_1
n_lane_0_1 --> n_lane_0_2
n_lane_0_2 --> n_lane_0_3
n_lane_0_3 --> n_lane_0_4
n_lane_0_4 --> n_lane_0_5
n_lane_0_5 --> n_lane_0_6
n_lane_0_6 --> n_lane_0_7
n_lane_0_7 --> n_lane_0_8
end
subgraph lane_1["📄 src/prompt_score.rs · 11 ops"]
direction LR
n_lane_1_0["EDIT × 5"]:::a
n_lane_1_1["READ × 5"]:::o
n_lane_1_2["EDIT"]:::a
n_lane_1_0 --> n_lane_1_1
n_lane_1_1 --> n_lane_1_2
end
subgraph lane_2["📄 src/pr.rs · 3 ops"]
direction LR
n_lane_2_0["EDIT × 3"]:::a
end
subgraph lane_3["🗂 Other · 1 node"]
direction LR
n_lane_3_0["READ · searched breakdown|test for ”signal|heuristic”"]:::o
end
classDef o fill:#dbeafe,stroke:#1e3a8a,color:#0b1c4a;
classDef t fill:#fef3c7,stroke:#92400e,color:#3f2d05;
classDef a fill:#dcfce7,stroke:#166534,color:#0a2e16;
classDef n fill:#ede9fe,stroke:#5b21b6,color:#221251;
classDef m fill:#e5e7eb,stroke:#374151,color:#0b0f17;
💬 Agent coordination — 25 messages across 7 threadsFrom ✅ ASK · claude → codex · 2026-06-17 21:05 — v1.1 landed (commit 9073343). Both DO-NOW items shipped: (1) context gate softened — extracted apply_balance_gates(): control<.35 hard-caps 69, context<.35 caps ONLY if NOT (spec>=.6 && control>=.5)…
✅ ASK · claude → codex · 2026-06-17 20:57 — Stepping back: is the CURRENT Prompt Maturity Score the best FORM, or did we lock a local optimum? I want a real critique, not a sign-off. My own doubts:
🟡 ASK · codex → claude · 2026-06-17 20:56 — Design review question: is the current Prompt maturity index the best form, or just a good v1? My provisional read: good v1 because it is offline, explainable, hard to game relative to raw keyword sc…
🟡 ASK · codex → claude · 2026-06-17 20:57 — Direct design verdict for your #f2c17 prompt-maturity critique: current index is a strong explainable v1, not the best final form. Highest-impact concern is Goodhart/framing: keep scalar for PR compa… ✅ ASK · codex → claude · 2026-06-17 20:41 — Research addendum for Prompt maturity design:\n\nWhat recent work says:\n- Prompt-engineering surveys frame prompts as task-specific instructions plus context, and categorize modern techniques around…
🟡 ASK · claude → codex · 2026-06-17 20:37 — Follow-up to ASK #2e4737373042e81b. There are now TWO prompt-score designs to reconcile. (A) Your untracked draft src/prompt_score.rs: 5 dims [readability, lexical_diversity(MATTR w=40), specificity,…
🟡 ASK · claude → codex · 2026-06-17 20:33 — Designing a 'Prompt Maturity Score' for h5i: offline (no LLM API), classical NLP, computed over the AI-commit prompts on a branch, surfaced in 'h5i share pr post' body so managers can gauge how well …
Note 🪙 Token reduction — 62 captured tool outputs kept out of context: 125713 → 28912 tokens (77% saved, 96801 tokens). Full output is recoverable with By tool
📜 Per-commit provenance
|
Codex review caught that balance_gate_blocks_context_free_specific_prompt no longer tests what its name claims: its prompt scores spec=0.61, control=0.50 -> tactical=true, so the v1.1 context-gate exemption applies and the prompt is NOT capped. The test passed only vacuously (raw score 40.5 is below 69 regardless of any cap). Replace it with tactical_context_free_prompt_is_exempt_from_context_gate, which asserts the real v1.1 behavior end-to-end: the prompt reads as context-free (context<.35) AND tactical (spec>=.6 && control>=.5), and a high base score survives apply_balance_gates unclamped. 23 tests pass; clippy -D warnings clean.
No description provided.