Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .claude/skills/porting-to-canyonos/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ without a question. Never deploy or ask whether to deploy from that flow.

## Progress

Copy this checklist into the response and update it while working:
Use this checklist for progress updates, not the final handoff:

```text
Port progress:
Expand All @@ -35,7 +35,8 @@ import root from actual imports and use `prepare.py`; do not assemble or refresh

Read [references/source-survey.md](references/source-survey.md) in full. Produce
its survey record and choose the smallest useful service map before writing
runtime code or configuration.
runtime code or configuration. Apply its application-readiness gate; pause the
build and cite the guide when the source has a blocking prerequisite.

## 3. Implement the port

Expand Down Expand Up @@ -63,7 +64,9 @@ Read these only when triggered:
Read
[references/validation-and-deploy.md](references/validation-and-deploy.md).
Validate only authored contracts that CanyonOS tooling does not strongly
guarantee. Fix every reported error, hand off warnings and blockers, then stop.
guarantee. Fix every reported error, then use its concise success or blocked
handoff and stop. Keep the final message limited to status, required developer
actions, and next steps.
Do not run `canyonos deploy` without explicit user approval.

## Diagnose an approved deployment
Expand Down
29 changes: 28 additions & 1 deletion .claude/skills/porting-to-canyonos/references/adapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ Use this order:
1. Choose a safe entrypoint module for each service.
2. Write a no-argument synchronous adapter around source-owned behavior.
3. Bridge async or session state only when the source requires it.
4. Write the workflow and preserve parallel dispatch.
4. Write the workflow, preserve parallel dispatch, and resolve final outputs
with `.value()` before returning.

Complete `manifest.md`, then validate only the authored contracts that CanyonOS
does not already guarantee.
Expand All @@ -22,6 +23,7 @@ only when a container loads.
## Contents

- Adapter and workflow shape
- Resolving workflow outputs
- Choosing the entrypoint
- Bridging async
- Multi-turn and session state
Expand All @@ -46,6 +48,26 @@ writes there holds the LLM proxy alone, under an `__init__` that exports
nothing. `from canyonos_core import deploy` builds green and raises ImportError
at container start. V021.

## Resolving workflow outputs

Every remote service call returns a Future, not its computed value. In
`main(query: str)`, explicitly call `.value()` on each Future contributing to
the final output before returning it, including values nested in dictionaries,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not a blocker, but final output is a bit misleading, what if you call the Futures value in one place and then call it again later

lists, or tuples.

```python
def main(query: str) -> dict[str, str]:
answer = agent.work(query=query)
return {"answer": answer.value()}
```

Before returning from `main`, resolve any Future included in the final output
with `.value()`. For example, if `answer` is a Future, use
`return answer.value()`. Calling `str(...)` or `json.dumps(...)` does not resolve
a Future. Decode the resolved value with `json.loads(...)` only when it is JSON
text and the workflow needs the decoded structure. Return already concrete
values unchanged.

For parallel remote calls, dispatch all work before resolving any result:

```python
Expand All @@ -55,6 +77,11 @@ results = [json.loads(future.value()) for future in futures]

Combining dispatch and `.value()` in one comprehension serializes the work.

Before completing the workflow, trace every `return` in `main`, including
early returns and conditional branches. Verify that every remote result in
the returned payload passes through `.value()` before parsing, formatting, or
serialization, and that no nested Future escapes.

## Choosing the entrypoint

The entrypoint is the one module in the copy the build destroys: each agent's
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/porting-to-canyonos/references/llm-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ credential into a 401 that reads like a broken port.
This is a step, not a recommendation. Do not ask for approval first, and do not
close the port by reporting that the `.env` "should" point at the proxy: a
report that says so while the file still says otherwise is the failure this
section exists to prevent. `git status` will show `.env.example`; name it in the
handoff.
section exists to prevent. `git status` will show `.env.example`; report that
change in progress updates and name the required keys in the final handoff.

## A source with no env hook needs one in the `.car/app` copy

Expand Down
32 changes: 29 additions & 3 deletions .claude/skills/porting-to-canyonos/references/source-survey.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,34 @@
**Inspect:** `.car/app`, not a framework-based guess about the original tree.

**Output:** a short survey record and the smallest useful service map. Do not
start adapter or config work until each section is resolved or marked as a
blocker.
start adapter or config work until the readiness gate passes and each section
is resolved. A blocker pauses the build, not just the survey checklist.

## Application-readiness gate

Read [Preparing an Agent App for CanyonOS](https://github.com/CanyonCodeCoreAI/canyonos/blob/5cd4fa8c51082e414aad64e27283ba50c27c579f/docs/CANYONIZATION-APP-READINESS.md)
and check the selected serving path against its requirements before adapting
it. Use the target image's dependency baseline rather than copying version
numbers from the guide.

Pause the build when a required source capability cannot run within CanyonOS:
interactive or device-dependent serving, Docker inside the agent, unsupported
required model routing, incompatible dependencies or resource requirements,
unavailable required services/data, or a demonstrated source install, import,
or request failure. Check the actual serving path: an unused demo or optional
integration is not a blocker.

Do not silently remove required behavior, switch providers, fabricate data,
or repair source defects to make the port pass. Stop adapting when a blocker
is found, even if static validation could pass. Use the blocked handoff in
`validation-and-deploy.md`: identify the source evidence, the developer action
needed to resume, and a link to the relevant section of the readiness guide.
Do not report build success or recommend test/deploy while it remains blocked.

Credentials that only need filling in before test/deploy belong in the final
env reminder, not a build blocker. Record their names from source and
`.env.example`; never read `.env` or request secret values. Pause if missing
configuration, services, or data prevents determining or preparing the port.

## 1. Public behavior

Expand Down Expand Up @@ -61,7 +87,7 @@ import that only resolves from a nested root, an asset the sweep drops, a
credential name.

An existing syntax error on the selected import graph is a source defect;
obtain approval before changing even the copied version. The final gap validator
pause the build and identify the required source fix. The final gap validator
checks authored runtime code and cross-file bindings after the port is
complete.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ From the application root, run:
python3 <skill_dir>/validate.py .car
```

Fix every `ERROR` and rerun until the command exits 0. Do not hide warnings:
list each in the handoff and state whether it blocks this source.
Fix every `ERROR` and rerun until the command exits 0. Review every warning;
pause for blockers and surface required developer actions in the handoff.
Keep non-actionable diagnostic details in progress updates.

Confirm with `git status` that nothing outside `.car` changed except the two
files the port is allowed to write: `.gitignore`, which `prepare.py` adds the
artifact to, and `.env.example`, which proxy wiring appends to. Name both in
the handoff. `.env` is written the same way but is normally ignored, so it does
not show up there.
artifact to, and `.env.example`, which proxy wiring appends to. Report these
changes in progress updates. `.env` is written the same way but is normally
ignored, so it does not show up there.

## What a clean run does not prove

Expand All @@ -49,28 +50,48 @@ into each image, anything reached only at runtime, or whether the first request
returns an answer. A ModuleNotFoundError at container start and an
AttributeError on the first call both survive an exit-0 run.

Report it as what it is. "Gap validation exits 0" is accurate; "validation
passed" claims a deployment nobody ran.

Report:

- that the `.car` port validated;
- files created;
- validator warnings;
- unresolved runtime blockers;
- intentionally omitted unreachable dependencies or source surfaces.

In an attended porting session, stop and ask exactly one direct approval
question:

> Gap validation exits 0 -- static checks only; no image was built and no
> request served. Run `canyonos deploy` now? This will build images and start
> the deployment.

For an unattended `canyonos build -y`, instead report the validation result and
stop without asking this question. The build command only creates and validates
the port; it never deploys. Do not treat silence, an unattended run, or the
original request to “port” as approval.
## Final handoff

Keep the final message short and actionable. Do not repeat the progress
checklist, file inventory, implementation details, or raw validator output.
Use the developer's language. Do not ask whether to deploy or run additional
commands as part of the handoff, in attended or unattended sessions.

**Success:** only after gap validation exits 0 and no readiness blocker
remains, report that the porting work for `canyonos build` succeeded. This
means `.car` was prepared and validated, not that images were built or a live
request passed. When running inside the build's coding session, do not claim
the parent CLI has exited successfully; it performs its final check after the
session ends.

Name the required environment keys from the source and `.env.example`, and
the configured `env_file` path (normally `.env`). Tell the developer to fill
them before the operations that require them; never show secret values or
claim their presence was verified. `canyonos test` stubs LLM calls by default;
real model calls and deployment need provider credentials, and external tools
may still need their own keys during testing.

Offer only these next steps: quit the coding session to return to the CLI,
or run `canyonos test` / `canyonos deploy` from the application root. For example,
substituting the actual required keys and env file:

> Porting for `canyonos build` succeeded; `.car` passed static validation.
> Before deployment or real model calls, set `OPENAI_API_KEY` in `.env`.
> Next: quit this coding session, or run `canyonos test` for a local check /
> `canyonos deploy` to deploy.

**Blocked:** say the build is paused and identify the concrete source problem
with its file/call-path evidence. Give the developer the specific change
needed before retrying `canyonos build`, and link the relevant section of
[Preparing an Agent App for CanyonOS](https://github.com/CanyonCodeCoreAI/canyonos/blob/5cd4fa8c51082e414aad64e27283ba50c27c579f/docs/CANYONIZATION-APP-READINESS.md).
Do not use the success message or suggest test/deploy. For example:

> Build paused: `agent.py` starts Docker for required code execution. Move
> execution to an external sandbox service, then rerun `canyonos build`.
> See [readiness guide: Docker inside the application](https://github.com/CanyonCodeCoreAI/canyonos/blob/5cd4fa8c51082e414aad64e27283ba50c27c579f/docs/CANYONIZATION-APP-READINESS.md#2-do-not-require-docker-inside-the-application).

The build command only creates and validates the port; it never deploys. Do
not treat silence, an unattended run, or the request to port as deploy approval.

## Deploy only after approval

Expand Down
Loading