docs(content-drive): Status filter design (plan, research, data model, contract) (#37066) - #37171
Conversation
…37066) Phase 1 design artifacts for the Status filter, stacked on the spec PR. Carries only the two artifacts .specify/CUSTOMIZATIONS.md considers durable: data-model.md (the ContentStatus enum, the `status` transport shape, the filter-bag entry) and contracts/ (the `status` field on POST /api/v1/drive/search, including the AND semantics and the 400 on an unknown value). plan.md, research.md and quickstart.md stay local by design — the repo gitignores them as process-only artifacts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @zJaaal's task in 1m 44s —— View job SDK Compatibility Review — PR #37171
Result: No SDK-breaking change detected. This PR is documentation-only — it's Spec-Kit PR 2 of 3 (per #37170/#37171), carrying design artifacts, not runtime code:
None of these touch a live wire-format surface: no GraphQL schema/resolver changes reachable via No comment or label added, per instructions (only acts when a breaking change is found). |
Restores stock Spec-Kit behavior for the three artifacts a reviewer needs to judge a design. Only tasks.md and checklists/ stay gitignored. The original policy in #36416 kept all five local on the "process artifact" test. That predates this repo adopting GitHub's native stacked pull requests (public preview 2026-07-30), which changes the calculation: the spec-driven flow now lands as a stack whose middle layer exists purely to review the design. Gitignoring plan.md makes that layer a PR with nothing to review. tasks.md and checklists/ stay ignored — both are regenerated by their own command, and a merged task list that no longer matches what was built is worse than no task list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…37066) Now trackable after the preceding gitignore change. These are the artifacts /speckit-plan already generated for this feature; they were sitting on disk, invisible to review. - plan.md design, Legacy Impact, Constitution Check, ADR Alignment gate - research.md R1-R10, each verified against the code rather than the issue text - quickstart.md build/test commands and the end-to-end validation walkthrough Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4c6f547
into
issue-37066-content-drive-status-filter
|
Folded into #37170 rather than reviewed separately — GitHub marked this merged automatically once its commits fast-forwarded into the base branch. The spec and its design artifacts are one reviewable unit, so splitting them across two PRs was overhead without a payoff. Everything that was here ( The stack is now #37170 (spec + design) → implementation, which is the two-PR shape Analysis and comment by Claude (Claude Code), posted from @zJaaal's account. |
Spec-Kit PR 2 of a stack (stack #37172). Based on #37170 (the spec), so the diff here is only the design layer. Review #37170 first.
The stack
issue-37066-content-drive-status-filtermainspec.md— #37170issue-37066-content-drive-status-filter-plana4e63f1un-ignoresspecs/*/plan.md,research.mdandquickstart.md. @nollymar — this touches the commit policy you set in #36416, so please weigh in.Your original rule kept all five artifacts local on the "durable reference vs. process artifact" test, which was sound for the shape it was written for: one spec PR, one implementation PR. It predates this repo adopting GitHub's native stacked PRs (public preview 2026-07-30). Stacks add a middle layer whose entire purpose is reviewing the design — and gitignoring
plan.mdmakes that layer a PR with nothing in it to review. That's how this surfaced.tasks.mdandchecklists/stay ignored: both are regenerated by their own command, and a merged task list that no longer matches what shipped is worse than no task list..specify/CUSTOMIZATIONS.mdis updated with the revised policy table and the reasoning. Happy to split this into its own PR againstmainif you'd rather the team decide it separately from a feature stack.Proposed Changes
plan.md— the design: approach, Legacy Impact, Test Strategy, Constitution Check, ADR Alignment gate.research.md— R1–R10, each verified against the code ate46da2b187rather than taken from the issue text.quickstart.md— build/test commands and the end-to-end validation walkthrough.data-model.md— theContentStatusenum and its column/index mapping, thestatustransport shape and validation rules, theBrowserQueryfield, the frontend filter-bag entry.contracts/drive-search-status.md— thestatusfield onPOST /api/v1/drive/search: accepted values, AND semantics with a per-combination result table, theshowFoldersside effect, the 400 on an unknown value..gitignore+.specify/CUSTOMIZATIONS.md— the convention change above.Design decisions worth a reviewer's eye
1. All three predicates resolve in the database. ADR-0018 routes version-info flags (archived/deleted) to the DB and says structural criteria must never be re-routed to the index for speed. All three statuses are version-info flags:
ARCHIVEDcvi.deleted = true+deleted:trueUNPUBLISHEDcvi.live_inode is null+live:falseLOCKEDcvi.locked_by is not null+locked:trueThe index terms exist only because
BROWSE_API_HEURISTIC_TYPE=PURE_ESis a supported (non-default) configuration where the filter would otherwise silently no-op, returning a wider set than asked for. Under the default hybrid heuristic the SQL clauses apply with and without a keyword.2.
statusis typedList<String>, notList<ContentStatus>. The AC asks for a 400 on an invalid value "consistent with howuserSearchablerejects unknown keys", and that precedent is an explicitBadRequestExceptionthrown inContentDriveHelper. A typed field would route through Jackson's deserialization error instead, whose status mapping is less direct. The typed field is prettier; the deterministic error is worth more.3. No schema or mapping change.
deleted,live_inodeandlocked_byalready exist oncontentlet_version_info(postgres.sql:550-552), andlockedis already indexed (ESMappingAPIImpl.java:527). Nothing here is rollback-unsafe.The risk this design carries into PR 3
Two existing code paths already have an opinion about
cvi.deleted, and both must learn aboutARCHIVEDor the filter breaks:BrowserAPIImpl:2006) would otherwise emitcvi.deleted = falsealongside= true, soARCHIVEDwould always return nothing.:1980) —appendWorkflowQueryownscvi.deletedper branch when such a step is selected, soARCHIVEDneeds the same treatmentshowArchivedalready gets.ContentDriveWorkflowArchiveStepTestis the regression guard.With no
statussent, every generated query stays byte-identical to today. See research.md R5.Checklist
PURE_ESparity and the workflow archive-step regression; Jest/Spectator for the chip, the store payload and the URL round-tripcontent-drive.status-filter.*keys, in PR 3Additional Info
/speckit-adr-contextran as the mandatorybefore_planhook. ADR-0018 (proposed) governs and this design complies; ADR-0009 (accepted) constrains only the index terms, all core fields mapped identically under ES and OpenSearch; ADR-0020 surfaced but does not apply. No new ADR proposed — this adds a filter within an already-decided routing contract.🤖 Generated with Claude Code
This PR fixes: #37066
This PR fixes: #37066