Skip to content

Plan integration follow-on (D-D): derive the plan bias from prerequisite edges, milestone order and energy demand #25

Closed as not planned

Description

@NetDevAutomate

Origin

  • Owner decision D-D (docs/architecture/plan-integration/HANDOFF-2026-09-16.md §2): "F2 → open a ticket, don't park: a context-derived plan bias (prerequisite edges from the concept store via get_concept_context, milestone order; per-item energy demand from struggle state) — deterministic and rubric-testable. Not an LLM tie-break (unauditable; defeats D-16)."
  • Evidence: rubric row 1 (receipts/now-rubric-2026-09-16.md) — the owner ranked the plan-matching due item first because of what depends on it ("window function is the logical step before decorating it"); the engine ranked it first only because it carried the plan bias. Same answer, different reason; the reason generalises.
  • Full proposal, written from the code on main a5b9f903: proposals/2026-09-16-context-derived-plan-bias.md. Follows on from Integrate Study Plans across Now, Web architect, and MCP #7 (plan integration) and council review 3 F2; not a blocker of Integrate Study Plans across Now, Web architect, and MCP #7.

What to build

Replace the single constant PLAN_RELATED_BIAS = 12 in studyloop/learning/decision.py (rule 5) with a derived bias from three deterministic inputs, each its own rule with its own rubric row, bounded so the "bias, never a filter" invariant holds (a clearly more-urgent unrelated candidate must still win):

Rule Input Signal
5a — plan relevance (today's rule 5) plan refs / key intersection the existing +12, as today
5b — prerequisite order learning/mastery.py::list_dependencies(topic) edges with relation_type == "prerequisite" (already consumed by weak_links_for_topic) a candidate whose concept is a prerequisite of an open milestone's concept in a matchable plan gains a small bonus; a candidate whose concept depends on a concept the learner is struggling with loses the same amount — bounded below the urgency-class gap, pinned like PLAN_RELATED_BIAS
5c — per-item energy demand struggle state (confidence, last_teachback_score) and action type vs ENERGY_CAPABILITY[energy] consumes item 5's (D-F) energy-demand definition when it lands; this issue must not define a second one

Constraints (from the decision):

  1. Deterministic — every input is a stored fact; no model call anywhere in ranking.
  2. Rubric-testable — one D-16 rubric row per rule, planted world + expected primary, scored by the owner before it ships; row 1 re-run under 5b should still be yes, now for the engine's reason; a new row plants a struggling prerequisite and expects the dependent milestone not to be primary.
  3. Still a bias — golden now_plan_no_active.json byte-identical; the existing rule-5 pins stay green with the derived value in place of the constant: test_matching_due_concept_outranks_unrelated_same_urgency, test_unrelated_more_urgent_due_outranks_new_milestone, test_weak_due_still_beats_overdue_synthesised_milestone.
  4. Partial knowledge is not knowledge — get_concept_context is explicit that omitted edges cannot support "no alternative exists"; 5b treats an absent edge as no signal, never as "not a prerequisite".
  5. Read once, through the seam — edges read in _PlanContext.build beside the plan read (rule-1 pin: no per-consumer plan reads, no checkpoint-history reads); the concept-store read budgeted and measured on the live database before shipping (the item-4 preview read was ~320 ms on an 877 MB sessions.db and recorded; this must be too).

Out of scope

  • Item 5 (D-F) owns the energy-demand definition and the body-doubling floor; this issue consumes it.
  • No change to what a plan document stores; prerequisite knowledge lives in the concept store.
  • No filter, no reordering of urgency classes (review 3 F2 stands).

Acceptance criteria

  • PLAN_RELATED_BIAS replaced by a derived value with a pinned upper bound; the three rule-5 pins above and the golden byte-identity green unchanged.
  • RED tests, one per rule: a prerequisite-of-open-milestone candidate outranks a same-class sibling; a candidate dependent on a struggling concept loses to that concept's repair; an absent edge changes no score.
  • A measured read cost on a real sessions.db, recorded beside the constant.
  • Rubric rows added and scored by the owner (D-16), row 1 re-run.
  • Docs: docs/study-plans.md "Plan-aware now" describes the derived bias in the eligibility terms test_docs_plan_integration_contract.py pins.

Blocked by

  • Rule 5c only: item 5 (D-F) of openspec/changes/plan-integration-followons (T5.3 energy_demand) — not yet a GitHub issue. Rules 5a/5b can start now.

Definition of Done

  • Full unit suite green; just lint; just typecheck; golden now_plan_no_active.json byte-identical.
  • Council review of the RED and the arbitration before merge (the programme's pattern: one commit per accepted finding).
  • Docs and spec (openspec/specs/active-learning-decisions) updated in the same change.

Activity

  1. added
    ready-for-agentImplementation-ready specification with settled requirements and test seams
    on Sep 19, 2026
  2. added this to the 0.6.0 milestone on Sep 20, 2026
  3. NetDevAutomate commented on Sep 21, 2026

    @NetDevAutomate
    OwnerAuthor

    Closed: not planned — owner decision 2026-09-21, with a reopen condition.

    Why. The one rule here that would add information the engine does not already have is 5b, prerequisite order, read from the concept store's prerequisite edges. On the live database (~/.config/studyloop/sessions.db, opened read-only on 2026-09-21) concept_dependencies holds 0 rows — 0 prerequisite edges, and nothing in the product writes them for a real learner: the table is schema without data (agent_session_tools/migrations.py creates it; learning/mastery.py can upsert; no learner-facing path does). This issue's own constraint 4 requires an absent edge to be read as no signal, so 5b would produce nothing for a real learner today. Rule 5c is now redundant: item 5 (D-F, on main at 96806feb) governs a repair's eligibility by its energy demand; biasing on the same number a second time double-counts it. Rule 5a is today's PLAN_RELATED_BIAS = 12 unchanged. On real data the derived bias would therefore equal the constant it replaces — a RED per rule, a measured read cost, a council round and two rubric rows spent on a value that changes no recommendation.

    What stands. The shipped ranking is the honest implementation for the data that exists: rubric row 1 scored yes on it (2026-09-16), the golden now_plan_no_active.json is unchanged, and "a bias, never a filter" holds. Owner decision D-D in docs/architecture/plan-integration/HANDOFF-2026-09-16.md and the proposal docs/architecture/plan-integration/proposals/2026-09-16-context-derived-plan-bias.md remain as the record of the design; this decision supersedes D-D's when, not its shape.

    Reopen when: the concept store carries prerequisite edges for a real learner — i.e. a product path writes concept_dependencies rows from study evidence and SELECT COUNT(*) FROM concept_dependencies WHERE relation_type='prerequisite' is non-zero on a real database. At that point 5b is buildable exactly as written above (5a stays the constant; 5c stays out, item 5 owns demand), with the measured read cost and the rubric row this issue already specifies.

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

    ready-for-agentImplementation-ready specification with settled requirements and test seams

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions