Repository navigation
Healthsheet bundles: take the origin line from the profile, so a non-study record carries no false FAIRhub origin (#4009) - #4387
Open
realmarcin wants to merge 3 commits into
Open
realmarcin wants to merge 3 commits into
realmarcin wants to merge 3 commits into
Conversation
`healthsheet.render` wrote "Origin: FAIRhub API record, metadata.healthsheet" into every healthsheet-only bundle, a record built with --record/--project/--name included, so a non-study dataset's model input named the study's platform as its origin. - `Profile.healthsheet_origin`: what the `Origin:` line says the profile's own record is. `bridge2ai` carries today's text; `neutral` carries none. - `render(..., origin=None)` writes the line after `Source:` only when given one; `build_bundle` gives the profile's origin only for the profile's own record, whatever project the caller names, since the origin describes the record. - Any other record gets no `Origin:` line. The module knows of it only what the caller passed, which `Source:` and `Project:` already state, and reading a platform off the record's content would be a guess. - The tracked AI_READI_healthsheet_only.txt is byte-identical (sha256 ef2f5a5c..., md5 a66b1681..., the chunk manifest's pins), rebuilt through the library, the CLI, an absolute record path and tests/. - The IRB wording at healthsheet.py:134 gets a tracked reason in the specificity audit's exceptions.yaml; rewording it would move bytes the chunk manifest and the healthsheet arm's records pin. Tests: the study bundle's whole bytes; the origin follows the record, not the project; a foreign record under bridge2ai (--project, --name, claiming AI_READI) and every record under neutral get no `Origin:` line; render writes a given origin after `Source:`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 5, 2026
`build_bundle`'s docstring said the default bundle name was "derived from the record's stem", and the `--name` help of `d4d healthsheet bundle` said "else <record stem>_healthsheet_only.txt". Neither has been true since a553d42 (#1493). That commit named a record that is not the profile's after the project it is filed under, `{project}_healthsheet_only.txt`, which is what lets the name be checked against the profiles' reserved bundle names. Both texts now say so. They also add what the old wording left out: the profile's bundle name is the default only for the profile's own record filed under the profile's project. The `--project` help and the docstring's `project` sentence had the same gap, and get the same qualifier: only the profile's own record defaults to the profile's project; any other record must name one. `TestDefaultName` runs the command on a record that is not the profile's, under `bridge2ai` and `neutral`. It requires the `--name` help, the command's help and `build_bundle`'s docstring each to name exactly the file that was written. This changes documentation only. No bundle byte changes, and the tracked healthsheet bundle stays as it is. Correction to the message of 1d78540 (#4421): "The IRB wording at healthsheet.py:134" uses origin/main's line numbers. At 1d78540, and at this commit, the IRB literal is healthsheet.py:138; line 134 is the `Source:` line. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`build_bundle` refuses a default name that is any profile's bundle name, under every active profile (#1565). The refusal said the name "is the active profile's bundle name". Under `neutral`, which has no bundle name, that told a record filed under the study's project that the name was the neutral profile's. The refusal now names the profile the name belongs to: "AI_READI_healthsheet_only.txt is the bridge2ai profile's bundle name; pass --name for ...". This matches the docstring and `--name` help corrected in the previous commit, which say the default is refused where it is a profile's bundle name. `TestDefaultName::test_a_reserved_default_is_refused_naming_the_profile_it_belongs_to` checks the message, and that nothing is written, under `bridge2ai` and `neutral`. The existing tests (#1543, #1565) check only "pass --name" and still pass. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 9, 2026
Closed
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4009
Fixes #4420
healthsheet.renderwrote the literalOrigin: FAIRhub API record, metadata.healthsheetinto every healthsheet-only bundle. That included a bundle built from a record that is not the profile's (d4d healthsheet bundle --record X --project P [--name N]), under either profile. That bundle is the model input of thehealthsheetarm ({p}_healthsheet_only.txt), so a non-study dataset's model was told its healthsheet came from the study's platform. The generation-specificity audit (#4007) reported this as the onlydeterministicviolation.Header of a foreign record's bundle (
--record clinic_record.json --project CLINIC), same output underbridge2aiandneutral:Merge held on the owner's audit28 decision (#4761)
audit28's controllers compare
src/data_sheets_schema/profiles.py(andschema_digest.py) between a continuation's repository and its parent's, and stop on any difference:validate_scientific_identityinnotes/matched_cborg_2026-09-13/audit_controls/registration.py:479-491raises "shared scientific instrument changed";finalization_controls/registration.py:125-129raises "finalization changes the inherited scientific instrument".This PR changes
profiles.py. When it was opened, main'sprofiles.pystill hashed to the registered pin (36de6c72…), so a continuation prepared from a main that included this PR would have stopped at that check. That no longer distinguishes this PR (#5030). Sincebfab086a6(#4459, 2026-10-05), main'sschema_digest.pyhashes to2626779774de…, which matches neither registration's pin. A continuation prepared from current main therefore already stops, with or without this PR, and audit28 can only run from a fixed compatible checkout, which a merge to main does not touch. The merge waits only on the owner's decision in #4761, which the plan's D10 applies to #2910, #2922 and this PR together. Review continues meanwhile.What changed
Profile.healthsheet_origin(profiles.py) holds what the bundle'sOrigin:line says about the profile's own record.bridge2aicarries today's text (FAIRhub API record, metadata.healthsheet) andneutralcarries none. The field holds the line's text, and the renderer keeps theOrigin:label, as it does forProject:andSource:.render(..., origin=None)writesOrigin: <origin>directly afterSource:, and only when it is given one.build_bundlepasses the profile's origin only for the profile's own record (own, the resolved-path identity the bundle name already uses), whatever project the caller names. The origin describes the record, not the dataset label it is filed under.Origin:line. The scope asked to either derive the origin or omit the line, and to say which; this omits it. For such a record the module knows only what the caller passed, and theSource:andProject:lines already state that, so a derived line would repeat them. The record also has no generic field naming the service that served it, so reading a platform off its content (a DOI prefix, a title) would be the platform-specific guess the audit forbids.build_bundle's docstring and the--nameand--projecthelp ofd4d healthsheet bundle(cli/healthsheet.py) now say what has been true since a553d42 (#1436 r2 (Claude): a foreign healthsheet record under the study profile is written to the study's tracked bundle name #1493): a record that is not the profile's is named after the project it is filed under ({project}_healthsheet_only.txt), and the profile's bundle name is the default only for the profile's own record filed under the profile's project. A reserved default is refused naming the profile it belongs to ("AI_READI_healthsheet_only.txt is the bridge2ai profile's bundle name; pass --name for ..."); the old message called it "the active profile's bundle name", which was wrong underneutral. Documentation and message only: no bundle byte changes.exceptions.yamlin the user-approved audit skill (nothing else under.claude/changes) gets a tracked reason for the IRB wording athealthsheet.py:138(line 134 on origin/main; PR body and commit message put the IRB wording at healthsheet.py:134; at this head it is line 138 (134 is the Source: line) #4421). The entry is appended, so no existing exception number moves. The wording is not changed because the sentence is in the tracked study bundle.The tracked bundle does not change by a single byte
data/preprocessed/concatenated/AI_READI_healthsheet_only.txt, 56,453 bytes:ef2f5a5c98c56f565728c09305ecee10f47586472533b3648c2421c637ed210aa66b16818139bca4018efe11cae5cc7aThe four routes are: the library default, the library with an absolute record path,
d4d healthsheet bundle, and the same CLI run fromtests/. The same md5 is pinned by 12claudecode_agent_healthsheet_coreprovenance records. No file underdata/changes.Specificity audit, before and after (
scan.pyon this branch)bc1f41d)1d78540)deterministicviolationshealthsheet.py:131,FAIRhub)Every count that moved is accounted for:
healthsheet.py:131FAIRhub(model-facing, gated bydeterministic) is gone. The one new gc_project hit isprofiles.py:133FAIRhub: a string literal in run-shaping code, gated by no approach, under exception #0 (the profile is the designated home of the study's facts). The other 21profiles.pyhits that appear as removed and added are the same hits, moved down by the lines inserted above them: five for the new field, and a sixth below the newBRIDGE2AIline. I checked this: the shifted "before" multiset equals the "after" multiset minus line 133.healthsheet.py:138IRB(line 134 on origin/main) leaves the triage queue under the new exception Model timestamps for different data resource and dataset milestones -- support construction of a data resource dependency graph #10 (1 hit). Exception #0 goes from 34 hits to 35, Explore unification with Data Diversity Standards #1–Include field for whether agreements are necessary to use data #9 are unchanged, and no exception is unused.Tests
tests/test_rocrate/test_healthsheet.pyadds seven tests: five inTestOrigin, and two inTestDefaultNamefor #4420.TestOrigin:test_the_study_bundle_keeps_its_bytes(bridge2ai): the profile's record renders the tracked bundle's whole bytes (sha256 compare), and its oneOrigin:line is the profile's text.test_the_origin_follows_the_record_not_the_project: the study record filed under--project CLINICkeeps the profile's origin.test_another_record_states_no_origin(bridge2ai): a foreign record with--project, with--project --name, and with--project AI_READI --name other.txtgets noOrigin:line and no "fairhub" anywhere.test_neutral_states_no_origin_for_any_record:NEUTRAL.healthsheet_origin is None, and underneutralneither a foreign record nor the study's capture gets anOrigin:line.test_render_writes_the_origin_it_is_given_after_the_source:renderwrites no line without an origin, and writes a given one directly afterSource:.TestDefaultName(#4420), underbridge2aiandneutral, on a record that is not the profile's:test_the_stated_default_name_is_the_name_written: the--namehelp, the command's help andbuild_bundle's docstring each name exactly the file that was written.test_a_reserved_default_is_refused_naming_the_profile_it_belongs_to: the refusal names the owning profile, and nothing is written.Re-checked 2026-10-13 at
c5115f439merged into origin/main5c952d210(adversarial review, #5029/#5030): the merge is clean, the tracked bundle rebuilds byte-identical through all four routes, no pin, schema digest, chunk manifest or record moves, and 1,426 targeted tests pass.I ran every test file that imports
healthsheetorprofiles:tests/(-m "not corpus",-n 2): 239 + 888 passed, 1 skipped. The skip istest_resources.py:371, which needs a symlinked.venvthat a worktree does not have.notes/matched_cborg_2026-09-13/audit_controlsfiles that importprofiles, run in CI's environment: 205 passed, andnotes/was left untouched.Mutation checks
Each mutant was run on a
git archivecopy, never the worktree. All eight were killed:renderown_name)neutralgiven the study's originrenderignoresoriginThe existing byte test (#1542) catches only M4, M5, M7 and M8. The false-origin regressions (M1, M2, M3, M6) are caught only by the new tests.
Not done here
--originoption for a foreign record: the scope allowed either deriving or omitting, and this PR omits. If a non-study dataset should state its origin, the manifest is the place for it (Healthsheet bundles: let a non-study dataset state its record's origin (manifest, not a literal) #4389).notes/. The before and after numbers are above.d4d download audit-bundlesstill lists the healthsheet bundle as "no rebuild route registered here" (audit-bundles: register a rebuild route for the healthsheet-only bundle #4388).🤖 Generated with Claude Code