Skip to content

Releases: OnlyWorlds/python-sdk

onlyworlds 0.45.2

Choose a tag to compare

@github-actions github-actions released this 24 Oct 12:32
  • The doctor's flag 4 counts a dependency as a link on a spine world. A spine draws its edges with x_spine_depends_on, so on a world that carries the profile (any x_spine_ key, flag 13's test) a non-empty list is a link out from its element and a link in to each id it names. Before, every element of the OnlyWorlds Spine read as having no links in or out (348 of 348 on its first run through a crew seat); now 102 of 378 do, each with neither a link field nor a dependency either way. An empty list is no dependency. On any other world nothing changes. A test with a mutant watched failing.

onlyworlds 0.45.1

Choose a tag to compare

@github-actions github-actions released this 24 Oct 11:55
  • The .owworld reader's NFC is Unicode 15.1's own, built from the set's files. OW-18 folds every entry name with NFC, then simple case folding, and two names that fold to one refuse the file. The fold was already a table from the vendored CaseFolding-15.1.0.txt; the NFC before it was the interpreter's unicodedata.normalize, which is Python's Unicode (15.0 on 3.12, 16.0 on 3.14). Since schema-dist serial 57 the spec (§4.7) rules that the NFC is built from UnicodeData-15.1.0.txt and CompositionExclusions-15.1.0.txt, vendored beside CaseFolding, never a runtime's. On 3.14 the old reader joined 20 code points that 15.1 leaves unassigned (Todhri, Tulu-Tigalari, Gurung Khema, Kirat Rai): U+11383 against U+11382 U+113C9 was refused as one name, and is two at 15.1. The same fold matches a private producer's RECORDS.json entry to its directory (OW-8), so that follows too.
  • onlyworlds.worldfile.nfc, UAX #15 from the two files: full canonical decomposition (Hangul by arithmetic), canonical ordering, canonical composition skipping the listed exclusions, singletons and non-starter decompositions. Its tables are _nfc.py, generated by codegen/generate_nfc.py as _casefold.py is by generate_casefold.py, so the wheel needs no file from codegen/. worldfile.py no longer imports unicodedata.
  • Tests: every line of Unicode's NormalizationTest-15.1.0.txt (19,074 lines, vendored under tests/fixtures/, 2.6 MB, its sha256 checked) holds both NFC invariants, and every code point Part 1 does not list is its own NFC; the 20 code points stay apart in a world file (and are checked joined under unicodedata 16.0 or later, so the test is live); the generated module is current; the .owworld set holds at 93 of 93. Mutants, each restored: composing an exclusion, skipping canonical ordering, ordering by code point, dropping Hangul composition, removing blocking, and one-level decomposition each fail the NormalizationTest test; skipping ordering and ordering by code point also fail the set (fail-OW-18-nfc-reorder, pass-OW-18-nfc-same-class); the old unicodedata call fails the 20-code-point test.

onlyworlds 0.45.0

Choose a tag to compare

@github-actions github-actions released this 24 Oct 11:42
  • The doctor's flag 13, the spine (OW Spine #614's last half: "the doctor lints the Spine world against it"). On a world where some element carries an x_spine_ key (any other world skips the flag and says so), every element is read by read_spine_element. A listed type whose supertype is off the spine's list or empty is a finding; so is each value the reader drops (its key and value) and a probe that is not in the probe form. Then the audit's definite parts: each row (an Object, Construct, Location or Law of a listed kind, the world's Charter included, since the page exempts none) must be kept by exactly one Title with supertype Seat, through the Seat's field for that type; no seat, or two, is a finding. Every x_spine_depends_on id must be in the world (not checked through a guest key: an id a guest cannot see is not a missing one). Never checked, and named so in the report: a legacy or provenance row's Retirement Event (the page names it by the row's text, which no structure attributes), whether a probe passes, and x_spine_probed. Known-of stubs are not read. Run on the landing's 360 rows as a folder, it names the 21 probes written as prose; every row reads "no seat keeps it" until the seats' Titles land.
  • Schema repinned to schema-dist v0.33.0-dist.57 (from dist.56; same canonical 00.33.00, no schema file moved). The .owworld set grows to 93: eight OW-18 cases on NFC, with Unicode 15.1.0's UnicodeData and CompositionExclusions beside CaseFolding. read_world_file agrees with all 93. Its NFC is the interpreter's unicodedata (Python 3.12 ships Unicode 15.0, 3.14 ships 16.0), not a normaliser built from the set's files; the eight cases use characters every one of those versions treats alike.

onlyworlds 0.44.1

Choose a tag to compare

@github-actions github-actions released this 24 Oct 11:15
  • Schema repinned to schema-dist v0.33.0-dist.56 (from dist.55; same canonical 00.33.00, no schema file moved). The one serial settles five readings of profiles/spine.md that the first reader found ambiguous, and the fixture grows to 40 cases.
  • SpineRead.dropped entries are {"key", "value"} dicts (were "<key>: <JSON>" strings), the value exactly as the element held it, a copy. The page now compares dropped as JSON values, never as text, because Python and JavaScript write JSON differently. A caller that read the strings changes; a SpineRead that dropped something is no longer hashable.
  • A non-string x_spine_truth or x_spine_probe is named in dropped (it was left out silently). The order is the page's: address, truth, access, status, layer, audience, depends_on, probe, verified.
  • Already so in 0.44.0, and now on the page: probe verbs are syntax (case-sensitive, single spaces), verified.at must be a real calendar day, and an empty depends_on is stated.
  • Tests: the fixture is compared as canonical JSON, because Python's == holds True == 1; a dropped boolean stays a boolean; the page's key order; the probe form's syntax. Two mutants watched failing (a boolean written as 1, a non-string probe not named).

onlyworlds 0.44.0

Choose a tag to compare

@github-actions github-actions released this 24 Oct 10:56
  • onlyworlds.spine, the spine profile's first reader (schema-dist profiles/spine.md, serial 55; OW Spine #614): a world that maps a software ecosystem, in the 22 types and nothing more. read_spine_element(type, element) reads one element (a body or a FolderElement) and returns a SpineRead: its kind (the closed list's spelling, off-list for a listed type whose supertype is off its list or empty and for every type the list does not name, free for a Character, an Institution or a Collective), each x_spine_* key as read or None when not stated (address, truth, access, status, layer, audience and its primary, depends_on, the probe's verb or unsupported, the verified date), and every value it left out, named in dropped; as_dict() gives the fixture's shape. Supertypes and machine values are compared trimmed (Unicode White_Space, exactly) and by Unicode simple case folding, the room profile's definition and is_room_element's helpers, never str.strip() or str.casefold(). SPINE_KINDS (exported, as ROOM_PAIRS is) is generated from the page's table into _schema.py and checked against the fixture's cases at generation; the key value lists (SPINE_ACCESS, SPINE_STATUSES, SPINE_LAYERS, SPINE_AUDIENCE, SPINE_PROBE_VERBS, SPINE_FREE_TYPES) are typed in the module and tested against the page's rows. All 34 fixture cases read as their read block. Not done here, as the page says: the world's audit (one owner per row, a depends_on id resolving, a Retirement Event), running a probe, and the calendar: the fixture's six calendar steps are the npm SDK's kernel's (4.70.0) to check, and this package has none. One choice past the reference reader: a verified at must be a real day (2026-02-30 is not stated, and dropped).
  • Schema repinned to schema-dist v0.33.0-dist.55 (from dist.54; same canonical 00.33.00, no schema file moved). The one serial adds profiles/spine.md and profiles/spine.fixture.json (34 cases, six calendar steps) and the README's profiles row; _schema.py gains SPINE_KINDS and moves its provenance lines (SCHEMA_DIST_TAG, SCHEMA_DIST_SERIAL 55, SCHEMA_MANIFEST_SHA256). Tree from git archive of the tag (commit 2937031); MANIFEST sha256 7b4db33d... matched against the raw file GitHub serves at the tag. FORMAT_VERSION stays 0.3.18.
  • The PyPI page links the docs, the source, the issues and this changelog ([project.urls]; until now it linked nothing, so a person with a bug had no door from it).

onlyworlds 0.43.1

Choose a tag to compare

@github-actions github-actions released this 23 Oct 12:54
  • Schema repinned to schema-dist v0.33.0-dist.54 (from dist.49; same canonical 00.33.00, no schema file moved, so _schema.py moves its provenance lines only: SCHEMA_DIST_TAG, SCHEMA_DIST_SERIAL 54, SCHEMA_MANIFEST_SHA256). Five serials in the vendored tree: 50 and 51, example/world-export.json's world block is the World whole, with origin and x_names (keel #516, #571); 52, profiles/review.md's reader rule (a reader that hands a world on leaves proposed elements out unless asked); 53, the folder lint (walk/lint_folder.py) takes hidden as a folder key, true or false (folder spec §4.8), and review.md's rule 4 on a malformed mark; 54, profiles/checks.md's where.type as a list and reader rules 6 to 8 (a known-of stub judged by no rule, a pattern outside the shared subset not checked by name, the size cap no step limit), and checks.fixture.json's rule 6 with four cases and three not-checked rows. The doctor already reads all of it: the fixture replays clean (7 rules, 17 cases, 39 expectations, 11 not-checked rows). Tree from git archive of the tag (commit 6153745); MANIFEST sha256 82ba25c1... matched against the raw file GitHub serves at the tag. FORMAT_VERSION stays 0.3.18: the dist carries no folder-format stamp, and the package's moved by hand in 0.42.0. No API change.
  • apply_checks judges no known-of stub itself (the checks profile's rule 6, dist.54): a stub is neither scoped nor short. Until now only the doctor left stubs out before calling it, so a direct caller passing a guest's stubs got them reported short on fields that are unknown, not empty.
  • Tests: the door tests' lint checks (LegendKeeper's API and file roads, Kanka, World Anvil) tolerated one "hidden is not a field of" line per hidden element while the lint did not know the mark; now that it does, any lint line fails them (test_folder_lint_passes_with_the_hidden_mark, renamed from ..._but_for_the_hidden_mark, in three files; lint_ok and hidden_lint_ok), each watched failing against dist.49's lint. The doctor's checks tests hold dist.54's counts as their floor and require the fixture's null-reason control row, so the not-checked comparison runs both ways.

onlyworlds 0.43.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 12:03
  • draught(..., compact=) (keel #585, PR 198, live 2026-10-23 13:30): compact=True leaves out every section that is an empty list or object, and cut when it is empty; the frame (world, calendar, as_of, now, mode, policy) and every null stay, since a null is an answer. Sent as true or false; None (the default) sends nothing. Anything but a bool is a TypeError before anything is sent, as the npm SDK's 4.69.0. The live wire test now calls draught with all eight policy keys, so each is checked against the document's parameters.
  • A create sends the hidden mark (keel #587, PR 199, live 2026-10-23 13:30; folder spec §4.8). create, upsert and bulk now send hidden as the element has it (CREATE_FIELDS; sanitize_payload(..., create=True)), so an element hidden in a folder is created hidden from its first moment, never visible for a moment. Until now the three stripped it, so such an element was created visible: a behaviour change. Only the owner's keys and a co-builder's may send true; any other key gets a 403 hidden_not_allowed (new ApiError.is_hidden_not_allowed; a bulk slot's 403) and nothing is created; a server with the hidden mark off answers 422, param hidden. An update never sends it: patch, propose and push's patches strip it as before (keel drops it from an update, and a PUT that replaces ignores it). A create retried after a lost answer reads the element back and takes it as its own only if the mark matches. push creates nothing, so its withholding stands: an element hidden in the folder and not in the baseline is in the baseline, so on the server and visible, and keel moves an existing element's mark only by its own route (PushResult.hidden, unchanged; the docstring now says why). stops_run is unchanged: push never sends the mark, so it never meets the 403.
  • A reader that hands a world on leaves hidden elements out (Skeld's ruling, OW Council h58 #11461, #11462; folder spec §4.8): an element carrying hidden: true is hidden from whoever the world is handed to, never from its holder. folder.is_hidden (exported) is the one test: any value of the mark but absent, null and false, so a doubt leaves the element out. The Markdown pack leaves one out unless hidden=True (--hidden) on build_pack, pack_world, pack_folder and pack_api, counts it in 00-world.md's opening lines (*1 hidden element is left out of this pack.*), PackReport.hidden_left_out and the command's line; kept, it is labelled hidden under its id line (pack.HIDDEN_LINE), on its index line and on every link to it (Cy (character, hidden)), PackReport.hidden_kept. Unlike a proposed element, one left out is never named: a link to it is left out and an in-prose reference keeps only its own label (PackReport.hidden_links_left_out), as keel leaves a hidden element out of every answer to a reader who may not see it. A hidden element counts as hidden, never as proposed or a room element. The OKF bundle the same: left out unless hidden=True (build_bundle, export_okf, --hidden), no file, no index line, links to it left out (never a urn:uuid:), an in-prose reference its label, counted in OkfReport.hidden_left_out and world.md's onlyworlds_export.hidden_left_out; kept, its frontmatter carries hidden: true and every link and index line to it says (hidden). A world with no hidden element packs and exports byte for byte as before. export_world and write_folder copy a world and keep the mark; the doctor shows a world to its holder and drops nothing.
  • The .owworld writer keeps hidden elements unless the file is a share (Skeld's ruling, OW Atlas h20 #11469; folder spec §4.8). write_world_file and world_file_bytes take include_hidden=True: a world file is a copy, and a hidden element's file travels byte for byte. include_hidden=False leaves every element file in elements/ or spatial/ whose JSON object carries the mark out whole, nothing else rewritten (a link to it keeps the id, which dangles, as ruled). The count: private records have no report to follow (the writers return a path or bytes), so a list passed as hidden_left_out= receives the left-out files' paths, sorted; its length is the count. The two defaults differ on purpose: private records out unless asked, hidden kept unless the write is a share.
  • Tests: compact sent as true and false, absent sends nothing, a refusal sends nothing; hidden on create, upsert and bulk, none on a visible create, never on patch or propose, the 403 and the 422 raised once and not resent, a bulk slot's 403, the read-back with the mark; a push never sends the mark (the folder unhid it), and creates nothing for a hidden element new to the server; the pack and OKF each with a hidden element left out, counted and never named, kept and labelled, links to it either way, the command lines; the world file's copy byte-identical, the share's files and count, determinism either way; a staging case (an owner's hidden create unseen by a contributor, a contributor's refused; skipped without the staging keys, not run). 30 mutants watched failing, one per rule.

onlyworlds 0.42.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 11:24
  • No tool name in a supertype (the schema owner's lane rule, Skeld, OW Market h40 #11385, #11386: "a converter never writes its own name into supertype or subtype; where a thing came from is the producer line and its x_<tool>_ keys, what a thing is goes in the type words"). Behaviour change in three doors: an untyped element came in as a Narrative with supertype kanka (a Kanka module with no OnlyWorlds type), notion (a row of an untyped Notion database) or legendkeeper (a LegendKeeper page whose tags name no type, or two); each now comes in with supertype Article, as the World Anvil and Campfire doors already write. Nothing else moves: the subtype (Kanka's module folder, Notion's database title), the tags, the x_<tool>_ keys and every id stay as they were, and a test pins each door's ids to those 0.41.0 gave (Kanka's and LegendKeeper's real exports, Notion's built fixture, LegendKeeper's recorded API answers). No other place in the package writes a door's name into a supertype or subtype.
  • LegendKeeper maps (onlyworlds.legendkeeper; Skeld's ruling, OW Market h40 #11385; Boss's three cases, #11387; Seethe's measured placement, #11426, #11429). From the export file, a map document becomes a Map, named <resource>: <document> as a hidden page's Narrative is: width max_x - min_x and height max_y - min_y from the document's map bounds, the bounds kept as x_legendkeeper_bounds and max_zoom as x_legendkeeper_max_zoom; image_url the map's mapId only when it is an http(s) address, as given and never copied (the image lives on LegendKeeper's host and loads only as long as that account's asset does, which the report says); a bare asset id (the tutorial map's) kept as x_legendkeeper_map_id, never written as a URL; location when the map's resource became a Location, else x_legendkeeper_resource its element id. A map document with no map object is a Map with no width, height or image, named so in the report, never zeros. Each pin becomes a Pin on its Map: its name, or, for a pin with none, the name of the element it places (what LegendKeeper shows), each named in the report; element_type and element_id the element its lk://resources/<id> uri names; a pin with no uri, or one naming no resource of the export, a Pin with no element, named, never a dangling id. Its place: the bounds are image pixels, but LegendKeeper's pos is [y, x] in zoom-0 units, an image pixel divided by 2^max_zoom, y counting down from 0 at the map's top to min_y; OnlyWorlds counts image pixels from the bottom left, so x is x * 2^max_zoom - min_x and y y * 2^max_zoom - min_y, a half rounded up, the exact pair kept as x_legendkeeper_pos, and the report names each map's scale ("positions scaled by 2^2 = 4"). Measured on two pins of Seethe's quay map, an 800 by 600 image with max_zoom 2 (OW Market h40 #11426, #11429; Skeld #11428): the first, read at image pixel (127, 110) from the top left, is stored [-27.5, 32], which times 4 is (128, 110): x 128, y 490; the second, read at about (796, 524), is stored [-131.118, 199.314]: x 797, y 76. Both fit the scaled reading and neither the unscaled one. A pin on a map with no max_zoom gets no x, y (the scale is not known, never guessed), keeps its pos, and the report names the map; its icon and label (iconGlyph, iconColor, iconShape, labelSize, labelVisibility, isSynced, any other) together as x_legendkeeper_pin. A hidden map document, or one on a hidden resource, is a hidden Map whose Pins are hidden; a pin whose isHidden is true a hidden Pin (no real file has a hidden pin or map yet: the tests plant them). Ids UUIDv5 of legendkeeper:<project>:map:<resource>:<document> and ...:pin:<resource>:<document>:<pin>. The API road keeps 0.41.0's behaviour: the API's map shape (bounds, pins) is not known, never read on the wire, so a map read through the API stays not imported, and the report now says why.
  • The third real export (Seethe's, a few hours after the first, the JSON type, her quay map with two pins: "The quay" on her page, and one near the map's right edge with no name and no uri, a Pin with no element named Untitled pin (uhljd0gj) in the report): banked as tests/fixtures/legendkeeper/the-quay-world-3.json, Boss's scrubbed copy (OW Market h40 #11434): the account's createdBy id and her map image's asset id each a same-length placeholder, LegendKeeper's tutorial asset ids and its authors' ids as exported. A test checks every uuid left on LegendKeeper's asset hosts is also in the first export (LegendKeeper's own tutorial content) or the placeholder. It becomes 113 elements: 2 Characters, a Creature, 29 Events, a Location, 5 Maps, 54 Narratives, 18 Pins, 3 Relations. The first export's folder is byte for byte 0.41.0's but for the supertype, its maps (4 Maps, 16 Pins) added.
  • Fixtures: no account identifier (Skeld's doctrine, OW Market h40 #11415; Boss's scrubs, #11420, #11430, #11434). The Kanka fixture is Boss's scrubbed copy, renamed tests/fixtures/kanka/quay-export-world_20261023_074706.zip (the old name carried the username): the username, user id and campaign id each a same-length placeholder. The Kanka fixture's ids moved with the scrubbed campaign id (the door keys them on it); a real user's ids are unchanged: 0.41.0 run on the scrubbed file gives the ids the test now pins. The LegendKeeper .lk fixture is Boss's scrubbed copy too (the account's createdBy id a placeholder), and the door's folder from it is the unscrubbed file's, byte for byte. A new test (tests/test_fixture_identifiers.py) holds the Kanka username, the LegendKeeper account id and its map image's asset id by sha256 only, and fails if any word-start window of any fixture (zip members and gzip read through) or test file hashes to one; run on the unscrubbed exports it finds each.
  • Folder format v0.3.18: a stamp move, the spec's one change being the campfire-export word (Skeld, OW Market h40 #11413). FORMAT_VERSION is 0.3.18.
  • Tests: on the third export the quay map and its two pins at their measured places, the scale the report names per map, the bare-id map and its 16 unnamed pins (Wiki City x 3553, y 5445 at 2^6), the three map-less documents, counts, the lint, determinism; on planted copies bounds that do not start at 0 and half bounds, a map with no max_zoom, a hidden pin, a hidden map, a pin naming no resource, a visible pin on a hidden page; the API road's map named; Kanka's untyped module on a planted copy; the ids of every door; no account identifier in any fixture or test file, by hash. 27 mutants watched failing, one per rule (the unscaled position, a guessed scale with no max_zoom, and a blind hash check among them).

onlyworlds 0.41.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 10:57
  • The Campfire door (onlyworlds.campfire): python -m onlyworlds.campfire --file EXPORT.html OUT-DIR [--project NAME] [--plan] and import_campfire(source, out_dir, plan_only=False, project=None) read Campfire's export (File, Export Elements, the html format) into a world folder written through write_folder. No AI, no account, no new dependency (the Kanka door's HTML to Markdown). A documents door, said in its docstring (the schema owner's rules, Skeld, OW Market h40 #11368): Campfire's web app has no data export, only four documents of the same text (docx, pdf, html, rtf), and the door reads the html. Proven on one real export (Seethe's project on a free account, 2026-10-23; its bytes banked as tests/fixtures/campfire/campfire-export.html): the document's title, then one section.export-item per element, its name, its description, its pages of panels (custom panels of Label / value pairs, text panels), an em dash for an empty value. What becomes what: each element heading is an element, its description block the description; each filled panel's Label / value pairs are kept as x_campfire_<panel>_<label> in lower snake case (a text panel as x_campfire_<panel>, a number as a number), an em dash or an empty paragraph read as empty and not written; no panel fills an OnlyWorlds field. The type: the file names no module (no Characters or Locations heading, in the html or the docx), so the module is read from each template's own panel words (TEMPLATE_MODULES: Basic Information / Place of Residence and its neighbours for Characters, Location Details for Locations, each read on the real file) and the type from the module by one table, MODULE_TYPES, mapped against the definitions; the module from the panels and the table are as the schema owner ruled (Skeld, OW Market h40 #11396): Characters Character and Locations Location, seen; Species and Cultures Species, Items Object, Languages Language, Religions, Philosophies, Systems and Magic Construct ("a magic system is how the world works, not a thing anyone does"), Maps Map, believed; Timelines, Arcs, Manuscript, Encyclopedia and Research stay unknown, and Relationships too until a real file shows one with two ends (then Relation). A module not in the table is a Narrative with supertype Article and the module's name as subtype; an element whose panels match no known module, or two, a Narrative with supertype Article. The report names, per element, the panel words its module was read from (which panel and label matched which module), or that none matched (ImportReport.evidence, ModuleEvidence). Ids are UUIDv5, since the file has none, and the file holds no links: the report says both on every run (a second export gives the same ids only while the names hold; a renamed element comes in new). --project NAME (project=; Skeld, h40 #11396): the file names no project, so a project name given keys every id (campfire:<project>:<type>:<name>, the world campfire:<project>:world) and names the world. Without it each element is keyed campfire:<type>:<name> and the world campfire:world:<title>, named for the document's title, and the report says plainly that two projects exported under Campfire's default title "Campfire Export" would share ids, and that --project NAME keys them apart; a blank name is refused. One resolution: a Character's Place of Residence that equals a Location's name in the same export becomes its location link, else stays the x_campfire_ field; a name inside prose stays prose. No hidden rule: nothing in the file marks an element hidden, and the door says so. A second element of one type and name is keyed :2, an exact copy folds, text outside the parts read is kept as x_campfire_unread; all named. producer.input is campfire-export, the word on the folder spec's §4.2 list since v0.3.18 (Skeld, h40 #11396); the folder's format_version stays FORMAT_VERSION (0.3.17) until the next schema-dist serial moves it.
  • The real file becomes 2 elements: Ada Okafor a Character (x_campfire_basic_information_full_name, _place_of_residence "The quay", x_campfire_bio naming Mara Voss, kept as prose) and The Ferry Quay a Location (four numbers Campfire printed as 0, kept as 0 and named: the file cannot tell a 0 from a number never set). "The quay" is not "The Ferry Quay", so no link: the negative is the real file, the link a planted copy. The dist's folder lint passes both. Tests: the fixture's hash and size, and that it carries no script, no form and no mail address (each pattern watched catching a sample); counts, types and every field; the em dash; the link and its two negatives (no such Location, not exactly equal); prose stays prose; the report's lines on ids, links, hidden, modules and the default title; each element's module evidence; the report naming everything not placed; the table pinned whole; without --project today's ids (pinned as literals), with it every id keyed and stable across runs, two names two sets of ids, the world named, a second element of one name, a blank name refused, the flag on the command line and --plan with it writing nothing; the lint; two runs byte-identical; the round trip; --plan writing nothing; and on planted copies an element of no known module, a Magic module a Construct, a module not in the table, two modules, a missing panel, a second element of one name, an exact copy, unread text, a panel kind not yet seen, refusals and the command line. 26 mutants watched failing, one per rule.

onlyworlds 0.40.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 10:43
  • The World Anvil door takes the schema owner's three rulings (Skeld, OW Market h40 #11360). The template table (Skeld's ruling): every row of 0.39.0 holds, and four are added on his reading of the definitions page: Ethnicity to Species, Myth / Legend to Narrative, Vehicle to Object, Profession to Title (believed: none yet seen in a real export). Anything else stays unknown. The unknown template (Skeld's ruling): still a Narrative, but with supertype Article, what the thing is rather than where it came from (the producer line says that); the subtype is the template's name as World Anvil spells it, the template word still in x_worldanvil_template, and the report names each unknown template and its count. Behaviour change: an article whose template 0.39.0 left unknown came in with supertype worldanvil; it now comes in with supertype Article, and a Vehicle, Ethnicity, Myth / Legend or Profession article now comes in typed. The extra fields and the dates (Skeld's ruling): a template field with no OnlyWorlds name stays x_worldanvil_<name>, as before; the article's three dates, which 0.39.0 left out, are now kept on the element under the export's own words, x_worldanvil_created, x_worldanvil_updated and x_worldanvil_published (DATE_KEYS), as ISO 8601 parsed from what the page prints (23 Oct, 2026 is 2026-10-23); a date not parsed exactly (another shape, or no such day) is kept as printed and named in the report, never guessed. The author stays out of the elements and is named in the report only (one platform username for the whole export). The real files: the three articles of each now carry their three dates, 2026-10-23, and the report names the author once.
  • The account's handle is out of the package (Boss's find, OW Market h40 #11375): 0.39.0's tests/test_worldanvil.py spelled the export account's handle as a literal in its forbidden list, so the name shipped with the tests. The test now checks it by hash: no word-ish token of a fixture, lowercased, may hash to the handle's sha256, and only the digest is in the file; the check is proven on a planted stand-in name, in either case. The handle appears nowhere in the tree.
  • Tests: the table as ruled; the four added templates each typed; an unknown template an Article Narrative; the dates on the real files; a date not parsed exactly, kept and named; the parse exact (no 31 February); the author on no element. 9 mutants watched failing, one per rule.