Skip to content
Open
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
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nanoclaw-e2e",
"description": "Install and verify NanoClaw on exe.dev, Proxmox, macOS or Windows WSL2, then triage failures against upstream issues and PRs with form-aware reporting.",
"version": "0.12.0",
"version": "0.13.0",
"author": {
"name": "Nano Co",
"url": "https://github.com/nanocoai"
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ __pycache__/
# typesafe-docs-drift raw answers (doc excerpts and code snippets) and this clone's worktrees.
/skills/typesafe-docs-drift/output/
/.worktrees/

# typesafe-triage raw answers (may contain issue bodies).
/skills/typesafe-triage/output/
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ instead of being backfilled as releases.

## Unreleased

Development milestone (plugin 0.12.0); supersedes the unreleased 0.11.0
milestone and is not yet released.
Development milestone (plugin 0.13.0); supersedes the unreleased 0.11.0 and
0.12.0 milestones and is not yet released.

### Added

Expand Down Expand Up @@ -63,6 +63,13 @@ milestone and is not yet released.
wall time, per-pair latency with startup overhead separated, tokens, cost,
parse failures, run-to-run flips, agreement, and precision/recall on
`contradicts` against a 30-pair gold file labeled by an LLM-assisted reviewer.
- `typesafe-triage` skill: a dry-run label triage of open nanocoai/nanoclaw
issues and PRs through the TypeSafe System One API. One fan-out request per
item (area, kind, priority, needs-repro or PR readiness), a confidence gate
that falls back to `triage/unresolved`, AGREE/DISAGREE/NEW against existing
labels, a summary with agreement rates, token usage and wall time, raw answers
saved under a gitignored directory, and `--fixture` replay for offline runs.
Reads `TYPESAFE_API_KEY` from the environment only and never writes to GitHub.
- OpenCode public-wizard E2E for OpenRouter, DeepSeek, and custom/self-hosted
API-key endpoints across exe.dev, Proxmox and Windows WSL2. Select the model
with `--opencode-model`, the endpoint with `--opencode-base-url`, and its API
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ selected provider's authentication choices from that exact Git revision.
| [e2e-windows](skills/e2e-windows/SKILL.md) | Qualify Windows WSL2 with the local Docker Desktop engine, then run the public wizard with validated reply, service and sanitized evidence. |
| [e2e-triage](skills/e2e-triage/SKILL.md) | Research unexpected E2E failures against upstream issues and PRs, recommend next actions, and prepare drafts using the target repository’s current issue forms. |
| [typesafe-docs-drift](skills/typesafe-docs-drift/SKILL.md) | Rank where the docs portal disagrees with the NanoClaw code using the TypeSafe decision API: deterministic fact extraction, lexical section search, contradicts / covers / staleness per pair, DRIFT / MISSING / UNSURE / OK report; offline fixture replay; nothing written. |
| [typesafe-triage](skills/typesafe-triage/SKILL.md) | Dry-run label triage of NanoClaw issues and PRs with the TypeSafe decision API: confidence-gated area, kind, priority and triage proposals compared with existing labels; offline fixture replay; nothing written to GitHub. |
| [shared-terminal](skills/shared-terminal/SKILL.md) | One local browser terminal shared by the human and agent for supervised installers and interactive handoffs on macOS or Linux. |

Each skill follows the [Agent Skills format](https://agentskills.io). Use it with
Expand Down
33 changes: 29 additions & 4 deletions docs/skills-catalog.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# NanoClaw OSS Dev Tools: skill catalog

Verified: **2026-09-17**. This checkout contains **8 skills**, with plugin
manifest version **0.12.0** (development, unreleased). Three drive headless setup steps; `e2e-wizard` and
Verified: **2026-09-24**. This checkout contains **9 skills**, with plugin
manifest version **0.13.0** (development, unreleased). Three drive headless setup steps; `e2e-wizard` and
`e2e-windows` drive the public interactive wizard. The shared `e2e-triage` skill
researches unexpected failures and prepares reporting recommendations. The
workflows and their qualifications are listed separately below. `shared-terminal`
provides a local terminal for human and agent handoffs. `typesafe-docs-drift`
ranks where the docs portal disagrees with the code through the TypeSafe
decision API and writes nothing.
decision API and writes nothing. `typesafe-triage` previews confidence-gated
issue and PR labels from the TypeSafe decision API without writing to GitHub.

Installed skill copies must be updated separately, and the manifest version
does not imply a tagged GitHub release.
Expand All @@ -34,6 +35,7 @@ attempt exposed a harness tool-path bug and remains a retained failure. See the
| [e2e-windows](../skills/e2e-windows/SKILL.md) | Fresh Windows WSL2 distribution using the local Docker Desktop Linux engine. | Public wizard passed again on 2026-09-14 at current NanoClaw `main`; terminal-close and post-Windows-reboot inference also passed with locally validated sanitized evidence. | WSL-only restart still left the service/socket unavailable, and Docker Desktop did not start automatically after Windows reboot. |
| [e2e-triage](../skills/e2e-triage/SKILL.md) | Agent workflow on the operator machine, using retained evidence and current upstream trackers. | Replayed retained Windows CA failure against live issues/PRs and the current NanoClaw bug form on 2026-09-12. | Instruction-driven; direct shell runs do not invoke it. No public submission was performed during validation. |
| [typesafe-docs-drift](../skills/typesafe-docs-drift/SKILL.md) | Ranks disagreements between a NanoClaw checkout and the nanoclaw-docs portal through the TypeSafe System One API: deterministic facts, lexical candidate sections, one fan-out request per pair, gated DRIFT / MISSING / UNSURE / OK verdicts. | Offline fixture replay and mocked-transport tests; one live run on 2026-09-16 (142 facts, 426 requests, 71.5 s: DRIFT 7, MISSING 1, UNSURE 11, OK 123; see [typesafe-docs-drift.md](typesafe-docs-drift.md)). | Detection only; candidate recall is lexical top-3; fixture answers are hand-written. |
| [typesafe-triage](../skills/typesafe-triage/SKILL.md) | Dry-run label triage of open nanocoai/nanoclaw issues and PRs through the TypeSafe System One API, with a confidence gate and comparison against existing labels. | Offline fixture replay and mocked-transport tests only; no live TypeSafe call has been recorded yet. | Live agreement rates are unmeasured; the fixture answers are hand-written. It proposes labels only and never applies them. |
| [shared-terminal](../skills/shared-terminal/SKILL.md) | One local PTY with browser and agent control, for supervised interactive work. | macOS browser typing, interactive prompts, agent/human handoff and shutdown passed; real HTTP/PTY tests passed. | Native Windows, WSL and browser forwarding are unqualified. |

The shared baseline for the three headless skills tested NanoClaw
Expand Down Expand Up @@ -312,7 +314,7 @@ run inside the dedicated WSL2 distribution from the NanoClaw checkout.

**Entry point:** [SKILL.md](../skills/e2e-triage/SKILL.md), invoked by the testing
agent after an unexpected failure or directly against a retained run. Install it
alongside the E2E skill; the plugin includes all eight. This workflow adds no
alongside the E2E skill; the plugin includes all nine. This workflow adds no
runtime or GitHub dependency to the shell/Python test drivers.

- Captures distinct failures without rewriting installation/recovery outcomes.
Expand Down Expand Up @@ -367,6 +369,29 @@ Validation: fixture replay through the full pipeline and the mocked tests in
`tests/test_typesafe_docs_drift.py`, plus one live run on 2026-09-16 whose
sanitized summary is recorded on the detail page.

## typesafe-triage

**Entry point:** [typesafe-triage.py](../skills/typesafe-triage/scripts/typesafe-triage.py),
run from any directory; it needs no NanoClaw checkout.

- Needs Python 3.10+ and, for live mode, an authenticated `gh` plus
`TYPESAFE_API_KEY` exported in the shell. Standard library only; no SDK.
- Fetches the 30 most recently updated open issues and 20 open PRs read-only
(`gh api`), sends one fan-out request per item (area, kind, priority, and
`needs_repro` for issues or `pr_ready` for PRs), and prints proposed labels
with confidence, the existing labels and an AGREE / DISAGREE / NEW verdict.
- Gates on confidence (area and kind 0.6, priority 0.8, yes/no 0.7, all
overridable) and proposes `triage/unresolved` below the gate instead of guessing.
- `--fixture` replays recorded items and responses offline; the shipped fixture
holds five real items fetched on 2026-09-16 with hand-written answers.
`--record` saves a live run in the same format. Raw answers go to a gitignored
output directory.
- Writes nothing to GitHub. Details: [typesafe-triage.md](typesafe-triage.md).

Validation is offline only: fixture replay through the full pipeline and the
mocked-transport tests in `tests/test_typesafe_triage.py`. No live TypeSafe
request has been made from this repository yet.

## Installation and maintenance

Use the [README installation instructions](../README.md#1-install-the-skill).
Expand Down
92 changes: 92 additions & 0 deletions docs/typesafe-triage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# TypeSafe triage dry run

`skills/typesafe-triage/scripts/typesafe-triage.py` previews how TypeSafe's
System One model (`jev-latest`) would label open NanoClaw issues and pull
requests. It never writes to GitHub. This page records the questions, the
confidence gate, where the key comes from, and how to run and replay it.

## What one request contains

Every item gets exactly one `POST https://api.typesafe.ai/v1/systemone` with a
structured `state` and four questions (speculative fan-out: all questions are
answered in parallel and code decides which answers matter).

State: `repository`, `item_type`, `number`, `title`, `author_association`,
`body` (first 12,000 characters). Pull requests add `draft`, `changed_files`
(first 80 paths), `changed_file_count` and `template` (whether the
`nanoclaw-pr-template:v2` marker is present and which of its eight sections are
`filled`, `empty` or `missing`). Existing labels are deliberately not sent.

| Question | Type | Options and outcome |
|---|---|---|
| `area` | choice | The 16 `area/*` labels; one line of rubric each, derived from NanoClaw's CLAUDE.md, docs and `.github/labeler.yml` path mapping. |
| `kind` | choice | `kind/bug`, `kind/feature`, `kind/documentation`, `kind/question`, `kind/security`, `kind/hardening`, `kind/cleanup`, using the label descriptions. |
| `priority` | score | Four ordered levels with concrete descriptions; the score rounds to `priority/low`, `medium`, `high` or `critical`. |
| `needs_repro` (issues) | noul | Yes means the report lacks reproduction steps or a concrete failing case, proposing `triage/needs-repro`. Skipped when the top `kind` is not `kind/bug` or `kind/security`. |
| `pr_ready` (PRs) | noul | Yes means the template is filled, tests or a reason for none are stated and the diff matches the title, proposing `Status: Needs Review`; a confident no proposes `triage/needs-author`. |

## Confidence gate

Choice and score answers carry `confidence` (0 to 1) derived from their
probability distribution. Noul answers are a probability of yes.

| Question | Default gate | Flag |
|---|---|---|
| `area`, `kind` | confidence >= 0.6 | `--area-threshold`, `--kind-threshold` |
| `priority` | confidence >= 0.6 | `--priority-threshold` |
| `needs_repro`, `pr_ready` | yes if p >= 0.7, no if p <= 0.3, otherwise uncertain | `--noul-threshold` |

Below the gate the script proposes `triage/unresolved` and shows the model's top
answer in parentheses instead of guessing. Priority is maintainer-set in NanoClaw,
which is why its gate is the strictest.

Each proposal is compared with the item's existing labels: `AGREE` when the label
is present, `DISAGREE` when a different label of the same `area/`, `kind/` or
`priority/` family is present, `NEW` when the family is absent. The summary gives
the agreement rate per question over compared items, the count of items with a
gated question, token usage and wall time.

## The key

Live mode reads `TYPESAFE_API_KEY` from the environment when the first request
is built. If it is unset the script exits with status 2 and a message; it does
not look for a file. Export it for the shell session only, for example from a
password manager. Never commit it, never put it in `.env` or a fixture, and never
paste it into an issue. The script does not log request headers, and the saved
JSON contains only items, responses and decisions.

## Run

Offline, using the shipped fixture (five real nanocoai/nanoclaw items fetched
read-only on 2026-09-16 with hand-written answers in the documented shapes):

```bash
python3 skills/typesafe-triage/scripts/typesafe-triage.py \
--fixture skills/typesafe-triage/fixtures/nanoclaw-sample.json
```

Live dry run (30 most recently updated open issues, 20 open PRs):

```bash
export TYPESAFE_API_KEY=...
python3 skills/typesafe-triage/scripts/typesafe-triage.py --record /tmp/triage-record.json
```

`--record` writes items plus raw responses in the fixture format so the run can
be replayed with `--fixture` without spending tokens. Raw answers for every run
are saved as `triage-<UTC stamp>.json` under `skills/typesafe-triage/output/`
(gitignored) or `--output-dir`; `--json` prints the same payload to stdout.
`--repo`, `--issues` and `--prs` change the target and sample size. The issues
endpoint interleaves pull requests, so the fetch pages until it has enough real
issues. Requests run one at a time; if one fails after retries (429 and 529 are
retried with backoff), the completed items are still saved and printed, the
failing item is named in `partial`, and the exit status is 1.

## Tests

`tests/test_typesafe_triage.py` runs in the offline suite: question and request
shape, template-section detection, gate and verdict logic, `gh` output parsing
with a mocked runner, HTTP transport with a mocked opener (bearer header, retry
on 429/529, no retry on 422), fixture replay end to end, and a check that a key
in the environment never reaches stdout, stderr or the saved JSON. No test
contacts the network.
95 changes: 95 additions & 0 deletions skills/typesafe-triage/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
name: typesafe-triage
description: Dry-run label triage for nanocoai/nanoclaw issues and pull requests using the TypeSafe System One decision API. Proposes area, kind, priority and triage labels with confidence, compares them with the existing labels, and writes nothing to GitHub. Use to preview or evaluate automated triage, or to replay the offline fixture without a key.
license: MIT
---

# TypeSafe triage dry run

Fetch the most recently updated open issues and pull requests, ask TypeSafe one
fan-out request per item, gate every answer on confidence, and print proposed
labels next to the labels the item already carries. The script is read-only
towards GitHub. Applying labels is a separate, human decision.

Entry point: [typesafe-triage.py](scripts/typesafe-triage.py) (Python 3.10+,
standard library only). Offline fixture:
[nanoclaw-sample.json](fixtures/nanoclaw-sample.json). Details of the questions,
gate and output: [docs/typesafe-triage.md](../../docs/typesafe-triage.md).

## Sources this skill drives

- NanoClaw label taxonomy: `gh label list -R nanocoai/nanoclaw` (the `area/*`,
`kind/*`, `priority/*` and `triage/*` families and their descriptions).
- NanoClaw `CONTRIBUTING.md` (issue forms, "exactly one `area/*`", maintainer-only
priority, `triage/needs-repro` meaning) and `.github/labeler.yml` (path to area
mapping used for the area rubrics).
- NanoClaw `.github/PULL_REQUEST_TEMPLATE.md`, marker `nanoclaw-pr-template:v2`,
whose section headings the script checks for content.
- TypeSafe HTTP API: `POST https://api.typesafe.ai/v1/systemone`, model
`jev-latest`, question types `noul`, `choice`, `score`
([API reference](https://docs.typesafe.ai/api.md),
[confidence](https://docs.typesafe.ai/confidence.md),
[speculative fan-out](https://docs.typesafe.ai/patterns/fan-out.md)).

Re-check the rubrics when the label set or the labeler mapping changes.

## Prerequisites

- `gh` authenticated with read access to the target repository (live mode only).
- `TYPESAFE_API_KEY` exported in the shell (live mode only). The script reads it
from the environment at request time, never from a file, and never prints it.
Do not put the key in `.env`, a fixture, or any file inside a repository.

## Run

Offline demonstration, no key and no network:

```bash
python3 skills/typesafe-triage/scripts/typesafe-triage.py \
--fixture skills/typesafe-triage/fixtures/nanoclaw-sample.json
```

Live dry run against nanocoai/nanoclaw (30 issues, 20 PRs; nothing is written):

```bash
export TYPESAFE_API_KEY=... # from your password manager, this shell only
python3 skills/typesafe-triage/scripts/typesafe-triage.py --record /tmp/triage-record.json
```

`--record` saves the fetched items and raw responses so the same run can be
replayed later with `--fixture`. Raw answers for every run land in
`skills/typesafe-triage/output/` (gitignored) or `--output-dir`. Item bodies are
included there; keep the directory private.

Flags: `--repo`, `--issues`, `--prs`, `--area-threshold` (0.6),
`--kind-threshold` (0.6), `--priority-threshold` (0.6), `--noul-threshold` (0.7),
`--model`, `--timeout`, `--json`.

## Read the output

One row per proposal. `Verdict` compares the proposal with the existing labels:
`AGREE` (already present), `DISAGREE` (a different label from the same
`area/`, `kind/` or `priority/` family is present), `NEW` (that family is
absent), `SKIP` (not applicable, for example `needs_repro` on a feature
request). Below the confidence gate the proposal is `triage/unresolved` with the
model's top answer in parentheses, so a maintainer sees what it leaned towards
without the script guessing.

The summary reports agreement per question over compared items only
(agree / (agree + disagree)), the number of items with at least one gated
question, token usage and wall time.

## Limits

- Dry run only. There is no flag that writes labels, comments or anything else.
- The fixture's answers are hand-written in the documented response shapes to
exercise the pipeline; they are not evidence of model accuracy. Evaluate
accuracy with a live `--record` run and the agreement summary.
- `priority/*` is maintainer-set. The default 0.6 gate comes from the first live
run on nanoclaw (50 items): at 0.8 it withheld 34 of 48 priority proposals, at
0.6 it withheld 13 with every fired proposal agreeing with the existing label,
and at 0.5 disagreements appeared.
- Existing labels are never sent to the model, so agreement is a fair comparison.
- Requests are sequential; 50 items take roughly a minute. A request that fails
after retries stops the run, but completed items are still saved and printed
(exit status 1, `partial` names the failing item).
Loading
Loading