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
This is an upstream (objectstack-ai/objectstack) gap, filed in hotcrm as a tracker because the session that found it has no access to the upstream repo (add_repo → you need push access to objectstack-ai/objectstack). The ready-to-paste upstream body is at the bottom — someone with push access can move it over and close this.
Verified with the merged reference-integrity rule (objectstack#3885 validate-ai-tool-references): 22 tool references, 0 findings
and the follow-up commit adds:
Re-verified with the corrected rule (objectstack#3894, which now models AI exposure): 19 tool references, 0 findings
That rule is not present in the @objectstack/*@16.1.0 packages this repo installs. Which is why search_knowledge in customer_360 survived #512 and had to be caught by hand in #493 / #557 — nothing in the shipped toolchain could see it.
Evidence
Checked three layers, not just one:
@objectstack/lint@16.1.0 — the strings skill, tool and agent do not appear anywhere in dist/index.js. Zero occurrences, so no rule of any kind inspects AI metadata.
lint-liveness-properties (@objectstack/cli) — this one does cover skills (TYPE_COLLECTIONS includes { type: 'skill', key: 'skills' }), but it is ledger-driven and only flags dead authored properties. It has no notion of resolving a tools[] name against a registry, so it cannot catch this class.
So the check either was never released, was dropped before 16.1.0, or lives only in the closed cloud distribution. Any of the three is worth knowing.
Why it matters beyond hotcrm
SkillSchema.tools is a list of bare strings. validate and build check only that each is well-formed snake_case; at runtime an unresolved name is silently dropped. The model is then handed instructions describing a capability it does not have, and improvises. Every instance of this ships green — hotcrm accumulated eleven of them across six skills before anyone noticed, and it is the reference app. Any app built on ObjectStack has the same blind spot.
Interim mitigation (already merged here)
#557 added test/skills-integrity.test.ts, a repo-local guard: every skill tool must resolve to a platform built-in or an action_<name> materialised from an Action that is ai.exposed with a headless path; AI tool metadata cannot satisfy a dangling reference (ToolSchema is a read-only projection with no executor); and skill-to-skill handoffs in instructions must resolve.
That is a workaround, not a fix — every ObjectStack app would have to reimplement it, and the built-in allowlist has to be hand-maintained because the AI runtime ships closed (ADR-0025 §2) and exposes no authoritative tool list to validate against.
Ship it in the open-edition toolchain (@objectstack/lint or objectstack validate), not only in cloud. The metadata it validates is authored in the open edition, so the check belongs there.
Expose the platform built-in tool registry as data the open edition can read. Without it, any local guard hardcodes a list that silently drifts from the runtime — which is a smaller version of the same bug.
Ready-to-paste body for the upstream issue
Title:validate-ai-tool-references is not in the 16.1.0 open-edition toolchain — skill tools[] names are unvalidated
SkillSchema.tools holds bare strings. objectstack validate / build check only the snake_case shape; the runtime silently drops a name it cannot resolve. The result is a skill whose instructions describe tools the model does not have — it validates, builds, and passes CI in that state.
objectstack#3885 / #3894 describe a validate-ai-tool-references rule for exactly this, and downstream work cited it as the verification. It is not present in @objectstack/*@16.1.0:
@objectstack/lint@16.1.0dist/index.js contains zero occurrences of skill, tool, or agent.
lint-liveness-properties does walk skills, but is ledger-driven over dead properties only — it has no reference-resolution step.
Impact: objectstack-ai/hotcrm, the reference app, accumulated eleven skill references to tools that exist nowhere (#493). Ten were removed by hand in #512, the last in #557, all found by human audit rather than by tooling.
Requests:
Confirm whether the rule shipped, and where.
Ship it in the open-edition toolchain — the metadata is authored there, so the check belongs there.
Expose the built-in tool registry as data the open edition can read. Any downstream guard currently has to hardcode the built-in list, which drifts from the runtime silently — a smaller instance of the same defect.
Why this is filed here
This is an upstream (
objectstack-ai/objectstack) gap, filed in hotcrm as a tracker because the session that found it has no access to the upstream repo (add_repo→you need push access to objectstack-ai/objectstack). The ready-to-paste upstream body is at the bottom — someone with push access can move it over and close this.The gap
#512's commit message states its fix was:
and the follow-up commit adds:
That rule is not present in the
@objectstack/*@16.1.0packages this repo installs. Which is whysearch_knowledgeincustomer_360survived #512 and had to be caught by hand in #493 / #557 — nothing in the shipped toolchain could see it.Evidence
Checked three layers, not just one:
@objectstack/lint@16.1.0— the stringsskill,toolandagentdo not appear anywhere indist/index.js. Zero occurrences, so no rule of any kind inspects AI metadata.objectstack validate(@objectstack/cli@16.1.0) — runs 13 checks; none touches AI metadata:JSX-source pages (ADR-0080),React-source page props (ADR-0081),React-source pages (ADR-0081),SDUI styling (ADR-0065),capability providers,capability references (ADR-0066),dashboard action references (ADR-0049),dashboard widget bindings (ADR-0021),flow trigger wiring,list-view navigation modes (ADR-0053),security posture (ADR-0090 D7),source-page styling (ADR-0065),view container shape.lint-liveness-properties(@objectstack/cli) — this one does cover skills (TYPE_COLLECTIONSincludes{ type: 'skill', key: 'skills' }), but it is ledger-driven and only flags dead authored properties. It has no notion of resolving atools[]name against a registry, so it cannot catch this class.So the check either was never released, was dropped before 16.1.0, or lives only in the closed cloud distribution. Any of the three is worth knowing.
Why it matters beyond hotcrm
SkillSchema.toolsis a list of bare strings.validateandbuildcheck only that each is well-formedsnake_case; at runtime an unresolved name is silently dropped. The model is then handed instructions describing a capability it does not have, and improvises. Every instance of this ships green — hotcrm accumulated eleven of them across six skills before anyone noticed, and it is the reference app. Any app built on ObjectStack has the same blind spot.Interim mitigation (already merged here)
#557 added
test/skills-integrity.test.ts, a repo-local guard: every skill tool must resolve to a platform built-in or anaction_<name>materialised from an Action that isai.exposedwith a headless path; AI tool metadata cannot satisfy a dangling reference (ToolSchemais a read-only projection with no executor); and skill-to-skill handoffs in instructions must resolve.That is a workaround, not a fix — every ObjectStack app would have to reimplement it, and the built-in allowlist has to be hand-maintained because the AI runtime ships closed (ADR-0025 §2) and exposes no authoritative tool list to validate against.
Asks for upstream
validate-ai-tool-references(objectstack#3885 / #3894) shipped, and in which package/version. If it did not, that makes refactor(ai): skills-only AI surface — real Actions instead of 10 fictional tools, retire the two agents #512's "0 findings" verification unfounded — worth a note on that PR.@objectstack/lintorobjectstack validate), not only in cloud. The metadata it validates is authored in the open edition, so the check belongs there.Ready-to-paste body for the upstream issue
Title:
validate-ai-tool-referencesis not in the 16.1.0 open-edition toolchain — skilltools[]names are unvalidatedSkillSchema.toolsholds bare strings.objectstack validate/buildcheck only thesnake_caseshape; the runtime silently drops a name it cannot resolve. The result is a skill whose instructions describe tools the model does not have — it validates, builds, and passes CI in that state.objectstack#3885 / #3894 describe a
validate-ai-tool-referencesrule for exactly this, and downstream work cited it as the verification. It is not present in@objectstack/*@16.1.0:@objectstack/lint@16.1.0dist/index.jscontains zero occurrences ofskill,tool, oragent.objectstack validate(@objectstack/cli@16.1.0) runs 13 checks, none over AI metadata (ADR-0080/0081 pages, SDUI/source styling ADR-0065, capability providers + references ADR-0066, dashboard action refs ADR-0049, widget bindings ADR-0021, flow trigger wiring, list-view nav ADR-0053, security posture ADR-0090 D7, view container shape).lint-liveness-propertiesdoes walkskills, but is ledger-driven over dead properties only — it has no reference-resolution step.Impact:
objectstack-ai/hotcrm, the reference app, accumulated eleven skill references to tools that exist nowhere (#493). Ten were removed by hand in #512, the last in #557, all found by human audit rather than by tooling.Requests: