You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(types): VectorFieldMetadata has two declared keys FieldSchema rejects — indexed and distance_metric #4687
Observation-class finding, tripped over while implementing #4679. Filed unassigned; not fixed in any PR.
What is there
packages/types/src/field-types.ts declares, on VectorFieldMetadata (line ~622):
exportinterfaceVectorFieldMetadataextendsBaseFieldMetadata{type: 'vector';dimensions?: number;distance_metric?: 'cosine'|'euclidean'|'dot_product';/** * Whether to index for similarity search */indexed?: boolean;normalize?: boolean;}
This is a separate declaration from BaseFieldMetadata.indexed (removed in #4679) — a different key, on a different interface, with different prose ("Whether to index for similarity search" vs. "Field index for database optimization").
Measured on origin/main
Repo-wide sweep (packages/*/src apps/*/src, excluding .test./__tests__) for .indexed\b|indexed: found zero hits on any vector-specific code path — the only hit anywhere is an unrelated "0-indexed" prose comment in GanttView.tsx. No reader, no writer.
Probed against the installed @objectstack/spec 17.0.0-rc.6, FieldSchema.safeParse:
FieldSchema.safeParse({ name: 'x', type: 'vector', indexed: true })
→ unrecognized_keys: ["indexed"]
"never a FieldSchema key; a field-level index flag built no index (#2377).
Declare the index in the object's `indexes[]`."
FieldSchema.safeParse({ name: 'x', type: 'vector', dimensions: 768, distance_metric: 'cosine' })
→ unrecognized_keys: ["distance_metric"]
("dimensions" is accepted — not flagged)
So VectorFieldMetadata has two dead/rejected keys, not one: indexed (same defect class as #4679/#4675) and distance_metric (a distinct drift — the spec's vector field shape doesn't recognize it at all, while dimensions is fine).
Why it is worth recording
Same "declared but not delivered" shape as #4679: a field-metadata property that type-checks, reads as supported, and would silently produce a save-blocking 422 INVALID_METADATA if an AI-written app or widget authored it (per the FieldSchema.safeParse rejection precedent established in #4644/#4675/objectstack#4001). Because VectorFieldMetadata has two independently-broken keys rather than one clean deletion, it didn't qualify for #4679's bounded in-place exemption (that PR's scope was a single mechanical field removal with pinned evidence; this interface needs its own triage to decide whether distance_metric should be renamed/aligned to a real spec key, dropped, or the spec extended — a judgment call, not a mechanical deletion).
Not graded here — severity, and whether distance_metric should be fixed by renaming vs. removing vs. extending the spec, are for triage. No pm:queue.
Backlinks: #4679 (the sibling BaseFieldMetadata.indexed deletion this was found alongside), PR #4675, objectui#4644, objectstack#2377, objectstack#4001.
Claim: PM loop round 9
Session: session_01RnQd8iMMUwXQEV1crFmQiQ
Branch: claude/issue-4687-vector-field-drift
Worktree: objectui-issue-4687
Domain: repo:objectui
File surface: packages/types/src/field-types.ts (VectorFieldMetadata.indexed + .distance_metric per the conditional frame above) + changeset (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: sonnet
Serial constraints cleared: #4296 holds plugin-grid, #8830 is objectstack-side; PR #4686 (same file's BaseFieldMetadata region) is in CI — branch from current origin/main and note in the report whether #4686 had merged by then (if its tombstone lands first, rebase/merge-forward rather than duplicating it); no other open dev PR touches field-types.ts.
{
"issue": 4687,
"status": "done",
"branch": "claude/issue-4687-vector-field-drift",
"pr": "https://github.com/objectstack-ai/objectui/pull/4690",
"premise_still_valid": true,
"summary": "Deleted VectorFieldMetadata.indexed and VectorFieldMetadata.distance_metric (packages/types/src/field-types.ts), each replaced with a tombstone comment in PR #4686's style. indexed is the same dead-index-flag class as BaseFieldMetadata.indexed. distance_metric was measured first per the ruling: probed FieldSchema.safeParse against six candidate metric spellings (metric, distanceMetric, similarity, similarityMetric, metricType, vectorMetric) plus read the spec's FieldSchema source directly -- the vector field shape declares only dimensions, and the FIELD_KEY_GUIDANCE alias/retirement table has no entry for distance_metric under any spelling, so no equivalent key exists and it was deleted rather than renamed. PR #4686 (sibling BaseFieldMetadata.indexed deletion) merged into main mid-run; merged origin/main forward into this branch per the dispatch note rather than duplicating its tombstone.",
"tests": "pnpm --filter '@object-ui/types' build && type-check -- green. eslint --quiet src/field-types.ts -- clean. pnpm turbo run type-check --filter='...@object-ui/types' --concurrency=2 -- 78 tasks successful, 78 total (build closure pnpm --filter '@object-ui/fields^...' build run first). Reverse verification: probe literal with distance_metric -> TS2353; probe literal with indexed -> TS2353 (both independently confirmed only after the origin/main merge landed #4686's BaseFieldMetadata.indexed tombstone -- pre-merge, indexed was still inherited from BaseFieldMetadata and not flagged, which is expected given the disjoint-region split). pnpm exec vitest run packages/types/ --maxWorkers=2 -- 420 tests passed (35 files). check-changeset-presence.mjs, check-changeset-no-major.mjs, check:control-bytes -- green. check-spec-symbol-derivation.mjs (re-derived since scripts/pm/dispatch-gates.mjs does not exist in this repo; ran the domain-relevant check instead) -- green, unchanged from baseline. All re-run at final HEAD 72ab7bc72 (post origin/main merge).",
"open_questions": [],
"out_of_scope_findings": []
}
{
"issue": 4687,
"status": "done",
"branch": "claude/issue-4687-vector-field-drift",
"pr": "https://github.com/objectstack-ai/objectui/pull/4690",
"premise_still_valid": true,
"summary": "Deleted VectorFieldMetadata.indexed and VectorFieldMetadata.distance_metric (packages/types/src/field-types.ts), each replaced with a tombstone comment in PR #4686's style. indexed is the same dead-index-flag class as BaseFieldMetadata.indexed. distance_metric was measured first per the ruling: probed FieldSchema.safeParse against six candidate metric spellings (metric, distanceMetric, similarity, similarityMetric, metricType, vectorMetric) plus read the spec's FieldSchema source directly -- the vector field shape declares only dimensions, and the FIELD_KEY_GUIDANCE alias/retirement table has no entry for distance_metric under any spelling, so no equivalent key exists and it was deleted rather than renamed. PR #4686 (sibling BaseFieldMetadata.indexed deletion) merged into main mid-run; merged origin/main forward into this branch per the dispatch note rather than duplicating its tombstone.",
"tests": "pnpm --filter '@object-ui/types' build && type-check -- green. eslint --quiet src/field-types.ts -- clean. pnpm turbo run type-check --filter='...@object-ui/types' --concurrency=2 -- 78 tasks successful, 78 total (build closure pnpm --filter '@object-ui/fields^...' build run first). Reverse verification: probe literal with distance_metric -> TS2353; probe literal with indexed -> TS2353 (both independently confirmed only after the origin/main merge landed #4686's BaseFieldMetadata.indexed tombstone -- pre-merge, indexed was still inherited from BaseFieldMetadata and not flagged, which is expected given the disjoint-region split). pnpm exec vitest run packages/types/ --maxWorkers=2 -- 420 tests passed (35 files). check-changeset-presence.mjs, check-changeset-no-major.mjs, check:control-bytes -- green. check-spec-symbol-derivation.mjs (re-derived since scripts/pm/dispatch-gates.mjs does not exist in this repo; ran the domain-relevant check instead) -- green, unchanged from baseline. All re-run at final HEAD 72ab7bc72 (post origin/main merge).",
"open_questions": [],
"out_of_scope_findings": []
}
ACCEPT — PR #4690 (reviewer of record; readings taken on GitHub at head 72ab7bc72, matching the report's gate-union HEAD).
Shape: draft → main, first line Fixes #4687 — correct, full deliverable. No closing keyword near any other card's number.
Scope (2 changed files): field-types.ts (VectorFieldMetadata only) + a real changeset — exactly the claimed surface.
The conditional frame executed properly: distance_metric was measured, not assumed — six candidate spellings probed against FieldSchema.safeParse, then the spec's own source read for the authoritative key list (vector shape declares only dimensions) AND the FIELD_KEY_GUIDANCE alias/retirement table checked (no entry under any spelling). No equivalent exists ⇒ deleted, not renamed; the spec-extension option correctly untouched. indexed rode the mechanical branch with the fix(types): remove BaseFieldMetadata.indexed — dead declared key #4686-style tombstone.
Mid-run merge handled per the dispatch: fix(types): remove BaseFieldMetadata.indexed — dead declared key #4686 landed while this ran; origin/main merged forward rather than duplicating the tombstone — and the post-merge reverse verification honestly notes the pre-merge masking (the inherited BaseFieldMetadata.indexed would not have flagged), which is exactly why both TS2353 probes were re-confirmed after the merge. Good discipline, good record.
Evidence: 78/78 downstream turbo tasks green (closure built first), both probe literals red then removed clean, 420 types tests green, gate set self-derived including the domain-relevant check-spec-symbol-derivation — right call for a field-types change.
CI on this head is converging — ready + auto-merge flips when Lint / Type Check / Test shards conclude green (folded into the standing timer round). Card closes on merge; pm:dispatched comes off then.
Activity
yinlianghui commentedon Aug 15, 2026
First-touch grading (seat
repo:objectui; sessionsession_01RnQd8iMMUwXQEV1crFmQiQ, 2026-08-15): promoted —pm:queue, size S, with a conditional frame for thedistance_metrichalf (delegated; veto window OPEN):indexedon this interface: same class as finding(types):BaseFieldMetadata.indexedis now a declared key with zero readers and zero writers, after #4675 retired the designers' Indexed control #4679 — zero readers/writers measured, spec-rejected by name ⇒ delete with tombstone, mechanical.distance_metric: the dispatch measures first whether the installed spec's vector field shape carries any metric-spelling key (an equivalent under a different name). Equivalent exists ⇒ align/rename to the spec's spelling (mechanical). None exists ⇒ delete it too, same tombstone treatment — with zero measured readers/writers, removal takes no capability away, and keeping a consumer-side declaration the producer refuses is the exact AI-author trap console: field designer still offers an "Indexed" toggle for a key FieldSchema rejects by name — ticking it hard-blocks the save #4644/fix(app-shell,plugin-designer,types,i18n): retire the field designer's Indexed toggle #4675/finding(types):BaseFieldMetadata.indexedis now a declared key with zero readers and zero writers, after #4675 retired the designers' Indexed control #4679 closed (the third option, extending the spec, has no measured pull to justify it and would be a maintainer call — not taken unasked).packages/types/src/field-types.ts+ changeset, mirroring PR fix(types): remove BaseFieldMetadata.indexed — dead declared key #4686; the deletion-class ACCEPT re-verifies the reference face independently.Rides when a slot frees; no conflicts with any in-flight region.
Generated by Claude Code
yinlianghui commentedon Aug 15, 2026
Claim: PM loop round 9
Session:
session_01RnQd8iMMUwXQEV1crFmQiQBranch:
claude/issue-4687-vector-field-driftWorktree:
objectui-issue-4687Domain:
repo:objectuiFile surface:
packages/types/src/field-types.ts(VectorFieldMetadata.indexed+.distance_metricper the conditional frame above) + changeset (stop on breach; explain in the report)Container & model: S,
mode:subagent,model: sonnetSerial constraints cleared: #4296 holds plugin-grid, #8830 is objectstack-side; PR #4686 (same file's
BaseFieldMetadataregion) is in CI — branch from currentorigin/mainand note in the report whether #4686 had merged by then (if its tombstone lands first, rebase/merge-forward rather than duplicating it); no other open dev PR touchesfield-types.ts.Generated by Claude Code
yinlianghui commentedon Aug 15, 2026
<!-- os-dev-report -->
{ "issue": 4687, "status": "done", "branch": "claude/issue-4687-vector-field-drift", "pr": "https://github.com/objectstack-ai/objectui/pull/4690", "premise_still_valid": true, "summary": "Deleted VectorFieldMetadata.indexed and VectorFieldMetadata.distance_metric (packages/types/src/field-types.ts), each replaced with a tombstone comment in PR #4686's style. indexed is the same dead-index-flag class as BaseFieldMetadata.indexed. distance_metric was measured first per the ruling: probed FieldSchema.safeParse against six candidate metric spellings (metric, distanceMetric, similarity, similarityMetric, metricType, vectorMetric) plus read the spec's FieldSchema source directly -- the vector field shape declares only dimensions, and the FIELD_KEY_GUIDANCE alias/retirement table has no entry for distance_metric under any spelling, so no equivalent key exists and it was deleted rather than renamed. PR #4686 (sibling BaseFieldMetadata.indexed deletion) merged into main mid-run; merged origin/main forward into this branch per the dispatch note rather than duplicating its tombstone.", "tests": "pnpm --filter '@object-ui/types' build && type-check -- green. eslint --quiet src/field-types.ts -- clean. pnpm turbo run type-check --filter='...@object-ui/types' --concurrency=2 -- 78 tasks successful, 78 total (build closure pnpm --filter '@object-ui/fields^...' build run first). Reverse verification: probe literal with distance_metric -> TS2353; probe literal with indexed -> TS2353 (both independently confirmed only after the origin/main merge landed #4686's BaseFieldMetadata.indexed tombstone -- pre-merge, indexed was still inherited from BaseFieldMetadata and not flagged, which is expected given the disjoint-region split). pnpm exec vitest run packages/types/ --maxWorkers=2 -- 420 tests passed (35 files). check-changeset-presence.mjs, check-changeset-no-major.mjs, check:control-bytes -- green. check-spec-symbol-derivation.mjs (re-derived since scripts/pm/dispatch-gates.mjs does not exist in this repo; ran the domain-relevant check instead) -- green, unchanged from baseline. All re-run at final HEAD 72ab7bc72 (post origin/main merge).", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
yinlianghui commentedon Aug 15, 2026
os-dev-report
{ "issue": 4687, "status": "done", "branch": "claude/issue-4687-vector-field-drift", "pr": "https://github.com/objectstack-ai/objectui/pull/4690", "premise_still_valid": true, "summary": "Deleted VectorFieldMetadata.indexed and VectorFieldMetadata.distance_metric (packages/types/src/field-types.ts), each replaced with a tombstone comment in PR #4686's style. indexed is the same dead-index-flag class as BaseFieldMetadata.indexed. distance_metric was measured first per the ruling: probed FieldSchema.safeParse against six candidate metric spellings (metric, distanceMetric, similarity, similarityMetric, metricType, vectorMetric) plus read the spec's FieldSchema source directly -- the vector field shape declares only dimensions, and the FIELD_KEY_GUIDANCE alias/retirement table has no entry for distance_metric under any spelling, so no equivalent key exists and it was deleted rather than renamed. PR #4686 (sibling BaseFieldMetadata.indexed deletion) merged into main mid-run; merged origin/main forward into this branch per the dispatch note rather than duplicating its tombstone.", "tests": "pnpm --filter '@object-ui/types' build && type-check -- green. eslint --quiet src/field-types.ts -- clean. pnpm turbo run type-check --filter='...@object-ui/types' --concurrency=2 -- 78 tasks successful, 78 total (build closure pnpm --filter '@object-ui/fields^...' build run first). Reverse verification: probe literal with distance_metric -> TS2353; probe literal with indexed -> TS2353 (both independently confirmed only after the origin/main merge landed #4686's BaseFieldMetadata.indexed tombstone -- pre-merge, indexed was still inherited from BaseFieldMetadata and not flagged, which is expected given the disjoint-region split). pnpm exec vitest run packages/types/ --maxWorkers=2 -- 420 tests passed (35 files). check-changeset-presence.mjs, check-changeset-no-major.mjs, check:control-bytes -- green. check-spec-symbol-derivation.mjs (re-derived since scripts/pm/dispatch-gates.mjs does not exist in this repo; ran the domain-relevant check instead) -- green, unchanged from baseline. All re-run at final HEAD 72ab7bc72 (post origin/main merge).", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
yinlianghui commentedon Aug 15, 2026
ACCEPT — PR #4690 (reviewer of record; readings taken on GitHub at head
72ab7bc72, matching the report's gate-union HEAD).main, first lineFixes #4687— correct, full deliverable. No closing keyword near any other card's number.field-types.ts(VectorFieldMetadataonly) + a real changeset — exactly the claimed surface.distance_metricwas measured, not assumed — six candidate spellings probed againstFieldSchema.safeParse, then the spec's own source read for the authoritative key list (vector shape declares onlydimensions) AND theFIELD_KEY_GUIDANCEalias/retirement table checked (no entry under any spelling). No equivalent exists ⇒ deleted, not renamed; the spec-extension option correctly untouched.indexedrode the mechanical branch with the fix(types): remove BaseFieldMetadata.indexed — dead declared key #4686-style tombstone.origin/mainmerged forward rather than duplicating the tombstone — and the post-merge reverse verification honestly notes the pre-merge masking (the inheritedBaseFieldMetadata.indexedwould not have flagged), which is exactly why bothTS2353probes were re-confirmed after the merge. Good discipline, good record.check-spec-symbol-derivation— right call for a field-types change.CI on this head is converging — ready + auto-merge flips when Lint / Type Check / Test shards conclude green (folded into the standing timer round). Card closes on merge;
pm:dispatchedcomes off then.Generated by Claude Code
fix(types): retire VectorFieldMetadata.indexed and .distance_metric (o…
feat(tooling): gate designer field payload keys against the installed…
feat(tooling): gate designer field payload keys against the installed…