Skip to content

feat(cli): add canyonos validate, backed by the contract checks in core - #180

Draft
userAugustos wants to merge 8 commits into
feat/manifest-schemafrom
feat/cli-validate
Draft

userAugustos wants to merge 8 commits into
feat/manifest-schemafrom
feat/cli-validate

Conversation

@userAugustos

@userAugustos userAugustos commented Sep 22, 2026

Copy link
Copy Markdown

What was done

canyonos validate checks a ported project with the platform's own rules, so the checks can no longer drift from the code.

The skill directory, canyonos build's call to the old validator and the docs are untouched here; the next PR removes the validator from the skill and points it at canyonos validate / canyonos test.

How to test it

uv sync --frozen --all-packages
uv run --active --frozen pytest packages/core/tests packages/cli/tests tests -q
uv run --active --frozen ruff check . && uv run --active --frozen ruff format --check .
uv run --active --frozen ty check
bun run test

Build a .car from examples/helloworld (config/global_controller.yaml and the agent YAMLs under .car/config/, agents/ and workflow/ under .car/app/), then from the directory holding it:

$ canyonos validate
✓ .car: clean.
$ echo $?
0

Make ExampleAgent.hello an async def:

CAR-ADAPTER-ASYNC  app/agents/example_agent.py:10
    `ExampleAgent.hello` is `async def`
      The executor calls method(**args) with no await, so Redis receives
      '<coroutine object ...>'. Keep the signature synchronous and call
      asyncio.run(...) inside the body.

✗ 1 error(s).

Mistype an entrypoint in the manifest:

CAR-ENTRYPOINT-MISSING  config/global_controller.yaml
    agents[0].entrypoint: app/agents/exmaple_agent.py does not exist

Declare an argument type: List[str]:

CAR-SCHEMA  config/example_agent.yaml:8
    agent.functions[0].arguments[0].type: 'List[str]' is not a builtin type; ...

Each exits 1. Also: canyonos validate --json; with Docker and no local core install, the same command runs inside the core image; canyonos test --rebuild deploys fresh even while a deploy is already running.

…stants

The Dockerfile templates and both copy lists spelled these out by hand, so
anything reading them from outside the build was reading a copy that could
drift. The templates and the lists are now generated from the constants.
validate_car runs the schema first and then the eight contracts the schema
cannot see -- the class the controller loads by name, the method it calls
without awaiting, the module the platform posts to -- against the same parsed
model and the same runtime constants the deploy uses.
Reusing a deploy that is already up makes the run cheap, but it also means the
run is no evidence that what is in the tree installs and imports. --rebuild
always stands up its own deploy, so the command can answer that question.
The command runs core's checks and renders them: imported in process where
canyonos_core is installed beside the CLI, otherwise the same module inside the
core image over a read-only bind mount of the project. The CLI keeps no
dependency on core either way.
…ot hold

A mistyped entrypoint, a mistyped workflow_file or a missing app/ validated
clean. The build treats each as a service to skip rather than a reason to stop,
so the deploy comes up green and short an agent. CAR-ENTRYPOINT-MISSING names
the manifest field and the path it resolved to.

The rest of the change is one round of review fixes, kept together because each
of them crosses both packages at once:

- a finding has no level and there is no --strict: every check reports a
  violation, so the surface named something the checks never produced
- the container is given the .car itself rather than its parent, and --config
  is resolved against the artifact root in both paths and refused when it
  points outside it
- --json reports a failure as {"error": ..., "findings": []} rather than
  console text
- a reply from the image is checked for the fields the renderer reads
- init's socket lookup is public as `active_docker_socket`, and says what its
  None actually covers: a remote context, or a daemon that is not running
…ach missing file costs

A `./agents/x.py` entrypoint, which the schema accepts, named the module
`..agents.echo_agent`, so the workflow's correct import of it was reported as
reaching past the stub.

CAR-ENTRYPOINT-MISSING now carries the mechanism for the case it found -- an
agent file, a workflow file, or the source root -- written as the contract the
build needs rather than as the skip it performs today.

The container's reply is checked by type, not only for the keys, and a `--json`
run that never got to check anything prints the keys a run that did prints,
with `errors` null beside the reason.
@coderabbitai

coderabbitai Bot commented Sep 22, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • main

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: a16456d1-367b-43e7-a6f0-9aa57eb30407

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@userAugustos
userAugustos marked this pull request as draft September 22, 2026 22:52
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