Skip to content

fix(preflight-shape): contract start graph-body repair fields#4

Merged
tiziano-contorno merged 1 commit into
Tiziano-AI:mainfrom
ShinonKagura:pr3-pre-graph-body-fields
May 28, 2026
Merged

fix(preflight-shape): contract start graph-body repair fields#4
tiziano-contorno merged 1 commit into
Tiziano-AI:mainfrom
ShinonKagura:pr3-pre-graph-body-fields

Conversation

@ShinonKagura

Copy link
Copy Markdown

Second of three focused PRs splitting out the usable parts of #2 against current main, as requested in your review.

What

GRAPH_BODY_FIELDS in preflight-shape.ts was suggesting users relocate agents / synthesis / outputContract / callerSkills under graph via the "move under graph" repair hint. But GraphSchema rejects all four under additionalProperties: false — following the hint just produced a second failure.

Trimmed to what GraphSchema actually accepts: objective, steps, limits, authority. library is intentionally excluded because it has a more specific repair branch later in repairFor; the broad "move under graph" hint would clobber that better message.

The diff

+// Graph body fields recognized for the start "move under graph" repair message.
+// Kept in sync with schemas.ts GraphSchema (objective, steps, limits, authority).
+// `library` is intentionally excluded — it has a more specific repair branch later
+// in repairFor that points to graph.library; the broad "move under graph" hint
+// would clobber that more useful message.
+// Historical fields agents/synthesis/outputContract/callerSkills were dropped because
+// GraphSchema rejects them under additionalProperties:false, so suggesting users
+// relocate those fields under `graph` would only produce a second failure.
+// (callerSkills is agent-frontmatter scope, not graph-body scope.)
-const GRAPH_BODY_FIELDS = new Set<PreflightField>(["objective", "steps", "limits", "authority", "agents", "synthesis", "outputContract", "callerSkills"]);
+const GRAPH_BODY_FIELDS = new Set<PreflightField>(["objective", "steps", "limits", "authority"]);

Why

User experience bug: a model passing agents: [...] at top level got told "Move graph body fields under graph", then received a schema rejection when it tried. The trim eliminates this double-error flow.

Discipline

  • PreflightField and KNOWN_FIELDS are unchanged — misplaced-field detection still works for agents / synthesis / outputContract / callerSkills.
  • Only the relocation hint is narrowed.
  • Inline comment explains why the 4 fields were dropped and why library is intentionally excluded.
  • Parametrized regression test in planning.test.ts covers all 4 removed fields (asserts each triggers start-control-fields-denied AND does NOT match Move graph body fields under graph).

Required checks against this branch

Check Result
npx tsc --noEmit ✅ exit 0
node --test tests/*.test.ts ✅ 244/244 pass, 0 fail
node tests/check-source-size.ts ✅ PASS
node tests/check-public-docs.ts ✅ PASS
git diff --check HEAD~1..HEAD ✅ clean

Discipline notes

  • No version bump
  • Changelog entry under ## Unreleased only (1 sentence)
  • Single focused commit

Related

Closes a portion of #2 (separately scoped). Companion PRs:

@tiziano-contorno

Copy link
Copy Markdown
Contributor

Thanks for splitting this out. The direction is right, but I want to fix the root shape here rather than keep tuning legacy-field repair behavior.

agents, synthesis, outputContract, and callerSkills are not current agent_team public API. I don’t want preflight-shape.ts to keep carrying them as known/tombstoned fields with bespoke repair logic. That creates exactly this class of confusing compatibility tether.

Please rework this as a contraction:

  • Keep a narrow current-contract repair for valid graph body fields accidentally sent at top level:
    • objective
    • steps
    • limits
    • authority
  • Remove retired fields from PreflightField, KNOWN_FIELDS, GRAPH_BODY_FIELDS, comments, and tombstone-specific tests:
    • agents
    • synthesis
    • outputContract
    • callerSkills
  • Let deleted/unknown fields fail through strict schema validation as unsupported unknown properties. Do not provide conversion/babysitting advice for removed designs.
  • Keep current useful special repairs such as top-level library for start, misplaced extensionTools, preview, waitSeconds, etc.
  • Rename GRAPH_BODY_FIELDS to something more precise like START_GRAPH_BODY_REPAIR_FIELDS, since it is not the full GraphSchema (library is valid but intentionally handled separately).
  • Add a regression test for a mixed malformed shape, e.g. top-level objective + steps plus unknown retired fields, proving the repair only mentions moving current graph fields under graph and does not treat retired fields as known graph fields.

So: keep “move current graph fields under graph” as a current-shape repair, but remove the legacy-field awareness entirely.

@ShinonKagura ShinonKagura force-pushed the pr3-pre-graph-body-fields branch from a717555 to fb85e50 Compare May 28, 2026 16:40
@ShinonKagura ShinonKagura force-pushed the pr3-pre-graph-body-fields branch from fb85e50 to 4e081b7 Compare May 28, 2026 16:46
@ShinonKagura ShinonKagura changed the title fix(preflight-shape): trim GRAPH_BODY_FIELDS to schema-accepted set fix(preflight-shape): contract start graph-body repair fields May 28, 2026
@ShinonKagura

Copy link
Copy Markdown
Author

Thanks — I reworked this as a current-contract contraction and rebased it onto current upstream/main.

Current state:

  • base: upstream/main @ 4d9734b
  • branch/head: pr3-pre-graph-body-fields @ 4e081b7

What changed:

  • renamed the repair set to START_GRAPH_BODY_REPAIR_FIELDS;
  • limited the start graph-body repair set to current schema fields only:
const START_GRAPH_BODY_REPAIR_FIELDS = new Set<PreflightField>([
  "objective",
  "steps",
  "limits",
  "authority",
]);
  • removed retired fields from preflight awareness/repair: agents, synthesis, outputContract, callerSkills;
  • deleted the legacy-field repair/tombstone behavior instead of preserving conversion advice;
  • kept useful current-shape repairs, including top-level library, misplaced extensionTools, preview, waitSeconds, etc.;
  • added tests/preflight-schema-drift.test.ts, including a mixed malformed regression proving only current graph fields are suggested for movement under graph while retired fields fall through to strict schema rejection;
  • no scheduleId, list, or reattach drift in this PR;
  • no version bump or release-section rewrite; changelog entry remains under ## Unreleased.

Validation after rebasing onto current upstream/main:

focused preflight test ✅ pass (5/5)
pnpm run typecheck    ✅ pass
pnpm test             ✅ pass (249/249)
git diff --check      ✅ pass

Scope check:

git diff upstream/main..pr3-pre-graph-body-fields -- \
  extensions/multiagent/src/preflight-shape.ts CHANGELOG.md tests/preflight-schema-drift.test.ts \
  | grep -E 'scheduleId|reattach|^\+.*\blist\b'
# no output

pnpm run gate caveat:

upstream/main @ 4d9734b: 244/244 tests pass, then smoke:fake-pi fails at the /tmp artifact-path assertion
this PR      @ 4e081b7: 249/249 tests pass, then the same smoke:fake-pi /tmp assertion fails

I reproduced that baseline gate failure on current upstream/main three times in the same environment. So the remaining gate failure is pre-existing in the smoke check and not introduced by this PR.

Repro commands:

# PR branch
cd /tmp/pi-multiagent-upstream
git checkout pr3-pre-graph-body-fields
node --no-warnings --experimental-strip-types --loader ./tests/pi-peer-loader.mjs --test tests/preflight-schema-drift.test.ts
pnpm run typecheck
pnpm test
git diff --check
pnpm run gate  # expected in this env: tests pass, then baseline smoke:fake-pi /tmp assertion fails

# Baseline comparison
git checkout --detach upstream/main
pnpm run gate  # expected in this env: 244/244 tests pass, then same smoke:fake-pi /tmp assertion fails

I also ran independent local read-only reviews against the final branch state; no blockers were found.

@tiziano-contorno tiziano-contorno left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks — this revision matches the contraction request. I verified the retired fields are no longer preflight-known, mixed malformed start repair only mentions current graph body fields, useful current repairs still work, and focused/full validation passes. I’ll tighten the changelog wording while resolving the merge conflict with #3.

@tiziano-contorno tiziano-contorno merged commit f820467 into Tiziano-AI:main May 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.

2 participants