Skip to content

feat(f14): candidate_builder for Path B (program fragments, WP-521) - #8

Open
TserenTserenov wants to merge 2 commits into
wp521-f14-candidate-builder-path-afrom
wp521-f14-candidate-builder-path-b
Open

TserenTserenov wants to merge 2 commits into
wp521-f14-candidate-builder-path-afrom
wp521-f14-candidate-builder-path-b

Conversation

@TserenTserenov

Copy link
Copy Markdown
Contributor

Summary

  • Adds build_program_fragment_candidate(fragment: dict) to generator/candidate_builder.py, mirroring Path A's build_club_post_candidate.
  • source_ref.type = "program_fragment" -- matches the term material_selector.py already uses for the selected object.
  • topic_ref stays None -- the lead to reuse the lesson's week-topic field didn't pan out (different level, not implemented in code).
  • content_hash hashes a canonical JSON of the six-field catalog recipe (seed_id, bottleneck, domain, priority, description, covers_gaps), not generated prose -- there is no lesson text at selection time to hash instead. Re-selecting the same catalog entry always yields the same hash; editing the catalog entry always changes it.

Depends on collect_fragment_payload() (DS-autonomous-agents repo, material_selector.py, same session) to re-fetch the six-field recipe, since select_assignment() itself only returns selection metadata.

Based on #7 (Path A) since both land in the same new file; stacked, not independent.

Test plan

  • generator/test_candidate_builder.py -- 5 passed (2 Path A + 3 new Path B)
  • generator/test_recommendation_registry.py -- 21 passed, unaffected
  • DS-autonomous-agents/scripts/test_wp521_f6_material_selector.py -- 15 passed (2 new for collect_fragment_payload)

🤖 Generated with Claude Code

TserenTserenov and others added 2 commits October 22, 2026 15:01
Resolves the two open Path B questions from the WP-521 peer session
(Claude + Kimi + Codex, 2026-10-22): source_ref.type="program_fragment"
(matches the term material_selector.py already uses for the selected
object), topic_ref stays None (the lead to reuse the lesson's week-topic
field didn't pan out -- that field lives at a different level and isn't
implemented in code).

content_hash blocker: material_selector.py's catalogs carry no lesson
prose, only a short assignment recipe (seed_id/bottleneck/domain/priority/
description/covers_gaps). Hashes that recipe (canonical JSON, sort_keys)
instead of generated prose -- re-selecting the same catalog entry always
yields the same hash, editing the catalog entry always changes it, while
two separate AI renders of the same recipe's lesson text do not change it
(intended dedup semantics, validated with both peers in round 3).

Depends on collect_fragment_payload() (DS-autonomous-agents,
material_selector.py, same session) to re-fetch the six-field recipe --
select_assignment() itself only returns selection metadata, not the
catalog record.

Refs: peer-session 2026-10-22-06-wp521-path-b-source-ref

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cold-review finding: the same-named tuple is duplicated in DS-autonomous-
agents' material_selector.py with no shared import between the two repos.
A field added only there would silently drop out of the hash here instead
of raising, since the dict comprehension below ignores unknown keys.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant