Skip to content

fix(hire): the schema now permits the default its description promised - #14

Closed
lucy-wolfe wants to merge 1 commit into
tribes-protocol:mainfrom
lucy-wolfe:fix/hire-department-optional
Closed

fix(hire): the schema now permits the default its description promised#14
lucy-wolfe wants to merge 1 commit into
tribes-protocol:mainfrom
lucy-wolfe:fix/hire-department-optional

Conversation

@lucy-wolfe

Copy link
Copy Markdown
Contributor

An agent hiring into its own team passed the company name as a department id. It was following our own guidance, and the schema made following it impossible.

The mechanism

org_hire's departmentId was Type.Stringrequired — while its own description opened:

"Where this person lands. DEFAULT: the department YOU head — a hire joins the team that asked for it."

The transcript shows the agent reasoning that it should omit the field to get that default, meeting a schema that would not permit omission, and filling it with the most salient name available: the company's.

It obeyed the instrument over the claim, which is the correct thing for it to do. A description is a promise about the schema; where the two disagree, the claim is what gets believed and the schema is what gets obeyed. This is the same defect that has recurred in comments and reports — a claim no gate falsifies — expressed in a tool surface.

The change

The field is optional, and the default is real: an omitted id resolves to the department the caller heads, or failing that the one they sit in. That resolver already existed and is word-for-word what the description promised — the promise was always implementable and simply was not implemented.

The worked example now shows the omitted form first:

{"person":{"name":"Rhea","title":"Staff Engineer","mandate":"Own the SQLite store."}}

with departmentId shown as the override. An example that keeps passing the field re-teaches the habit the description is trying to correct.

The company name is still refused

That refusal is now the only thing standing behind an explicitly-passed id, so it is pinned by a test that passes the field deliberately rather than omitting it — otherwise the test would quietly become a default-path test the day the default landed, and stop guarding anything.

Accepting the name as an alias was rejected again, for a sharper reason than before: with a default in place, the alias would exist only on the override path — where a mid-level head naming the company means their own team. It would resolve to the impressive-sounding wrong target rather than the semantically right one, which is worse than the refusal it would replace.

The sweep, which was the substance rather than an appendix

The general question — does the schema permit what the prose promises? — asked of every parameter in the file, across DEFAULT, defaults to, omit, omitted, optional and leave empty.

Exactly one leaf field disagreed: this one. One other hit reads "Required complete message text. Never omit this field" and is required, so its prose and schema agree — a false positive in the opposite direction.

No mechanical guard was added. The rule given was that a second instance makes one mandatory and zero makes it skippable; there are none. An instrument for a class of one is furniture.

A detector artifact worth reporting

My first sweep reported sixteen mismatches. Fifteen were Type.Object containers matching on a nested field's prose — the detector was measuring a property adjacent to the question rather than the question. Refining it to leaf fields gave the real answer, which was one.

That is worth stating because the wrong number was the alarming one, and a sweep that over-reports is as misleading as one that under-reports.

Also caught, by an existing guard

The longer tool description pushed org_hire to 1056 characters, over the 1024 a strict provider accepts. It is 993 now — trimmed rather than expanded, since the point of the change is that the example should be shorter, not longer.

Tests

  • both arms of the resolver: a head gets the department they head, a non-head gets the one they sit in (mutation-verified — a head-only resolver fails the second);
  • the resolved default survives the scope check the hire then applies to it, so omitting the field cannot trade a guess for a refusal;
  • the explicit company name is still refused, with the root id named in the refusal.

Checks

bun run typecheck, test, lint, lint:reactive, knip, all 98 guards, the tool-contract lanes by path (4 files, 31 tests run), and CI.

…ed a default

The field was REQUIRED under a description opening 'DEFAULT: the department YOU
head'. An agent read that, reasoned correctly that it should omit the field,
met a schema that would not allow it, and improvised the most salient name in
context -- the company's. It obeyed the instrument over the claim, which is the
right thing for it to do.

The field is optional now and the default is resolved in execute using the
helper that already existed: the department the caller heads, or failing that
the one they sit in. That is word-for-word what the description promised, so
the promise was always implementable and simply was not implemented.

The worked example now shows the omitted form first. An example that keeps
passing the field re-teaches the habit the description is trying to correct.

The sweep asked the general question of every parameter in the file -- does the
schema permit what the prose promises -- across DEFAULT, omit, omitted,
optional and leave empty. Exactly one leaf field disagreed: this one. The only
other hit says 'never omit this field' and is required, so its prose and schema
agree. No mechanical guard was added: an instrument for a class of one is
furniture.

My first sweep reported sixteen mismatches. All but one were container objects
matching on a nested field's prose -- the detector measured a property adjacent
to the question. Refining it to leaf fields gave the real answer.

Also caught by an existing guard: the longer tool description exceeded the 1024
characters a strict provider accepts. Trimmed to 993 rather than expanded.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lucy-wolfe
lucy-wolfe requested a review from hishboy as a code owner August 28, 2026 16:17
@lucy-wolfe

Copy link
Copy Markdown
Contributor Author

Superseded by #16, which merges this branch together with the other two changes so main takes one commit and mints one release. The review that happened here still stands; nothing was rewritten on the way in.

@lucy-wolfe lucy-wolfe closed this Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant