Repository navigation
v0.4.0
-
Publish an Intel macOS DMG next to the Apple Silicon one. A second macOS
build job runs on themacos-15-intelrunner, and each macOS job fails when
lipo -archsreports the wrong architecture for the app executable. The
macOS release assets are now namedunsigned-macos-arm64.dmgand
unsigned-macos-x86_64.dmg, the checksum file lists both, and the website
offers both downloads. (#347) -
Fix the Windows native build, which had two separate faults:
- Since #332 it failed its bundled-profile check. A Windows checkout
converted line endings in the HOB profile snapshot and the bundled
baseline profile, so their bytes no longer matched the recorded sizes and
SHA-256. A new.gitattributesturns off line-ending conversion for
profile-snapshots/anddraftomen/baseline_profiles/. - Since #555 the built executable failed to start because the
pyside6-deployspecs excludedQtTest, which removedQt6Test.dll
whileqt_gui.pyimportsPySide6.QtTest. The specs no longer exclude it.
- Since #332 it failed its bundled-profile check. A Windows checkout
-
Add a Sets page to the website at
/sets/, linked from the navigation. It
lists the supported sets, those with card data and 17Lands ratings, and
marks the ones with an augmented model. A second list shows the sets that
have no 17Lands ratings yet. (#707) -
Load per-set card data in the CLI
replay,build,backtest,
benchmark-picksandrefresh-structure-targetscommands, the same data
the desktop app uses. They no longer read~/.draftomen/carddb.json, and
ratings metadata recovery no longer writes it.--bulk-filestill
replaces the card data for fixtures and CI.refresh-datanow only prints
that card data downloads per set, and an existingcarddb.jsoncan be
deleted. (#706) -
Keep pipeline caches out of the user data directory.
build-augmented-set
now caches draft dumps in.draftomen/corpus-cache/profile-input-cache, and
refresh-profile-datacaches 17Lands ratings in
.draftomen/corpus-cache/17lands, both relative to the working directory.
Both commands take--cache-dirto use another root, and
refresh-profile-datano longer accepts the hidden--app-diroption.
Nothing writes~/.draftomen/profile-input-cacheor
~/.draftomen/set-enrichmentany more, so both can be deleted.
~/.draftomen/17landsstays for the CLIbuild,replayandbacktest
ratings. (#705) -
Check downloaded card data against the sets manifest. With network access,
the card-data client readssets/manifest.jsononce per client, rejects a
download whose SHA-256 differs from the manifest, and downloads again when a
cached file no longer matches it. A failed update keeps the valid cached
file, and an unreachable manifest leaves cached sets in use. (#704) -
Publish
sets/manifest.jsonon the website. It lists every set with card
data, and gives each set's name, card-data URL, size and SHA-256, profile
formats with their maturity, and augmented model metrics.export-set-data,
build-augmented-setand the Profile Refresh publication regenerate it.
(#703) -
Make
build-augmented-setreport its progress. It prints one line as each
stage starts, the dump download at most every 10% and 5 seconds, and how
many picks training and evaluation use. Basic DO scoring now reports in 25%
steps instead of once per 5,000 picks. (#710) -
Publish the DFT PremierDraft augmented model. On 889,392 held-out picks it
raises Basic DO top-1 from 0.520 to 0.562 and mean reciprocal rank from
0.690 to 0.726. -
Make
build-augmented-settrain against the set profile the website
publishes inwebsite/public/profiles, with its checksums verified. It used
to read only the local app cache and fall back to a generic profile without
ratings, which calibrated DFT against the wrong baseline and reported it
only after training. The build now stops before any download when the set
has no published profile with ratings, and stops before training when the
dump's format has none. -
Let
build-augmented-settrain on draft dumps with bonus-sheet cards that
the set card data does not list, such as the 10 DFT Special Guests. Their
metadata comes from the local Scryfall bulk file, preferring an Arena
printing, and the set's own printing wins when both exist. (#715) -
Raise the profile input cache limits to 300 MiB per entry and 1 GiB in
total. The DFT PremierDraft public draft dump is 205 MB, so the old 128 MiB
limit rejected it andbuild-augmented-set DFTtrained on the much smaller
TradDraft dump instead. -
Let
build-augmented-setread 17Lands draft dumps that have nopick_2
column. 17Lands added that column for Pick Two Draft, so older dumps such
as DFT failed with "Draft dump is missing required columns: ['pick_2']".
Without the column, no row counts as a second pick. -
Make the weekly historical profile refresh process at most 6 set and format
pairs per run, keeping each set whole, and skip pairs that already have a
published profile. The old run refreshed all 128 historical pairs at once,
17Lands stopped answering after about 105 requests, and the run published
nothing. A
historical pair with no 17Lands games, such as IKO TradDraft, is now listed
as skipped and no longer fails the run. (#709) -
Close the Mocked Draft dialog once the draft started from it is under way,
so the live drafting view is visible. A failed start keeps the dialog open
with its error, and reopening the dialog during a draft to leave it keeps it
open. -
Let Mocked Draft offer booster cards that the set card data does not list,
such as SPG, MUL, BIG, and OTP bonus-sheet cards and 32 KTK cards. A card
maps to another Arena printing of the same card when the set has none, and
its metadata comes from the local Scryfall bulk file, or from the card
fields Draftmancer sends when the printing never reached Arena. These cards
carry no ratings and score the neutral prior. (#696, #697) -
Make the GUI replay smoke check wait for a pending hosted profile refresh
before it captures. A fast replay finished before the MSH profile download,
so the check showed fallback ratings even though the session adopts the
profile once it arrives. (#683) -
Let Mocked Draft play Draftmancer packs that are not 14 cards. Pack events
carry the pack size, and the pick stage, remaining picks, and pool ledger use
it, so 15-card sets such as LCI and 13-card sets such as BLB draft all 45 or
39 picks and reach a deck build. Arena drafts keep 14-card packs. (#695,
#682) -
Fix Mocked Draft booster cards that failed to map to an Arena card. The
Scryfall mapping now reads every set in the bulk file, uses the first face's
oracle id when the card has none, and picks the lowest Arena id when a card
has several Arena printings, such as the LCI Travel Poster basics. This fixes
booster decoding for LCI, M21, and SNC and startup for TDM and ECL. Booster
errors now name the card by name, set, and collector number. (#682) -
Add a QML regression test showing that the Mocked Draft set selector keeps
the chosen set, such as LCI, through state updates and after Start, and that
Start sends that set. The fix shipped with the set picker in #688. (#681) -
Make "Refresh hosted ratings" work during a Mocked Draft. The refresh now
uses the simulated set's profile client and updates only the Mocked Draft
session, so the Arena profile is never touched. If no hosted profile exists,
the ratings banner says so, and fallback scores stay active. (#687) -
Remove the "DO recommendation" comparison sentence and the repeated
"Pack 1, pick 6." status line from the desktop Live Draft header in wide
and narrow layouts. The pack heading, ranked cards, and controls stay. (#655) -
Remove the narrative score paragraph from the desktop Live Draft card
details in wide and compact layouts. The card image and the structured
score, win rate, grade, ALSA, and fit fields stay. (#654) -
List every Draftmancer-supported set in the Mocked Draft picker by full name
and code, such as "The Hobbit (HOB)", in alphabetical name order. A set
without cached card data shows a "Download set card data" button, and Start
stays disabled until a validated download completes. A failed download shows
the set and the reason, and Start stays disabled. (#657) -
Label the desktop card-detail score "Augmented DO Score" when a validated
per-set model adjusted it, in both wide and narrow layouts and in the
accessible description. Scores keep the plain "DO Score" label when the
switch is off or the set has no model. (#656) -
Remove the unused role-profile compile, load, dump, and rebuild helpers and
theCompiledRoleProfiletype.resolve_card_rolesand
RoleClassifier.resolveno longer take aprofileargument and always use
the local classifier with reviewed overrides. (#680) -
Republish the HOB and DFT profiles as clean schema-4 profiles and remove the
unusedenrichment-publications.jsonrecord. Retrain the HOB augmented model
against the clean Basic DO baseline. It passes both held-out gates on 274,932
picks: top-1 rises from 0.5489 to 0.5922 and mean reciprocal rank from 0.7115
to 0.7474. (#664) -
Remove the
enrich-setandlist-enrichmentcommands, the offline
semantic-enrichment extraction, review, and projection code, and its
OpenRouter and guide clients. Profile publication and refresh no longer
retain enriched manifest entries or report enrichment conflicts. Card-data
export and ratings-based profile generation are unchanged. (#662) -
Remove typed relationship scoring, pool-ledger support, and advice. Keep
empirical SetProfile scoring, local card-role classification, generic synergy,
and existing audit and draft-history readers. (#673) -
Generate clean schema-4 SetProfiles. Ignore retired semantic fields when
reading schemas 1–3 and reject them in schema 4. Keep confirmed enrichment
artifacts standalone, treat oldsemantic-onlymanifests as history, and
preserve the independent augmented artifact path. (#663) -
Retire relationship availability, advice, and preference state from shared
and mocked sessions, test-draft APIs, and CLI output. Keep Basic DO scoring
and contextual evidence. (#672) -
Remove retired relationship controls and advice from desktop Settings, status,
recommendations, and card detail. Keep contextual scoring, Augmented
Intelligence, and Mocked Draft. (#674) -
Remove the retired AI-enhanced-suggestions preference from the Qt adapter
and desktop Test Draft factory. Keep the shared session command and
non-desktop runtime option. (#675) -
Stop emitting legacy relationship fields in audit and backtest output while
preserving reads of existing audit and draft-history records. (#669) -
Remove legacy AI-enhancement controls and status from Textual and plain
watch while preserving ordinary recommendations. (#671) -
Preserve source-supplied ALSA in generated HOB profiles so recommendation
rows and selected-card details can show it. Keep missing values unavailable.
(#653) -
Remove rating attribution from shared recommendation comparisons while
keeping other selected factor explanations intact. (#652) -
Keep the desktop Augmented Intelligence choice on across restarts and
Mocked Draft source changes, even when the current set has no model.
Unavailable or failed models leave Basic DO and manual picks working. (#651) -
Load the published HOB augmented model when a desktop Mocked Draft starts.
Keep model loading off the session thread, and enable the setting for
simulated HOB offers without requiring another action. (#624) -
Publish the first HOB PremierDraft augmented model after it beats Basic DO
on held-out Top-1 agreement and mean reciprocal rank. Its manifest records
the source and points to the compressed model by checksum. (#624) -
Publish one validated augmented model with
build-augmented-set SETonly
when both held-out metrics beat Basic DO. Canonicalize public dump URL format
casing, read compressed cache objects by gzip signature, keep draft dumps in
the private cache, and update the manifest after installing the object.
(#639) -
Train one explicit set from pinned draft data and return a validated runtime
artifact only when held-out Top-1 and MRR both beat Basic DO. Keep the HOB
pilot command and reject mismatched set, card, profile, and source data. (#644) -
Package the HOB compact trainer for import without changing its pilot command
or strict held-out gate. Add a deterministic passing compact regression. (#643) -
Reuse valid published per-set card data without fetching sources or changing
its bytes. Generate only a missing requested set and reject invalid existing
files or unsupported set codes without replacing artifacts. (#637) -
Select a listed public 17Lands Draft Data dump for one set, preferring
PremierDraft before TradDraft and QuickDraft. Reuse validated cached bytes
and keep the source URL, checksum, retrieval time, and license for later
augmented training. (#636) -
Explain the augmented DO arithmetic in the desktop card detail. The
selected-card detail shows Basic DO, the signed adjustment, and the total
DO Score when augmentation is on, and keeps the plain DO presentation
otherwise. (#633) -
Show Augmented Intelligence availability and control in the desktop. Settings
gains a persisted Augmented Intelligence switch that stays off and disabled
until the active set has a validated model, the live status strip reports
unavailable, available, or on, and the adapter owns the per-set model load
off the session thread, failing closed to Basic DO. (#632) -
Apply the validated per-set augmentation delta to live scoring behind one
default-off session flag. Live totals clamp the bounded artifact adjustment
onto Basic DO and order on the float total, fail closed to Basic DO when no
model is usable, and expose per-set availability plus an adapter-owned load
request with per-row basic and adjustment scores. (#621) -
Add the per-set augmentation artifact contract, set-keyed manifest, and
offline-first runtime client with content-addressed downloads, atomic caching,
and framework-free bounded inference. (#620) -
Train the HOB coarse-context Model C with fixed-seed parameters, bounded
additive calibration, and held-out Basic DO comparisons. Write a local model
artifact only when both Top-1 agreement and mean reciprocal rank improve.
(#619) -
Prepare reusable per-set training rows from pinned public draft data with the
tested 22 pool-summary values, whole-draft chronological splits, source
provenance, Oracle card IDs, and leakage-safe reports. Resolve full card and
face names through set metadata so HOB remains the first checked set without
hard-coding it in the loader. (#618) -
Disable legacy AI-enhanced relationship scoring in production recommendations,
backtests, live sessions, and the desktop settings control while retaining the
schema-3 data and explicit offline calibration path. (#617) -
Separate drafted-card relationship advice from ordinary scoring rationale and remove
confidence and mana-production filler from focused card explanations. Mark cards that have
advice, show an explicit per-card no-match result, score either endpoint when its partner is
drafted, preserve all Oracle-derived capability roles in the published profile, and use
validated draw, exact shared-subtype, Landfall, Ferocious, and Storied evidence in live advice.
Restrict token-maker classification to creature tokens so Treasure creation cannot produce false
creature-token synergy claims. (#595) -
Give recovered enrichment publications a current timestamp so normal clients can replace an
older cached profile instead of rejecting the recovered artifact as stale. (#595) -
Republish the recovered HOB Quick Draft enrichment and expose relationship advice in the
headless real-Draftmancer pick trace. (#595) -
Show readable drafted-card relationship advice in focused card intel, including useful
interactions whose effective score increment is zero, and explain the independent contextual
scoring and AI-enhancement settings in the desktop UI. (#594) -
Score supported and conditional pool relationships within existing synergy bounds, preserve
zero-effective relationship provenance in audit and backtest output, and avoid generic synergy
double counting. (#611) -
Classify drafted-pool relationship evidence as supported, conditional, incompatible, or
unsupported while retaining exact clause, qualification, card, and profile provenance. (#606) -
Recover typed Hone counter sources and Equipment payoffs, including Dwalin-to-Equipment relationships and Sting's qualified self interaction, from saved HOB evidence without provider calls (#607).
-
Recover Bilbo's Gambit's complete Gift instruction with its optional opponent promise, Treasure
object, and qualified spell-lock branch in offline role profiles. (#608) -
Derive qualified source-to-replacement relationships from distinct explicit HOB token creators,
excluding Army growth, opponent-controlled creation, and duplicate printed instructions. (#612) -
Represent token-creation replacement effects as source-dependent modifiers so they cannot be
counted as independent token supply during offline relationship conversion. (#610) -
Recover friendly untap effects as typed support instead of disabling removal, including exact
target, controller, and source-exclusion restrictions in regenerated role profiles. (#609) -
Preserve Adventure component selection and printed exile-then-cast reminders as face-bound
relationship qualifications while every face shares its parent drafted-card identity. (#592) -
Reconcile saved HOB capability responses during offline resume. The workflow reparses retained
paid response bytes with the current parser, recovers candidates that older successful results
silently omitted, preserves stable provenance, and leaves every paid artifact unchanged. (#596) -
Compile source-bound landfall, ferocious, and storied condition maps offline. The
condition compiler derives helper and payoff capabilities from pinned Oracle text
with exact-quote evidence, links draft-potential helper edges with thresholds and
timing preserved, and publishes the map beside reviewed relationships without
touching finding, run, or confidence math; the offline probe recovers the saved
#587 family rows through the realgenerate-profileconsumer with zero network
calls. (#591) -
Recover qualified recruit and amass relationships offline. The projection
compiler binds exact multiline Oracle evidence, retains conditional recruit
discard, amass mode, Azog controller, and Misty Mountains threshold
qualifications, recovers qualified payoff participants with source-proven
cost, choice, timing, and conversion statements, and rejects the four
subtype-negative pairs astoken_subtype_contradiction, so all 414 scoped
HOB findings account through the realgenerate-profileconsumer with
410 qualified rows and four explicit contradictions. (#590) -
Recover qualified relationships through the offline profile pipeline. The
projection compiler now emits qualified rows: a prerequisite that cannot bind a
typed clause is retained verbatim as an exact-quote qualification inside the
participant's own frozen evidence paragraph, so a relationship with one
untypable statement is projected instead of dropped, and every stored
relationship gets exactly one deterministic conversion outcome with a
source-linked reason, one ofdecoded,qualified,missing_evidence,
contradiction, orunsupported, recorded bygenerate-profilein the
generation report underrelationship_conversions. The compiler also rejects
an enabler that consumes a zone its payoff counts, reporting
zone_supply_contradiction:<zone>, unless another capability of the enabler's
own card face refills that zone from the library or hand. (#589) -
Retain source-bound conditional draft synergies as qualified relationship projections.
A projection participant may declare the stated cost, choice, condition, mode, party,
quantity, and timing requirements the clause grammar cannot certify as exact
selector/occurrencequalifications inside its own frozen Oracle paragraph;
declared gaps closeincompleteverdicts while contradictions still fail, the
projection reportsdecodedonly when nothing is declared andqualifiedotherwise,
and the optional key keeps legacy artifact and profile bytes unchanged. (#588) -
Document the HOB enrichment coverage audit, source-bound capability and
relationship ledgers, conditional draft-synergy contract, and offline runtime
traces. Record missing recovery work without changing production behavior or
rerunning paid enrichment. (#587) -
Download the Mocked Draft Scryfall bulk source from the dialog. When the resolved
scryfall-default-cards.jsonl.gzis missing the dialog says so and offers Download
Scryfall data, and the click streams Scryfall'sdefault_cardsbulk JSONL into the
resolved path through a sibling temporary file withos.replace, so progress is
published as an indeterminate or percentage bar on the existing Mocked Draft state
channel, a failed or cancelled download never replaces an existing source or installs a
partial file, the capability re-resolves when the download lands so the dialog is ready
without a restart, and Start is not gated on the missing file, so it still reports the
real missing-file error until the download lands.
(#583) -
Edit and persist the three Mocked Draft sources from the DEVELOPER settings
section: the Draftmancer checkout directory, the server URL, and the Scryfall
bulk file each prefill with the effective location, the capability rebuilds on
the same path as the toggle, and the launch flags stay per-launch overrides.
(#582) -
Start and stop the pinned Draftmancer server from the Mocked Draft capability.
draftomen/draftmancer_server.pyowns the checkout process: it adopts a server
that already answers the configured location, otherwise starts the pinned checkout
on a picked loopback port with persistence disabled, waits for a Socket.IO
handshake, and stops only the process it started on leave, at exit, and after a
failed start, with every setup failure surfaced as actionable dialog text. (#558) -
Persist Mocked Draft as an off-by-default desktop developer setting with the
Draftmancer checkout location and server URL. The settings surface exposes it as a
DEVELOPER toggle that installs or clears the simulated-draft capability live, the
app-bar action and dialog read "Mocked Draft",--draftmancer-dirstays a
per-launch override, and the in-app path resolves the checkout, card data, and
Scryfall bulk source from configured or application-data locations instead of the
process working directory. (#557) -
Serve the confirmed HOB enrichment as a role-bearing profile. Recompiling the
confirmed artifactedc7d166…at theearlystage publishes
objects/75132bf4…json.gz(schema 3,enhancement_status=enhanced, a 138-card
role profile and 685 relationships) and selects it forhob/quickdraft,
superseding the metadata-onlyfd236b38…object, which stays committed. The
publication record names the artifact, run, and profile digest, and the
automated profile refresh reports a retained-enrichment conflict for that
identity instead of downgrading it, while unrelated identities still refresh.
The LCI identity is unchanged: its confirmed artifact stores pre-v2 capability
facts, so no relationship can be projected for it yet. (#573) -
Recover role-bearing enrichment offline.
republish-enrichmenttakes the explicit
generation--stageplus the same optional--ratings-file,--source-manifest, and
--draft-source-nameinputs asgenerate-profile, so a confirmed artifact recompiles at
earlywith its empirical evidence into a schema-3 profile that carries both the enhancement
and a compiled role profile. The default--stage metadatakeeps its metadata-only purpose,
and a role-bearing recovery with missing or unusable inputs exits1before any object,
manifest entry, or publication record is written. (#571) -
Fail
list-enrichmentinstead of printing a smaller inventory when a published
profile object under<profiles>/objectsexists but cannot be read: the
per-object read is separated from gzip/JSON decoding in
draftomen/enrichment_inventory.py, so a permission or I/O error exits 1 with
list-enrichment failed: Could not read the published enrichment profiles.,
while malformed gzip, invalid text or JSON, and non-profile payloads remain
skippable. (#572) -
Keep enrichment publication provenance across a failed or interrupted publication. The
durable record indraftomen/enrichment_publications.pyis written as schema 2 with one
committed entry per(set, format)identity plus at most one pending candidate:
publish_profile_publicationrecords the candidate, writes the manifest entry that names
the new profile, and only then promotes the candidate, so a failed manifest write or a
killed process no longer overwrites the provenance of the profile the manifest still
serves,filter_enriched_profile_downgradesprotects the retained digest through either
entry, and a fresh process resolves the leftover candidate against the manifest it finds,
promoting it when that manifest selects its digest and dropping it when it does not. Plain
publications never read or write the record, and a schema-1 record still loads. (#570) -
List local enrichment work and where it was published.
list-enrichmentreports
every run and saved artifact under a store directory with its set, run identity,
created and reviewed timestamps, review state, relationship and confirmed counts,
and artifact SHA-256, plus the profiles each artifact was published as, marking an
identityorphanedwhen the manifest no longer selects the published object, so a
replaced publication is visible instead of silent. It reads local files only, makes
no network request and no model call, and defaults to the shared
<app data directory>/set-enrichmentstore. (#567) -
Recover already-paid enrichment work offline.
republish-enrichmentrecompiles
and publishes one metadata-stage profile from a saved confirmed artifact without
freezing a guide and without any model call, selecting the newest confirmed
artifact for the set unless an exact--artifactdigest or--runidentity is
given, anddraftomen/enrichment_publications.pyrecordsartifact_sha256,
run_id,reviewed_at,published_at, andprofile_gzip_sha256per
(set, format)inwebsite/public/profiles/enrichment-publications.json, which no
website data refresh rewrites or deletes.filter_enriched_profile_downgradesnow
reads that record, so an identity whose recorded publication matches its retained
manifest entry is protected from a plain regeneration even when its retained object
is missing or unreadable, a record entry that does not describe the retained entry
never blocks a legitimate replacement, and an unreadable record fails closed. (#566) -
Retain published enriched profiles when an automated website data refresh would
replace them with plain ones.draftomen/profile_publication.pyadds
filter_enriched_profile_downgrades, which splits generated replacements into
accepted artifacts andEnrichmentDowngradeConflictrecords by reading the
published profile object bytes, and both plain-profile producers —
execute_profile_data_refreshand the refresh workflow's_materialize_profiles—
route every replacement through it before merging, so a downgraded identity keeps
its manifest entry and object bytes, its object is never rewritten, and the run
still succeeds;refresh-profile-dataprints one retained line per conflict,
generate_websiterecords them underprofiles.enrichment_conflictsand in a
### Retained enriched profilessummary block, and the bundle validator accepts and
re-validates the new records. Enriched-to-enriched replacement and replacement of a
non-enriched entry are unchanged. (#561) -
Generate usable profiles from saved confirmed enrichment without new model
calls.generate-profile --enrichment PATHvalidates the artifact digest,
frozen guide and card sources, then produces schema-3 profiles with compiled
roles at the selected evidence-backed stage. Generation recovers eligible
typed projections from retained local capability facts, preserves the source
artifact digest and review, and keeps unsupported relationships unchanged.
Unrepresented conditions fail closed. Clause validation now separates a
following instruction or activated ability effect from the current clause's
zones without dropping same-instruction restrictions. Generator version 3
records the changed deterministic output. (#560) -
Add the simulator-backed native Manual Test Draft acceptance journey (#553):
draftomen/qt_gui.pyturns the hidden--test-draft-smokeflag into a journey
selector whose bare form still selects the existing Auto journey whilemanual
selects the new Manual journey, addsTEST_DRAFT_MANUAL_PICK_COUNT, and adds the
_TestDraftManualSmokeDriverbehind the narrow_SmokeControlsport with the
_QmlSmokeControlsimplementation that locates a control by object name inside the
running window and activates it with a synthesized Space key, so the driver stays
testable without a display; the journey drives the real controls in order —
testDraftButton,testDraftManualModeButton, andtestDraftStartButtonto start
a manual draft,testDraftCloseButton, a realwideRecommendationRow2(or
narrowRecommendationRow2) recommendation row for the first pick,
testDraftPickButtonfor each of the five picks, thentestDraftButtonand
testDraftLeaveButtonto leave — requires the first confirmed pick to be a non-top
recommendation, and requires every pick to grow the published pool by exactly one
and to re-render the drafting heading, exits 1 with a named reason on any failed
requirement or missing capability, and prints oneTest Draft smoke: {...}manual
summary line whosemode,set_code,picks,pool_total,non_top_rank, and
statuskeys reportmanual,hob,5,5,2, andok;
tests/bundle_smoke.pyruns both journeys in one invocation behind
REQUIRED_MANUAL_PICKSand validates each journey's summary before printing its own
compact result;tests/test_qt_gui.pycovers the selector, the activation order,
the summary line, the non-top requirement, and the named failures while
tests/test_desktop_bundle.pycovers the two-launch argument vectors and the
summary validation; andREADME.mdanddocs/desktop-bundles.mddocument the
developer runbook for the headless, compiled, and interactive runs. (#553) -
Add the developer-only native Test Draft controls to the desktop GUI:
draftomen/qml/TestDraftDialog.qmlis the new modal dialog that lists the capability's
supported set codes with the published default preselected, offers Manual or Auto,
reports pending and failure text, and dispatchesstartTestDraftandleaveTestDraft;
draftomen/qml/AppBar.qmlgains a Test Draft action that is visible only while the
capability is enabled and accented while a simulated draft is active;
draftomen/qml/LiveDraftView.qmlgains the Test Draft status indicator, the visible
failure label, and the Manual Pick button that submits the selected recommendation with
its published offer generation, so the button stays absent during ordinary Arena
drafting;draftomen/qml/Main.qmlmounts the dialog and opens it from the app-bar
action with focus restoration; the new component is registered in
draftomen/qml/qmldir,pyproject.toml,pysidedeploy.macos.spec, and
pysidedeploy.windows.spec; andtests/test_qt_gui.pygains offscreen QML interaction
tests covering the opt-in absence, the set and mode dialog dispatch, the Manual pick
dispatch, the pending and failure states, and leaving the run. (#552) -
Package and smoke-test the native Test Draft (#548):
.github/workflows/native-bundles.ymlnow syncs the lockeddraftmancerextra with
uv sync --locked --extra draftmancerand keeps--extra draftmanceron every build-path
uv runin thenative-bundlejob, so every command there requests the environment —
the base dependencies plus the optional transport — that the sync step installs before
Nuitka packages it, while the two
tests/bundle_smoke.pysmoke steps stay extra-free so they prove the artifact in an
environment that does not provide the transport; bothpysidedeploy.macos.specand
pysidedeploy.windows.specdeclare--include-package=socketio, so the bundle carries the
Socket.IO transport thatdraftomen/draftmancer.pyimports lazily for the developer Test
Draft, while wheel, Homebrew, and source startup keeppython-socketiooptional;
tests/bundle_smoke.pynow runs two ordered compiled launches inside one temporary
directory — the existing mock launch with--provider mock --smoke-test --verify-bundled-profileand its isolated--app-dir, then a default live start with
--provider live --offline-profiles --no-startup-scan --smoke-test, its own app directory,
an isolated emptyPlayer.log, and a screenshot that must be non-empty — and gains an
opt-in--test-draftmanual journey mode that rejects those three journey flags unless
--test-draftis given, validates its pinned--draftmancer-dir,--scryfall-bulk-file,
and explicit--app-dirinputs, probes the Draftmancer endpoint before and after the run
without ever starting, stopping, or configuring the service, drives the compiled GUI
through the new hidden--test-draft-smokeflag, and requires the cross-process
Test Draft smoke: {...}summary before printing its own compact result, decoding
captured bundle output as UTF-8 so it cannot fail locale decoding;
draftomen/qt_gui.pygains the hidden--test-draft-smokeflag and the
_TestDraftSmokeDriver, which starts the capability's published default set code, reports
the completed draft and build, leaves the simulated session, and bounds the journey at
900 seconds, reporting a capability error immediately instead of waiting out that bound,
so the app gives the reason before the helper's own bound; and
docs/desktop-bundles.mddocuments the extra-aware build path, the two-launch helper, and
the manual native journey. -
Add the developer Test Draft opt-in to the native GUI and the serialized worker
lifecycle behind it (#547):draftomen/qt_gui.pyaccepts--draftmancer-dirto pin a
Draftmancer checkout beside--scryfall-bulk-file,--test-draft-server-url, and
--test-draft-timeout, builds the runtime factory only behind that explicit opt-in,
and leaves the mock provider and every run without the flag on the unchanged
Arena-only contract;draftomen/qt_adapter.pypublishes the immutable
TestDraftSessionState(capability, authoritative source, phase, mode, set code,
supported and default set codes, pending flag, opaqueoffer_generation, and error)
with theTestDraftFactoryboundary and thestartTestDraft,pickTestDraft, and
leaveTestDraftprovider intentions, and runs that lifecycle on the existing worker
thread, so the ArenaLiveSessionstays retained while a separate simulated source is
authoritative, Arena snapshots, image completions, and profile refreshes are dropped
by their source generation while simulated snapshots are dropped by their runtime
generation, manual picks submit at most once per published offer generation, leaving
restores the retained Arena session with exactly one poll, and the splash,
contextual-scoring, and AI-enhanced preference values are shared with the simulated
session and replayed onto Arena on leave;draftomen/card_data_client.pygains
cached_card_data_set_codes(...)anddraftomen/test_draft.pynow exports the shared
DEFAULT_TEST_DRAFT_*constants and accepts an injectedCardImageService, so the
offered sets intersect the pinned checkout with locally cached card data. -
Make the test-draft runtime cancellable and reusable (#546):
draftomen/test_draft.pyexposescreate_test_draft_runtime(...), which performs the
supported-set, card-data, Scryfall-identity, and profile-source preflight and returns a
TestDraftRuntimeowning the isolated source-lessLiveSession, the Draftmancer
adapter, theTestDraftController, and the implicit simulation directory;
TestDraftRuntime.cancel()wakes a blocked connection, start, or pick operation
without acquiring the controller lock, without waiting for in-flight session
publication, and without disconnecting the client, whileTestDraftRuntime.close()
retires the controller, session, and temporary directory exactly once in reverse
ownership order, unwinds partial construction, and reports every construction failure,
including the implicit simulation directory, as a startupTestDraftError;
supported_test_draft_set_codes(...)reuses the existing Draft Omen/Draftmancer
capability intersection, so HOB is offered only when both sides advertise it;
DraftmancerAdapteropens the transport without blocking on the namespace handshake
and waits for that handshake,startDraft, andpickCardon its own condition with a
public terminalcancel(), emits through a Socket.IO callback instead of the
transport's blockingcall(), ignores late acknowledgements after a terminal outcome,
records completion before publishing it, and keepsclose()as the only
client-transport teardown, so a blocked operation returns immediately on cancellation;
andrun_test_draft_auto(...)keeps its signature, ordered picks, build result, and
isolated persistence. -
Add the UI-neutral test-draft controller and headless
draftomen-tui test-draft
command (#538):draftomen/test_draft.pyexposesTestDraftControllerfor explicit
Manual confirmation of one inspected offer and recommendation-driven Auto advancement
overLiveSessionsnapshots, withTestDraftErrorpreserving the failure stage, the
accepted steps, and the last trustworthy snapshot;run_test_draft_auto(...)drafts a
full event through production scoring and the normalRequestBuild, keeps simulated
draft state and audit records in an isolated simulation directory while card-data and
profile sources stay in the normal application directory, and the command prints one
Pack N pick M: <card> (grpId <id>)line per accepted pick before the unchanged
deck-builder report. -
Add the pinned Draftmancer typed-event adapter and deterministic protocol
smoke helper for local three-pack development drafts. (#537) The helper
resolves Draftmancer printing identities through a locally downloaded
Scryfall default-cards bulk file without per-card API calls; the required HOB
smoke completes all 42 picks across three packs and verifies the typed event
stream, final pool, and persisted source-lessLiveSession. -
Accept typed
DraftEventingestion directly onLiveSession(#536):
LiveSession(log_path=None, ...)builds a deliberate source-less session
with noLogFollower, keeps the incremental parser soprocess_lines
stays the single Arena-line path, and returns the current snapshot from
poll_once,scan_startup_files, and setup-status refresh without
filesystem work; the existing per-event orchestration (store persistence,
scoring, profile and card-data activation, audit records, pool evolution,
ordered event publication, completion) moved unchanged into the new public
LiveSession.process_events(events=...)entry point, whichprocess_lines
now calls after per-line parsing and parser login recovery, so parsed Arena
lines and direct typed producers share one ingestion boundary. -
Publish the confirmed enriched HOB QuickDraft profile snapshot and manifest entry generated by
enrich-set. -
Publish the confirmed
enrich-setresult into the production profile tree instead of
only its local output directory: Confirm now installs the metadata-only QuickDraft
object atwebsite/public/profiles/objects/<gzip_sha256>.json.gz, merges its entry
into the existingwebsite/public/profiles/manifest.jsonthrough the shared
publish_profile_objectandmerge_profile_manifest_artifactspublication
primitives, and reportspublished_profile_object,profile_sha256,
gzip_sha256andprofile_manifest; the content-addressed object is installed
before the manifest so the manifest stays authoritative, an identical
republication rewrites neither the object nor the manifest, an absent or
malformed repository manifest fails closed withPROFILE_PUBLICATION_ERROR
rather than synthesizing one, and Cancel still publishes no profile. (#532) -
Resolve relationship candidates with a role-anchored local matcher (#527):
the Oracle-text regex pruning is gone, and each constructed candidate now
carries one deterministic verdict over the v2 capabilityaction,zone,
andqualifierfields — every declared mechanism
(token-go-wide-payoff,token-death-payoff,
token-sacrifice-outlet,discard-recursion-payoff,
loot-recursion-payoff, andmill-graveyard-payoff) decides locally,
an explicit structured-field conflict vetoes the pair, and a field the
parameters do not settle leaves it for the model; only residual pairs
reach the 20-pair validation batches, so the HOB corpus pays for zero
model validation batches while every pair keeps a truthfullocalor
modelbasis and the published artifact records the zero-cost
local-pair-matcher-v1run beside the paid work it did not replace. -
Tolerate per-item card extraction violations and recover them locally
(#527): a card response that violates one item of the capability contract
now keeps its other items instead of discarding the whole response, and a
stored all-or-nothing malformed card result is re-parsed from the paid
response it retains under an invocation-independent run identifier, so a
resume repairs the record with no additional model call, no store write,
and byte-identical provenance across reruns. -
Report pair resolution and validation budget in the HOB harness (#527):
the report gainscandidates.resolutionwith the local and residual pair
counts, the local share, and the planned relationship validation batch
count, and a complete unlimited full-source run now fails acceptance
below 80% local resolution or above 60 relationship validation batches. -
Cut relationship-validation enrichment cost: candidate validation now
sends bounded batches of 20 pairs per model call instead of one call per
pair, a local mechanism-compatibility filter prunes pairs whose oracle
texts cannot express the mechanism before any paid call, and per-batch
work identities keep runs resumable at batch granularity. (#432) -
Carry matcher-ready structured parameters on card capabilities (#526):
extracted card capabilities now require a closed primaryaction, a
zone, and aqualifierobject (card types, token restriction,
subtype, mana value) alongside the existing fields; card extraction
requests move to the dedicateddraftomen-card-capability-extraction-v2
prompt and response schema while guide extraction stays on its v1
contract, so previously paid card responses are re-acquired under the
new identities while guide work is reused, and stored relationship
results that predate the card v2 fields are revalidated from their
already-paid responses without a new request. -
Skip end-of-pack handshake picks in
backtest(#432 follow-up): Arena
sends a one-cardBotDraftDraftPickrequest withPickNumber14 after
the last pick of each pack, and persisted drafts carrying those records
crashed backtest with a ledger stage error; such picks are now reported
as skipped rows with an explicit reason instead of aborting the report,
and the skipped-picks footnote names the new reason. (#432) -
Expose enhancement availability and control in the desktop interface
(#519): the sharedenhancement_availabilitysnapshot state reaches QML
through the existing plain-value translation, Settings gains an
AI-enhanced suggestionsguidance row whose switch dispatches the
existingChangeAiEnhancedSuggestionscommand only when availability
permits it, and the status strip gains a compact enhancement label with
the same offline/no-live-model copy in its tooltip and accessible
description. (#519) -
Render the shared enhancement availability in
watch --plain(#518):
plain-text output gains aStatus:enhancement line beside the profile
status that announcesAI enhancement: On for {set}with the
profile-backed offline copy when the active set can use enhanced
suggestions and republishes the session's own set-specific message
verbatim fornot-enhanced,incompatible,unavailableanddisabled
states; unchanged statuses are not repeated across polls and the
announcement resets when the active set disappears. (#518) -
Render the shared enhancement availability in the Textual interface (#517):
the status bar gains anAI enhancementlabel that shows the exact
On/Offprofile-backed offline copy for theavailableanddisabled
states and republishes the session's own set-specific message verbatim for
not-enhanced,incompatibleandunavailablesets, while a newe
binding namedAI enhancedispatches the existing
ChangeAiEnhancedSuggestionspreference command only when the shared
availability permits it — the footer control stays visibly disabled and
non-dispatching for the other three states through Textual's
check_actiongate, refreshed on every session publication. (#517) -
Expose AI-enhanced relationship suggestions as an explicit, user-controlled
session capability (#440): a newenhancement_availabilitysnapshot field
classifies the active set asavailable,not-enhanced,incompatible,
unavailableordisabledfrom the set profile's confirmed enhancement,
its role compatibility, participant resolvability against the loaded card
database and the user preference, so frontends can render why enhanced
suggestions are or are not in effect; a newChangeAiEnhancedSuggestions
command toggles the preference, re-scores the current pack, invalidates the
backtest result and republishes the invariant-owned availability state;
PickEngine,project_pool_role_ledgerandgenerate_backtest_reportgain
anenhanced_relationships_enabledgate that removes the typed relationship
synergy term and empties ledgerrelationship_supportwhen the capability
is off, while the newrelationship_enhancement_is_compatiblepredicate
fail-closes on profiles without a compiled role profile or with
relationships whose participants cannot resolve; and the mock provider adds
not_enhancedandenhancement_incompatiblescenarios plus preference
handling for deterministic frontend development. (#440) -
Calibrate the typed relationship scoring against an offline HOB backtest
(#510): the nine pre-calibration0.5support factors are settled as
code-owned constants — the two HOB-observed token mechanisms keep their
deterministic same-card factor and the other seven retain the conservative
uniform value because no outcome labels support mechanism-specific strengths —
and a new trackedhob-relationship-scoringfixture pair plus
scripts/hob_relationship_scoring_smoke.pyprove the effect end to end
without network access: one persisted pre-pick draft is scored under the
compiled enhanced profile, the otherwise identical enhancement-removed
profile, and the all-context-disabled control, exposing exact same-card
raw-score deltas of0.190244(token-go-wide-payoff) and0.205793
(token-sacrifice-outlet), a neutral unsupported row, a saturation row
whose recommended card is itself the relationship target while the
generic synergy term already fillsMAX_SYNERGY_TERM, so the0.75
relationship increment is genuinely clipped, byte-identical determinism
across repeated controls, unchanged persisted state bytes, and a
privacy-safe canonical report that carries only allowlisted evidence. The
token-go-wide-payoff target clause is disclosed as a proxy through the
report'srelationship_projection_notes: the closed prerequisite
vocabulary cannot express the payoff's other-creatures anthem, so the
flash-condition requirement is encoded without the stated Human subtype.
(#510) -
Apply bounded, source-bound typed relationship support to pre-pick draft
recommendations: a confirmed schema-3 relationship whose typed prerequisite
projection is satisfied by a drafted card that survives the likely-deck
projection may now add one bounded synergy increment to its exact offered
target card.draftomen.pool_ledgergains an immutableRelationshipSupport
record, arelationship_supportledger field serialized for audit, and a
fail-closed matcher that dispatches the nine approved mechanisms over the
typed clauses only (exact card identities, compiled role profiles, canonical
prerequisite strings, no claim/quote/guide/run text).draftomen.pickengine
folds the matched signal into the existing synergy term under the current
MAX_SYNERGY_TERMcap with one uniform pre-calibration factor of0.5per
mechanism, renders "Confirmed relationship support" evidence in the detailed
rationale, and selects a single maximum instead of stacking findings, copies
or quantities. Completed-pool evaluation stays relationship-neutral and
historical replay/calibration remains #510 work. (#509) -
Establish one shared typed relationship prerequisite contract in the new
draftomen.semantic_relationship_recordsmodule: an accepted relationship may carry an
optional directionalprerequisite_projectionwhose atomic clauses bind each controlling
cost, trigger, condition, threshold and supplied output fact to one exact frozen Oracle
ability paragraph, a closed color/type/zone/controller/quantity/timing vocabulary and the
complete indices of the capability prerequisites it discharges, with shared validators that
decline to project incomplete, ambiguous or unsupported prerequisites instead of inventing
constraints, while a prerequisite that contradicts its own source evidence becomes a
rejected diagnostic rather than an advisory relationship;CardRelationshipmoves to that
module and keeps every legacy descriptive
field, artifacts and profiles without a projection stay loadable and serialize without the
new key, and relationship duplicate identity now carries the projected direction so
reversed and distinct-capability relationships no longer collapse. Relationship validation moves
to the pinned v2 request and response contract while guide and card extraction stay on their
existing version, so retained v1 relationship results stay readable but are never reused for a
v2 request. (#508) -
Add the interactive terminal
enrich-setcommand that turns the UI-neutral
set-enrichment workflow into one operator journey on the packageddraftomen-tui
executable:draftomen-tui enrich-set SET --guide-url URL --output-dir PATHstreams one
flushed stderr line per guide, capability, candidate and relationship progress event with
completed/total counts, percentages, tokens, live and projected cost, and executed/reused
work; prints a plain-text review whose sections separate guide mechanics, Oracle-validated
card mechanic support grouped by capability role, format/archetype/uncategorised strategy
claims, named strategy claims with their resolved card names, projected inferred synergies,
aggregated uncertain reasons, rejected and malformed diagnostics with deterministic subject
labels, source, guide, model and prompt provenance, the full run, work, card-data and
pending artifact paths, and the reconciled final accounting; defaults every ambiguous
decision point — blank input,Cancel, end of input, an interrupt — to Cancel, accepts only
an exactConfirm, and reports one-shot invalid input as a cancellation; delegates every
reviewed-artifact and profile transition tofinalize_set_enrichmentand never generates a
profile itself, so Cancel printsprofile=not-publishedwhile a Confirm reports the profile
path, the generation report, and the matching profile and gzip checksums; returns 130 with
the resumable-work location when analysis is cancelled or interrupted while keeping the
durable prefix, and reduces every workflow failure to one bounded, path-free
enrich-set failed:line with exit code 1 — retaining the reviewed artifact path when
confirmation failed after publication of the review. (#504) -
Serve the reviewed LCI QuickDraft enrichment from the production profile tree:
website/public/profiles/objects/gains the schema-3 enriched object and
website/public/profiles/manifest.jsonnow lists it forlci/quickdraft, so
clients fetch the enriched profile from the default manifest URL they already
use instead of an opt-in development tree. The published object is
byte-identical to the reviewed artifact and keeps its enrichment provenance
digest. -
Run one set-enrichment analysis as a resumable, UI-neutral workflow through
analyze_set_enrichment, and publish its reviewed outcome through
finalize_set_enrichment, instead of leaving the extraction engine, the
durable work store and the profile publisher to a future interactive surface:
the module resolves one output root and confines every cache, run, source, work
and artifact path to it, re-validating the layout at each phase boundary and
immediately before publishing and rejecting any nested symlink in the source or
profile tree, acquires the pinned card data and freezes the guide under
enrichment-runs/<set>/<guide-key>/without clobbering an existing freeze —
re-validating a reused freeze against the acquisition path's URL rules and a
strict integer schema version — and replays the card-to-card
analysis over durable content-addressed work identities, so a compatible rerun
reuses the completed prefix without a replacement paid request. Analysis
reports the guide, capability, candidate and relationship phases; ordered
progress events; running token and cost accounting — including cached input
tokens — reconciled against exactly one durable model run per request, with a
null response cost disabling the projected-final-cost claim; globally namespaced
findings; and the accepted, uncertain, rejected and failed counts, keeping
candidate omissions out of the failed count. Cancellation before each paid
request and an interrupted analysis preserve the durable prefix, and a
provider failure raises a bounded, path-free error with no artifact. A
completed analysis publishes a pending artifact under the guide-keyed
artifacts directory and leaves it in place for review; a decision records a
distinct content-addressed reviewed artifact, installing it without clobbering
an identical existing object, and rejects an incomplete or already reviewed
analysis, a blank reviewer ID, a naive timestamp, a timestamp preceding the
artifact, and a decision that is not anEnrichmentReviewDecisionvalue; any
failure after that review publication carries the persisted reviewed artifact
on the error. It generates the metadata-only QuickDraft schema-3 profile plus
itsgeneration.json— with matching profile and gzip checksums — only for an
explicit operator Confirm. Cancel records a cancelled artifact and publishes
nothing; confirming nothing publishable fails closed withNO_PUBLISHABLE_ERROR;
and a publication failure keeps the confirmed review artifact and leaves any
existing generation marker authoritative. (#503) -
Compile a confirmed semantic-enrichment artifact into local profile
generation instead of leaving schema 3 unreachable:generate_set_profile(...)
andgenerate_local_profile_artifacts(...)accept one optional keyword-only
enrichmentartifact,compile_profile_enhancementis the only schema-3
writer, and the generation report records the compiled block's privacy-safe
provenance in anenhancementobject rather than any guide text, oracle text,
reviewer identity, or local path. Compilation fails closed before any profile
bytes exist — an unconfirmed or cancelled review, an artifactset_codethat
does not match the requested set, card data whose semantic set-source digest
differs from the generation card database (a limited-card artifact is rejected
by design), a card-data identity that cannot be a profile identity, a
published identity (guide, run, provider, or model) that looks like a local
filesystem path (absolute, home-relative, or.//../-relative), or no
accepted mechanic claim and no confirmed relationship — and each rejection is
a bounded, path-free message that publication re-raises unchanged. Validation
also reconciles the report's provenance against the published block. An
unenhanced generation keeps schema 1 or 2 with byte-identical report bytes and
noenhancementkey, a rejected artifact leaves no output directory, and an
identical replay writes no new object. (#437) -
Carry reviewed model-assisted set enhancement in an explicit schema-3 profile
block instead of leaving it indistinguishable from empirical evidence: an
enhancement_statusofenhancedornot-enhancedplus a self-contained
enhancementobject built from the merged semantic-enrichment vocabulary —
the artifact and set-source digests, the pinned card data, the pinned cards,
guides and model runs, the accepted mechanic and relationship findings, and
the artifact review with its own confidence. The block must cover exactly the
declared card data, carry at least one accepted finding, hold globally unique
finding IDs, resolve every finding's run, guide and card reference, and carry
a confirmed review; an unconfirmed, mismatched or incompatible block is
rejected rather than partially read, and a schema-1 or schema-2 payload that
declares enhancement data is rejected rather than silently dropped. Schema-1
and schema-2 artifacts keep their canonical bytes and report themselves as not
enhanced, model-assisted claims never enter the empiricalsynergyfield, and
the enhancement compiler is the only schema-3 writer. (#436) -
Decide a
token-death-payoffrelationship from its two frozen participants
instead of the model's sampling draw: an enabler that creates a creature token
and a payoff that rewards creatures dying is valid without the enabler's text
showing the token dying, while a payoff whose quoted reward is restricted to
nontoken creatures is not declared. Prompt guidance cannot make identical
evidence receive one verdict — fresh draws of the same pairs arrived 2
accepted / 2 rejected and 0 accepted / 4 rejected — so the rule is read in
parse_relationship_validation_responsebefore the model's verdict, keyed on
the declared mechanism, the two participants' roles and the payoff's quoted
evidence, with the relationship prompt and every work identity left
byte-identical. The re-derived HOB run answers R5 as an accepted relationship,
changes no verdict of any other mechanism, and passes acceptance for the first
time. (#496) (#472) -
Record
token_makerfor a quoted ability that creates a creature token, even
when the same ability already carries the role of its trigger condition, so a
landfall payoff or an attack trigger that makes a creature token still pairs
with a token payoff instead of depending on one sampling draw. An artifact
creature token qualifies, while a Treasure, Food or Clue token, or a
quotation that only mentions a creature token, adds nothing. The recorded
re-run over the frozen HOB sources constructs and accepts
token-go-wide-payoff(103503→103381) andtoken-sacrifice-outlet
(103492→103491), the two expectations the run before it could not
construct;acceptance.passedstaysfalseontoken-death-payoff
(103531→103448) alone. (#494) (#495) (#472) -
Match a reviewed HOB mechanic against exact card Oracle evidence as well as
the guide quotation, so a complete run can evidenceAdventures,Hone CountersandAmassfrom the canonical card artifact instead of the one
guide sentence the extraction happens to quote, and re-author the
103531→103448expectation ontotoken-death-payoff, the declared rule
a token maker and a death payoff can reach. The first complete run under the
new expectations matched all seven reviewed mechanics —Adventures,Hone CountersandAmassonly through card Oracle evidence — and three of seven
relationships, and it failed acceptance ontoken-go-wide-payoff
(103503→103381) andtoken-sacrifice-outlet(103492→103491),
absent because neither enabler is assignedtoken_maker, and on
token-death-payoff(103531→103448), whose constructed pair the
validator rejected. (#472) -
Keep a static ability's card-capability role when the same Oracle text also
states a keyword ability, so an anthem or a creature-count payoff is a
go_wide_payoffon a card that also recruits and can pair with a token
maker instead of being replaced by the keyword's role. (#489) -
Define every card-capability role in the set-independent vocabulary and carry
that glossary, together with the card's declared mana value, power, colors and
produced mana, inside the pinned card request, so the model assigns a role only
when a quoted ability satisfies its definition,sacrifice_fodderexplicitly
excludes token producers, and the newtoken-death-payoffmechanism pairs
creature tokens with death payoffs. (#488) -
Re-author two reviewed benchmark relationships that named a mechanism the role
vocabulary cannot reach:103492→103491and103531→103458now expect
token-sacrifice-outlet, the interaction their card texts actually produce and
the mechanism the paid run already accepted for both pairs, and the benchmark
records the unassignedsacrifice_fodderrole, the remaining unreachable
expectations and the extraction misses behind them. (#472) -
Decide a triggered ability's card-capability role from its trigger event before
its effect, so an ability that triggers when one or more creatures die is a
death payoff and can pair with sacrifice fodder. (#485) -
Retain guide findings whose referenced card IDs are not all named in the claim
for review with the unverifiable references dropped, instead of discarding the
whole finding and its exact guide evidence. (#472) -
Verify a complete set analysis against reviewed expectations: a committed
HOB benchmark pairs a frozen Draftsim guide with required mechanics and
relationship expectations bound to exact Oracle evidence, and a run harness
enforces a hard USD ceiling, reuses durable work across interruption,
reports per-card outcomes, token and cost accounting, omission reasons and
benchmark matches, and proves set profiles stay untouched. (#472) -
Accept the guide and card extraction response schemas against strict
structured-output validation, which rejectsuniqueItems, while the
response validators keep enforcing array uniqueness and non-empty evidence,
so live set enrichment can run against the provider. (#472) -
Run a complete set analysis through a UI-neutral resumable service that
coordinates guide, card, candidate and relationship phases over frozen
sources and a caller-owned work store, reuses matching durable work, exposes
immutable progress and cost accounting, supports cooperative cancellation
and interruption-safe resumption, and returns a pending-review result
without writing set profiles. (#481) -
Validate constructed relationship candidates through a pinned prompt and
response schema that bind each verdict to the candidate identity and its
exact Oracle evidence, persist validated relationships under a durable
relationship work kind, and never turn fabricated, foreign or incomplete
evidence into an accepted relationship. (#480) -
Persist resumable set-enrichment work through a caller-owned
content-addressed store that matches input, model configuration, prompt and
schema hashes before reusing work, keeps raw responses with trusted
accounting and validated results across interruption, and never reports
incomplete, corrupt or conflicting artifacts as completed successful work.
(#470) -
Construct bounded compatible relationship candidates from validated card
capabilities by indexing typed roles, emitting stable enabler-to-payoff candidate
packages that retain exact participant identities, evidence, prerequisites,
timing, zones and quantities, and enforcing an explicit evaluated-pair budget with
deterministic per-mechanism omission diagnostics instead of enumerating all
possible card pairs. (#469) -
Extract typed source-bound capabilities from one complete canonical card and
all of its faces, binding exact Oracle evidence, semantic role, quantity,
timing, zones and structured prerequisites to the selected card and face
while retaining unsupported, foreign or fabricated candidates as diagnostics
and keeping every source-valid interpretation uncertain for semantic review.
(#474) -
Build deterministic guide extraction requests from frozen guide and card
inputs, and parse untrusted responses into source-bound format findings,
mechanics, archetypes and named interaction claims with exact evidence,
explicit malformed, successful-empty, uncertain and rejected outcomes, and
conservative acceptance that keeps an exact quotation as an uncertain guide
claim rather than an Oracle-validated relationship. (#473) -
Make CI signals deterministic by pinning the uv version in every GitHub
Actions workflow and waiting for the desktop card-preview explanation to
settle its scroll position before asserting it. -
Submit strict structured-output requests to OpenRouter through a bounded,
standard-library client that reads its credential only from
OPENROUTER_API_KEY, pins the model, JSON schema and reasoning effort at
construction, requires provider parameter support, and returns generated
content separately from trusted API token, cache, provider and billed-cost
metadata without parsing findings, writing profiles, or mutating production
artifacts. (#447) -
Acquire user-provided Draftsim guides through a bounded, standard-library
HTTPS client that enforces allowed hosts, same-origin redirects, response
size, timeout and UTF-8 content rules while returning verbatim source,
SHA-256, final URL and retrieval time without writing profiles or
production artifacts. (#446) -
Define a versioned, strictly validated semantic-enrichment artifact that
preserves Oracle-derived facts and advisory guide claims separately, records
card and package relationships with explicit prerequisites, keeps uncertain
and rejected findings out of the confirmed collection, and pins card, guide,
prompt, schema, reasoning, usage, and cost provenance in canonical JSON.
(#433) -
Benchmark pinned local Qwen3.5 4B and 9B Oracle-text extraction across a
frozen ELD snapshot, retaining evidence, telemetry, and a stop decision
without changing production scoring or publication. (#426) -
Publish contextual-evidence availability and exact or fallback source formats
from immutable live-session snapshots, with an accessible desktop status that
stays coherent across profile and scoring-mode transitions. (#413) -
Repair GitHub-hosted profile refreshes through the official 17Lands API hostname and canonical hosted event format names.
-
Render detailed pick rationales as base rating plus material drafter-facing
deck-fit reasons, omitting rounded-zero and internal bookkeeping while
retaining structured scoring evidence. (#424) -
Publish QuickDraft profiles from eligible same-set Premier/Traditional
aggregate evidence when exact coverage is incomplete, preserving actual
source provenance and replacing fallback sections on later exact refreshes.
(#421) -
Compose explicitly supplied same-set aggregate ratings independently by card
and color pair, with versioned source provenance and conservative cross-format
confidence for QuickDraft fallbacks. (#420) -
Generate hosted profiles through aggregate-only staged acquisition, retain
prior empirical profiles when evidence is unavailable, and publish canonical
batch provenance without exposing diagnostic inputs. (#416) -
Add explicit aggregate-only profile acquisition for Oracle metadata and
17Lands card/color evidence, with verified-cache fallback and privacy-safe
provenance preserved through staged generation and batch reports. (#415) -
Compile deterministic semantic card roles into EARLY empirical profiles so
contextual scoring can use Oracle metadata before public draft data exists.
(#410) -
Show each ranked plain-watch card's unchanged concise pick rationale directly
below its row while preserving buffered publication identity and replay output.
(#405) -
Explain why the top DO recommendation outranks the runner-up using retained
scoring evidence, preserve the comparison across display sorting, and record
it in decision audits without changing evaluation identity. (#398) -
Show the unchanged top-two DO comparison beside confidence in the TUI,
plain-watch pack footer, and desktop Live Draft header while preserving its
DO-order meaning across display sorting and buffered publications. (#399) -
Prevent pull-request CI runs for generated-only website card-data and profile
refreshes while retaining source pull-request and master-push coverage. -
Classify active and historical profile refresh formats at expansion level,
keeping every supported format in the expansion's lifecycle partition. -
Center and theme the live ratings-refresh confirmation consistently with the
About and Settings dialogs while preserving keyboard focus and commands. -
Show grades for empirical profile ratings by applying the existing 17Lands
grading scale to the published positive-sample GIH distribution. -
Fetch hosted card metadata when restoring a completed draft with an empty
local cache, while keeping active recovered drafts offline. -
Show unchanged concise pick rationale in compact desktop card previews and
unchanged detailed rationale in focused intel, with wrapped plain text,
retained scrolling and no pick rationale in build previews. (#389) -
Show each plain-watch pack's unchanged concise top recommendation immediately
after its ranked rows while preserving event-specific text for buffered packs
and omitting recommendation output when none is available. (#388) -
Show each focused offered card's unchanged session pick rationale below its
TUI facts, keep it mouse-wheel accessible in short terminals, and omit pick
rationale from build context. (#387) -
Add deterministic TUI CI coverage proving hosted profile refresh workers stay
blocked while keyboard input remains responsive. -
Add immutable per-card pick rationale with exact evidence and score accounting,
publish concise and detailed explanations through sessions and audits, and
include detailed rationale in every nonempty replay pack. (#355) -
Add an explicit shared-engine contextual-adjustment mode that can disable
additive contextual terms while retaining profile-backed base scoring and
non-contextual evidence. (#380) -
Add the default-enabled live-session and backtest contextual-adjustment
mode with immutable state, explicit commands, immediate local rescoring,
stale comparison invalidation, and no toggle-triggered external work; deck
construction remains independent. (#381) -
Add the persisted desktop Settings → Contextual pick scoring switch,
defaulting off while retaining the shared API/session default-enabled
contract; it re-scores current and later packs and backtests, survives a
fresh-process restart, and remains independent of profile refresh/cache and
deck construction. (#382) -
Native live startup now defaults to the production hosted profile manifest,
supports explicit HTTPS overrides and profile-only--offline-profiles,
and leaves static card-data, card-image, and card-metadata policies
unchanged. Existing ratings refresh controls use the shared hosted-profile
lifecycle, reportingupdatedorunchangedoutcomes and retaining the last
usable cache or deterministic fallback as applicable when refreshes fail, go
offline, or find no profile, while preserving visible 17Lands attribution.
(#354) -
Default terminal
watchprofile loading to the production manifest, add
--offline-profilesfor profile-only offline mode, and retain cached or
deterministic-fallback ratings when hosted refreshes fail. Producer,
publication, and release boundaries remain separate. (#353) -
Report profile-refresh publication as successful after verifying the generated
commit reachedmaster, even when GitHub PR merge metadata is delayed or
unavailable; keep master verification failures fatal. -
Isolate recoverable ratings errors to the active set at snapshot publication:
hide inactive-set errors while retaining nondismissed errors for return,
remove dismissed errors, and make Retry queue the active set's forced
hosted-profile refresh without disturbing unrelated operation errors. -
Remove direct provider-loader callbacks, cache/progress machinery, and raw
ratings surfaces from normal terminal and native live factories; TUI,
plain-watch, CLIwatch, and Qt now use the shared hosted-profile lifecycle
while preserving configured manifest overrides. (#370, #371) -
Complete the normal
LiveSessionprovider cutover: profile state is the sole
live ratings authority, cache-first startup and deterministic no-provider
scoring/build/backtest fallback remain intact, and explicit producer plus
separate offline/domain cached-provider workflows remain supported. (#373) -
Migrate shared-session regression fixtures to profile-backed inputs or
deterministic fallback and carry the lifecycle contract through end-to-end
adapter workflows, including refresh adoption, failure retention, and
shutdown guards. (#372, #374) -
Propagate explicit hosted-profile refresh requests with
force=True, bypassing
only the manifest TTL while preserving offline, authority, validation, and
non-regression safeguards and usable ratings during refresh. (#367) -
Route explicit ratings-download and recoverable ratings-retry actions through
that forced hosted-profile lifecycle, coalesce repeated requests, and update
recommendations in place after validated adoption; TUI and Qt retain existing
actions and plain-watch adds no command UI. (#368) -
Keep hosted-profile refresh generations scoped to the active lifecycle, rejecting obsolete completions on set/account/draft changes, clear, and stop without restarting on ordinary picks or repeated same-lifecycle detection. (#360)
-
Use cached empirical profile ratings immediately for live scoring and keep
deterministic fallback scoring provider-independent. (#361) -
Adopt hosted refreshes atomically across profile identity, profile-derived
freshness, current-pack scores/context, and recommendations; retain strongest
usable authority on outage, invalid, or weaker results and avoid rescoring
unchanged outcomes. (#361) -
Use hosted card and aggregate pair estimates in recommendation scoring, with exact canonical matching, deterministic legacy fallback, and no provider or lazy scoring requests. (#351)
-
Keep profile-refresh publication checks deterministic by evaluating fixture
ratings against their frozen test clock. (#351) -
Add guarded profile-refresh generation-artifact publication with validated
full-success automatic merges, immutable partial review snapshots, and
stale-base, failure, and unchanged-run safeguards. (#345) -
Add the generation-only scheduled and manually dispatched profile-refresh
workflow with read-only execution, structured failure evidence, and
successful generated-asset bundles. (#344) -
Use cached ratings or a local fallback for live locked-pair scoring without lazy 17Lands requests, while retaining the current-pack individual win-rate display and visible 17Lands attribution. (#339)
-
Add the local
refresh-profile-dataproducer command for deterministic set
selection, cached aggregate 17Lands ratings, validated content-addressed
profile publication, and bounded partial-failure reporting. (#338) -
Add the initial read-only CI profile-refresh evidence workflow as a
generation-only, publication-independent baseline. (#303) -
Bundle the immutable HOB/QuickDraft metadata-only baseline in native
applications with validated offline fallback and hosted refresh
supersession. (#313) -
Record the production HOB/PremierDraft metadata snapshot audit evidence from the #319 producer run; retain the gzip payload locally for publication. (#319)
-
Publish the first production HOB/PremierDraft metadata-only profile snapshot through content-addressed website assets. (#320)
-
Complete the production hosting marker add/fetch/remove verification lifecycle. (#320)
-
Add deterministic
generate-profile-refresh-batchgeneration from staged
refresh plans with isolated environment outcomes, privacy-safe reports, and
no-network, no-publication execution. (#307) -
Adopt the master-only Cloudflare website static-asset contract for hosted
profiles: production and development paths share complete website
deployments, validated digest-addressed objects, explicit cache and
retention/legal-erasure boundaries, and a two-merge smoke check. Hosting
remains independent of stable releases, native releases, PyPI, Homebrew, and
application startup. (#285) -
Add
execute-profile-refreshto stage portable, content-addressed profile
inputs from strict plans with bounded cache reuse, offline replay, and
privacy-safe execution authorities. (#290) -
Add deterministic profile-generation stage selection from staged ratings and
public-draft availability with immutable thresholds and privacy-safe records.
(#301) -
Add deterministic single-environment profile generation from staged inputs with publication eligibility only after existing schema, identity, size, and checksum validation, plus affected-card diagnostics, valid metadata fallback, and bounded failure records without partial artifacts. (#304)
-
Tighten agent skill guidance: single full-length waits for delegated
implementation slices, size-based implementation readiness with board-time
epic decomposition, and numbered acceptance-criteria issue templates. -
Add format-scoped public-draft acquisition with deterministic row reporting,
verified cache and offline reuse, stale fallback, and independent three-source
failure handling for profile-build bundles. (#296) -
Add optional format-scoped 17Lands ratings acquisition with deterministic
sample reporting, bounded cache reuse, offline support, stale fallback, and
metadata-only failure recovery. (#295) -
Add set-scoped card-metadata acquisition with deterministic source records,
bounded cache reuse, stale fallback, and metadata-only profile-build bundles.
(#292) -
Add bounded, content-aware profile-input caching with strict canonical
records, verified offline reuse, deterministic retention, and privacy-safe
outcomes. (#288) -
Add deterministic
plan-profile-refreshdry runs with explicit Arena
lifecycle metadata, 17Lands expansion discovery, bounded selections,
canonical plans, diagnostics, and atomic plan output. (#283) -
Reduce GitHub issue and project API usage with centralized authenticated I/O,
explicit call budgets, batched ProjectV2 mutations, and single-pass
verification. -
Expand the GitHub issue workflow with implementation size and orchestration-risk
classification plus approval-gated epic decomposition and dependency linking. -
Add issue-226's remote set-profile manifest/client workflow with
offline-first cached loading, explicit live/manual refresh, validation,
last-good recovery, and compact maturity/outcome status; discovery, scheduling,
backfill, and publication automation remain owned by #227; hosting is provided
by #285. (#226) -
Fix
generate-profile --format quickdraftto accept pinned ratings caches
withQuickDraftmetadata in any casing while preserving normalized profile
identity. -
Add the producer-side
generate-profileworkflow for staged metadata, early,
and mature set-profile artifacts with pinned inputs, validation, atomic
publication, deterministic checksums, and privacy-safe aggregate output.
(#274) -
Add a deterministic, provenance-preserving offline reader for public CSV dumps with checksum verification and privacy-safe reports. (#272)
-
Route shared 17Lands draft-row ingestion through the provenance-preserving structure-target builder. (#272)
-
Extend bounded whole-package deck ranking with profile-aware semantic and
empirical package terms, confidence- and maturity-bounded evidence, generic
no-profile fallback, and frozen HOB draw-second regressions and
counterfactuals. (#269) -
Add bounded deterministic whole-package beam search and local improvement to
deck spell selection, while preserving deck, splash, mana, pip, and
constraint-relaxation invariants. (#268) -
Route validated pre-pick scoring context through live, recovery, accountless, replay, backtest, benchmark, and audit workflows with recommendation/audit evidence parity. (#250)
-
Define immutable pre-pick scoring context with deterministic profile provenance and pair-theme annotations. (#251)
-
Add bounded contextual pick-score terms for projected role need, late
urgency, semantic package support, redundancy, unsupported payoffs, and
fixing, with material explanations and audit evidence. (#252) -
Shrink contextual pair and locked pair-card performance toward neutral/global
priors using bounded profile and rating sample evidence. (#253) -
Add a development-only reproducible card corpus workflow with pinned Scryfall,
current and legacy Arena mapping inputs, MTGJSON inputs, deterministic
normalized artifacts, and coverage reports for offline semantic-analysis work. -
Extend card metadata with normalized face semantics, source-aware augmentation, and schema-4 offline cache migration.
-
Add a typed, deterministic Limited semantic-role classifier with multi-valued
assignments, effective-removal/threshold/mana parameters, canonical keywords
and textual power support, reviewed overrides, and actionable unknown reports. -
Compile exact-set profiles with shared stable identities, atomic publication,
deterministic duplicate handling, conservative unknown omission, and
version-checked resolution; document the workflow. (#220) -
Add a versioned, deeply immutable local set-profile boundary with strict
sparse empirical sections, semantic-role compatibility, and non-raising
maturity-aware fallback loading. (#221) -
Add a deterministic immutable pool role ledger with explicit pre-pick
projection and completed-pool modes, stage urgency, profile targets, and
normalized interaction/package evidence. (#222)