Commit d5a5a8f
authored
* feat(contract): add the stdio server's local-git tool contracts and converge the hand-mirrored inputs
Adds the 19 tools the remote migration could not cover, which is every tool
the stdio server registers that the remote one either does not have or
declares differently. All 102 stdio tools now have a contract entry.
Thirteen of these existed on both servers with two hand-mirrored input
schemas that had already drifted -- the stdio copies of find_opportunities,
retrieve_issue_context and mark_notifications_read carried no length bounds
at all. The contract takes the wider bound in every such case, and resolves
the eligibility-transform question #9518 documented rather than solved: the
contract describes what a caller may SEND, so the pre-transform shape is the
one that belongs here and the remote server's downgrade stays a server-side
control over the parsed value.
* feat(mcp): register every stdio tool from @loopover/contract
All 102 stdio tools now take their title, description, category, annotations,
and BOTH schemas from the registry. ~85 hand-mirrored input shapes and the
560-line STDIO_TOOL_DESCRIPTORS table are gone (the bin file drops ~1,100
lines), every handler is typed via z.infer instead of `(input: any)`, and 97
of the 102 gain a real output schema where they had none.
The registration helper passes the schema OBJECTS, not their .shape. The SDK
accepts either, but a raw shape is re-wrapped in a plain z.object, which
discards the catchall -- so every output modelled as a looseObject would be
advertised and enforced as additionalProperties:false, and any field the
payload carries beyond the modelled set becomes a -32602 the caller cannot act
on.
Turning the output schemas on surfaced six real defects, which is what they are
for:
- the agent audit feed models pullNumber/actor/detail as nullable, but the
route OMITS them rather than sending null, so every real feed failed
validation;
- plan_repo_issues and generate_contributor_issue_drafts declared their six
counters required, but the service short-circuits to a countless
disabled/unavailable posture -- which is exactly why the CLI proxies carry
'?? 0' fallbacks;
- three test fixtures described payloads the services do not produce (laneFit
as a lane name rather than a fit score, autoMaintain as a string rather than
the settings object, a pending-action row missing four ledger columns).
Fixtures fixed, not schemas.
Four input divergences converged, each by widening so no live caller breaks:
get_repo_onboarding_pack gains stdio's 'refresh'; preflight_local_diff and
explain_score_breakdown gain stdio's local-diff fields; and
get_pr_ai_review_findings -- the one tool whose two servers disagreed on a
FIELD NAME -- accepts both 'number' (canonical, and what every other PR-scoped
tool uses) and 'pullNumber' (the remote's alias).
list_pending_actions is the single deliberate narrowing: its route hardcodes
status 'pending' and cannot honour a filter, so the stdio server registers
ListPendingActionsStdioInput -- derived from the contract entry with .omit() --
rather than advertising a filter that would silently do nothing.
Also restores .strict() on callerBranchEligibilitySchema, dropped when it was
relocated in #9518: both servers wrapped it strictly before the migration, and
without it a caller inventing an eligibility field is silently stripped instead
of rejected.
* fix(ci): stop import-specifiers:check reporting three false positives and one real miss
The checker exits 1 on main today. Two of the three reports are its own false
positives and the third is mine.
- check-dead-source-files-script.test.ts embeds import-statement TEXT as string
fixtures for its script's injectable readFile, and a js-suffixed relative
specifier is the exact case that test exists to pin -- so its fixtures read as
violations. Allowlisted, the same way this checker already allowlists its own
test file for the same reason.
- scripts/actionlint.ts runs under 'node --experimental-strip-types', whose
loader does no extension resolution: the literal .ts is the only form that
starts. That is a fact about how package.json invokes it, not something
readable from the source, so the entrypoint is listed explicitly.
- The three relative imports #9517/#9518 added to contract-registry.test.ts
carried .js in a Bundler-resolved zone. Extension dropped.
* feat(engine): collapse the duplicated plan-DAG state machine into @loopover/engine
Completes #9537's last requirement, and fixes the build failure the first push
of PR #9565 hit.
THE BUILD FIX: `ToolContract` was imported from @loopover/contract/tools, which
only imports that type internally and never re-exports it. The local typecheck
resolves the package through a src alias and passed; the real package build
resolves the export map and failed at 'Build MCP'. Now imported from the package
root, which does export it.
THE PLAN-DAG DEDUP: buildPlanDag/validatePlanDag/the step state machine existed
in src/services/plan-dag.ts AND hand-copied, untyped, into the stdio MCP bin --
whose own comment explained why: it resolves @loopover/engine through the
published package, whose export map did not surface them. It does now.
Moving it turned up a THIRD partial copy already in the engine: plan-export.ts
holds the step/plan types, plan-step-readiness.ts holds nextReadySteps/isDone,
and plan-overall-status.ts holds the status vocabulary, each decomposed into its
own module. The moved file imports all three rather than restating them -- a
fourth PlanDag would have defeated the point -- and contributes only the
mutating half (build, validate, advance) that had no engine home.
src/services/plan-dag.ts stays as the Worker's import path, now a re-export, so
nothing else had to move.
Release ordering, which is why this looked blocked: both publish workflows are
workflow_dispatch-only, so nothing auto-publishes on merge and an operator
publishes the engine before the CLI, as usual. The engine takes a minor bump for
the new export, with packages/loopover-miner/expected-engine.version and both
consumers' dependency ranges moved to ^3.16.0 in the same commit so a published
CLI can never resolve an engine without it.
Also declares @loopover/contract#build as an edge of the root typecheck task.
That was working only because ci.yml happens to run a contract build first; the
edge makes a bare 'turbo run typecheck' correct on its own.
* fix(mcp,typecheck): prune the imports the contract migration orphaned, and make the root typecheck catch them
The stdio migration left ~40 imports and shape constants unreferenced once every
tool started resolving its schemas through getToolContract. @loopover/mcp's own
tsconfig sets noUnusedLocals, so its package build failed on all of them -- twice
-- while 'npm run typecheck' and the full unit suite stayed green locally.
That gap is the real bug, and it is fixed here rather than worked around: the
root 'typecheck' script now runs the root tsconfig AND each package whose config
is stricter than it (@loopover/contract, @loopover/mcp, @loopover/miner). A bare
'npm run typecheck' now covers the same surface CI's build steps do, so this
class of failure cannot pass locally and fail in CI again.
Also defaults preflight_local_diff's baseRef at the call site. It is optional in
the shared contract input -- the remote server has no checkout to read -- so the
local diff collector needs the 'HEAD' default the stdio-only shape used to bake
into the schema.
* chore(release): sync the release-please manifest to the engine's 3.16.0 bump
The engine version bump that gives the stdio server a published plan-DAG export
has to be reflected in .release-please-manifest.json, which release-please reads
to decide what it is releasing. Caught by release-manifest:sync:check.
* test(mcp): cover the pr-ai-review-findings field-name alias and its two caller-error paths
codecov/patch flagged the new branches in getPrAiReviewFindings: every existing
test supplies pullNumber, so the canonical 'number' side of the alias and both
'required field missing' throws were unexercised.
* chore: move the #9520 validator files out of this PR
They were swept in by a git add -A while both branches were in flight; they
belong to the contract-validator issue, not the stdio migration.
* test(engine): move the plan-DAG behavioural tests in with the implementation
codecov/patch flagged packages/loopover-engine/src/plan-dag.ts at 40%: the engine
uploads its own coverage from its own node:test suite, so the root suite's
test/unit/plan-dag.test.ts -- which exercises the same code thoroughly through
the Worker's re-export -- contributes nothing to it.
The tests move with the implementation. 100% statements and branches on the
moved module, verified with c8 against the engine's own dist.
1 parent 3bffb87 commit d5a5a8f
30 files changed
Lines changed: 1427 additions & 1946 deletions
File tree
- packages
- loopover-contract/src/tools
- loopover-engine
- src
- test
- loopover-mcp
- bin
- loopover-miner
- scripts
- src
- mcp
- services
- test/unit
- support
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
100 | | - | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
101 | 103 | | |
102 | 104 | | |
103 | 105 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
598 | 598 | | |
599 | 599 | | |
600 | 600 | | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
601 | 612 | | |
602 | 613 | | |
603 | 614 | | |
| |||
644 | 655 | | |
645 | 656 | | |
646 | 657 | | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
647 | 661 | | |
648 | 662 | | |
649 | | - | |
| 663 | + | |
650 | 664 | | |
651 | | - | |
652 | | - | |
| 665 | + | |
| 666 | + | |
653 | 667 | | |
654 | 668 | | |
655 | 669 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
52 | 56 | | |
53 | 57 | | |
54 | 58 | | |
| |||
Lines changed: 36 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
484 | 484 | | |
485 | 485 | | |
486 | 486 | | |
487 | | - | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
488 | 510 | | |
| 511 | + | |
489 | 512 | | |
490 | | - | |
491 | 513 | | |
492 | 514 | | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
493 | 527 | | |
494 | 528 | | |
495 | 529 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
116 | 116 | | |
117 | 117 | | |
118 | 118 | | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
119 | 140 | | |
120 | 141 | | |
121 | 142 | | |
| |||
218 | 239 | | |
219 | 240 | | |
220 | 241 | | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
221 | 261 | | |
222 | 262 | | |
223 | 263 | | |
| |||
259 | 299 | | |
260 | 300 | | |
261 | 301 | | |
| 302 | + | |
262 | 303 | | |
0 commit comments