feat(cli,create-objectstack): os generate picklist, the src/picklists starter barrel, and a Picklists count in the metadata summary - #21167
Conversation
… starter barrel, and a Picklists count in the metadata summary os generate picklist NAME writes NAME.picklist.ts through definePicklist into src/picklists, collected under the picklists stack key. os init derives its wiring from the roster; the blank starter of create-objectstack gains the same empty barrel and config lines. collectMetadataStats counts picklists, printed in the Data: row of os validate, os build and os info. Claude-Session: https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB Co-authored-by: Claude <noreply@anthropic.com>
…, with changesets Claude-Session: https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB Co-authored-by: Claude <noreply@anthropic.com>
…project sees, as measured Claude-Session: https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 3 package(s): 4 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 3 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 32 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 4594faf5e1e5e7a3659b2e410762ce57a1e7c9b6 && git checkout 4594faf5e1e5e7a3659b2e410762ce57a1e7c9b6
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 1371dc980cdf0d3128bee4a5441f2c6bec18f008 cd1910a947360721404bab9d960b4e955914d453 && git checkout -B drift-repro 1371dc980cdf0d3128bee4a5441f2c6bec18f008 && git merge --no-ff cd1910a947360721404bab9d960b4e955914d453
node scripts/docs-audit/affected-docs.mjs --json 1371dc980cdf0d3128bee4a5441f2c6bec18f008
|
Contract reviewServed-tier: Inputs read: card #21018 (body, claim Checks on the head, collapsed latest-per-name, converged at 11:44Z: 37 names, 33 Mergeability: ① Derived judgments(a) Item 1, the generator. The emitted file is (b) Item 2, the starter. Structural half holds. The blank config gains the import and Behavioural half: against the REPO build a fresh project validates and builds — (c) Item 3, docs. (d) Item 5, the stats row. (e) Pins and ablations. ② Semver level
③ Boundary flags
Remedy for the FAIL (no code change needed; a body edit leaves this head-sha standing): (1) add an Acceptance note naming the Implemented-by: VERDICT: FAIL |
…icklists barrel Claude-Session: https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB Co-authored-by: Claude <noreply@anthropic.com>
|
Generated by Claude Code |
Contract reviewServed-tier: Re-review of PR #21167 after the FAIL record What moved. One commit, Checks on Mergeability. ① Derived judgments(a), (c), (d) and (e) carry from (b) carries with its FAIL cause removed. The structural half is as before. The behavioural half is now stated correctly in the PR: the Acceptance notes name the ② Semver levelCarries from ③ Boundary flags
Landability. The contract is met on this head. The one red is an advisory, non-required check, disclosed in the body and held by the seat, that cannot turn green before the release in #20639 publishes Implemented-by: VERDICT: PASS |
Part of #21018
Clause-②: yes (widening)
This PR is the code half of #21018. It covers scope items 1, 2, 3 and 5 of the card body. Item 4, the "seven generator barrels" line in
skills/objectstack-platform/SKILL.md, is on a Tier H governed path. It follows in its own PR under a second claim, so #21018 remains open for it.Dispatched by the
domain:cliseat's PM under claim 5929373213. Dev sessionsession_01VvcEokUG1tvVxkceYfR5XB.Premise, checked on
origin/mainThe card waited on the runtime reader. That reader is on
mainas 88b484e (#21047), and these are the parts this PR relies on:picklistsandpicklistExtensionsare inMETADATA_ARRAY_KEYS(packages/objectql/src/engine.ts).picklistinto servedoptions(picklist-resolution.ts,resolvePicklistFieldsOnto).packages/objectql/src/plugin.ts).The repro below measures all of this end to end on a scaffolded project.
What changed
Item 1:
os generate picklist NAME(packages/cli/src/commands/generate.ts)osCLI compile / validate / lint path accepts*.picklist.ts,picklistsandpicklistExtensions, andos validaterefuses apicklistthat names no picklist (Scope 6 of #19518) #20825's branch (6ef78d3f29, reverted ine16359a9fa), re-read against the landed reader.src/picklists/NAME.picklist.tsthroughdefinePicklist. The file name comes frommetadataFileName, with no override.picklists(singularToPlural).namesObject: false, andrequiresis empty.optionsof its own.Item 2: scaffold wiring
os initderives its wiring from the roster (SCAFFOLD_WIRED_BARRELS), so theappandplugintemplates wiresrc/picklistswith no edit toinit.ts.create-objectstackgainssrc/picklists/index.ts, byte-identical to the empty barrelos initwrites. Itsobjectstack.config.tsgainsimport * as picklists from './src/picklists';andpicklists: exportsOf(picklists),.create-objectstack-wiring-parity.test.tsholds the two scaffolders equal.Item 3: docs
content/docs/deployment/cli.mdxgets the example line, the table row (picklist,src/picklists/,NAME.picklist.ts,picklists) and the "What it does" clause.packages/cli/README.mdgets the type list and a short paragraph.Item 5: the metadata summary (
packages/cli/src/utils/format.ts)MetadataStatsgainspicklists, andcollectMetadataStatscounts it through the existingauthoringRuleUnionStackfold, so both ADR-0130 D4 shapes are covered.printMetadataStatsrenders it in theData:row, the kind's own domain (domain: 'data'in the registry).picklistExtensionsentry is not counted as a list.MetadataStatsmember gainpicklists: 0:format.metadata-stats-package-fold.test.tsandprint-metadata-stats-zero-row.test.ts.Changesets
@objectstack/cli:minor. A new generator kind, andstats.picklistsis added to the--jsonoutput ofos validate,os buildandos info.create-objectstack:minor. The starter gains a wired barrel.Clause-②: yes (widening). Nothing is narrowed and nothing is renamed, so there is no ADR-0087 marker.Repro, before and after
Before, on
origin/main58a77db:After, on this branch:
On a project scaffolded before this change (its config wires no
src/picklists),os g picklist regionexits 0. It reportsNot wiredand prints the import line and thedefineStackkey to add.Tests
The pins are:
packages/cli/src/commands/generate-picklist.pin.test.ts:src/picklists, stack keypicklists,namesObject: false, norequires) and theNAME.picklist.tsfile name;os validateuses (bundle-require,BUNDLE_REQUIRE_EXTERNALS), parsed byPicklistSchema, under the item nameos greports;ObjectQL.registerAppunderpicklists, serving its options on aField.select({ picklist })field, and passingPicklistServedFieldSchema;It constructs
ObjectQL, so it lands in theintegrationtier.packages/cli/src/utils/format.metadata-stats-picklists.test.ts:Data: 1 Objects 2 Fields 1 Picklists;Data: 1 Objects 2 Fields.The runs, all on HEAD 5a53515 except where noted:
pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2packages/cli is not builtand passed afterpnpm --filter @objectstack/cli build.--project integration, the 8 integration files among the related testsgenerate-picklist.pin,create-objectstack-stack-reach,generate-stack-reach,info-detail-package-foldand 4 moreOS_TEST_TIERS=nightly, the related*.e2efilesgenerate-scaffolds-reach-stack.e2e: "os g picklistexits 0 and reports no wiring to add"pnpm --filter create-objectstack exec vitest runpnpm --filter @objectstack/cli typecheck(tsc --noEmit && check:test-typecheck)pnpm --filter create-objectstack typecheckAblation
The ablations ran on the committed fix (e63b1db). Each mutation went through
scripts/ablation-replace.mjswith the anchor counted on disk. Each restore was proven: the blob equals HEAD andgit diff HEADis empty.picklistrow deleted fromGENERATORS(anchor x1 → x0, 53 lines)generate-picklist.pin3 of 5.wiring-parity: imports and stack keys (2)generate-scaffold-validates19/19; the pin's file-name case and its no-list controlpicklists: exportsOf(picklists),deleted from the blank configwiring-parity: "hands every wired barrel to its stack key" (1 of 22)picklists: count(stack.picklists),deletedmetadata-stats-picklists5 andpackage-fold4 (itsZEROEScomparisons)print-metadata-stats-zero-row['Picklists', stats.picklists],deletedmetadata-stats-picklists"Data: row", andprint-metadata-stats-zero-row"every metric collectMetadataStats counts is rendered"Gates
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, run with no paths, derived 96 families. All 96 were run, each with its exit code recorded before any pipe.PREREQUISITE NOT MET(exit 3) because their build inputs were missing:check:skill-examples,check:dual-build-cjs-loads,check:i18n,check:i18n-coverageandcheck:i18n-walk-parity. All five passed once those inputs were built.--ranreconciliation:✓ dispatch-gates --ran: 96 derived famil(ies) accounted for — 96 run, 0 NOT-MEASURED.pnpm lint, as a proven narrowing (on HEAD 5a53515):isPathIgnored/calculateConfigForFile): all 8 touched.tsfiles are linted. The 4 touched.md/.mdxfiles are outside its population.--format json: 8 files, 0 errors, 0 warnings, with--no-inline-config.parserOptions.project, noprojectService, aseslint.config.mjsstates). This diff touches no lint config or baseline. So it cannot move the verdict on any file it does not touch.Not in this PR
Item 4 (Tier H). On
db48028f1a, lines 194–195 ofskills/objectstack-platform/SKILL.mdread:The proposed text, net zero lines:
Not carried here, as the card says: the
picklist-reference-unverifiedtrigger, and a danglingpicklistExtensions[].extend(folded into picklist kind: theosCLI compile / validate / lint path accepts*.picklist.ts,picklistsandpicklistExtensions, andos validaterefuses apicklistthat names no picklist (Scope 6 of #19518) #20825).Acceptance notes
The two starter README listings now name
src/picklists(commit90d55b1e13, added on contract review5930680827):Layoutbullet inpackages/create-objectstack/src/templates/blank/README.md, which ships into every new project;packages/create-objectstack/README.md.They ride this PR, not the Tier H item-4 PR, so two non-governed lines do not wait on a human approval.
Scaffold with repo distis red on this PR, and the PR is held until the next release publishes. This note was added by the seat.create-objectstack, then installs the project's framework from the npm registry. The template's^17.0.0range resolves to the published@objectstack/spec17.5.0, which predates thepicklistsstack key (addbbf0,.changeset/19518-picklist-kind.md, still unreleased). So the generated project'sdefineStackrefuses the key as unrecognized at the validate step.npm create objectstackrows and the end-to-end chain were measured on the repo build, not against the registry.pull_requestunder its path filter (packages/create-objectstack/**,docker/**and its own workflow file), and it is not red onmain.create-objectstackPR until that release.@objectstack/specchangelog already listsaddbbf0. Once it merges and publishes, a re-run of this job reads the new spec and the template is coherent with it.pm:blockedon chore: version packages #20639.On a project scaffolded by an earlier release, the not-wired hint prints
picklists: Object.values(picklists),, not the starter'sexportsOf(...)spelling. Both type-check once the barrel exports a list, which is the only state the hint is printed in.Generated by Claude Code