Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-marketplace.json",
"name": "pascal",
"version": "0.1.2",
"version": "0.1.3",
"description": "Public Pascal workflows for MCP-capable agents.",
"owner": {
"name": "Pascal"
Expand All @@ -11,7 +11,7 @@
"name": "pascal-agent-skills",
"source": "./",
"description": "Create and inspect editable Pascal scenes and run bounded furniture footprint assessments.",
"version": "0.1.2",
"version": "0.1.3",
"category": "productivity",
"skills": ["./skills/pascal-3d", "./skills/furniture-fit"]
}
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json.schemastore.org/claude-code-plugin.json",
"name": "pascal-agent-skills",
"displayName": "Pascal agent skills",
"version": "0.1.2",
"version": "0.1.3",
"description": "Create, inspect, validate, and assess furniture layouts in Pascal through MCP.",
"author": {
"name": "Pascal"
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pascal-agent-skills",
"version": "0.1.2",
"version": "0.1.3",
"description": "Create, inspect, validate, and assess furniture layouts in Pascal through MCP.",
"author": {
"name": "Pascal",
Expand Down
4 changes: 2 additions & 2 deletions scripts/validate-skills.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { fileURLToPath } from 'node:url'

const root = resolve(dirname(fileURLToPath(import.meta.url)), '..')
const skillNames = ['pascal-3d', 'furniture-fit'] as const
const skillVersions = { 'pascal-3d': '0.1.0', 'furniture-fit': '0.1.1' } as const
const pluginVersion = '0.1.2'
const skillVersions = { 'pascal-3d': '0.1.0', 'furniture-fit': '0.1.2' } as const
const pluginVersion = '0.1.3'
const failures: string[] = []

function fail(message: string) {
Expand Down
10 changes: 9 additions & 1 deletion skills/VALIDATION.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Skill package validation

Released plugin bundle version: **0.1.2**. `pascal-3d` skill metadata version: **0.1.0**. `furniture-fit` skill metadata version: **0.1.1**. Prepared September 8, 2026.
Bundle version: **0.1.3**. `pascal-3d` skill metadata version: **0.1.0**. `furniture-fit` skill metadata version: **0.1.2**. Prepared September 9, 2026.

## Bundle 0.1.3 validation

This release adds a fail-closed input gate for furniture assessments. When the request itself establishes that a decisive dimension, room scale, target, pose, or clearance is missing, the skill preserves the supplied facts and asks only for the blocking input instead of producing conditional fit thresholds. A minimal read-only scene lookup remains allowed when it can resolve that value from existing measured evidence; assessment and mutation calls remain blocked until the input is resolved.

The exact `furniture-fit/SKILL.md` bytes at SHA-256 `c5283ef5d593f7c8beb66d20d8131966305b24b27104398f42343498138a1bd4` passed one prospectively frozen three-case native Claude Fable 5.1 gate: both decisive-missing-input cases made zero Pascal MCP calls, and the complete-input control used the real read-only candidate collision path while preserving the graph hash, version, and export bytes. All three deterministic outcomes and all 12 separately judged semantic criteria passed without task retries. The semantic judge ran in a separate first-party Fable process whose receipt reported no tools, MCP servers, plugins, or tool calls. The prior three-case diagnostic with an ambient Codex MCP configuration remains a failed promotion gate and was not rescored or replaced.

The two setup references changed after that exact skill-body gate. Their release checks are separate: extracted Claude commands rejected unset and empty keys, preserved an existing synthetic key, stored the exact header in private user configuration, and were visible from two isolated working directories; extracted Codex commands stored only the `PASCAL_API_KEY` environment-variable name after explicit placeholder replacement. Package validation, strict Claude marketplace validation, and diff checks pass for the combined bundle. These setup checks do not turn the skill-body task receipt into a blanket whole-bundle native claim.

The 0.1.2 candidate strengthens height-evidence boundaries and keeps every geometry inspection within the explicitly requested project, level, and room. Local package and strict Claude marketplace validation pass. Candidate commit `cf729f1decbf9fda5c6e6bb9cd82e06156af9ea3` then passed one prospectively frozen 20-case native Claude gate through the managed CLI connector: 20/20 native tasks, deterministic assertions, host checks, semantic evidence checks, and graph/export nonmutation checks passed with no retries. Whole-response review of the purchase, delivery, and export-boundary cases also passed. Those skill and package-manifest bytes were merged to public `main` at `72d4451202e79bbbb22090016543874a7c2e9836` and installed successfully through five fresh Claude configurations, a clean skills.sh project install, and a clean isolated Codex Git marketplace install. These are synthetic task and package-installation results for the tested source; they do not establish physical furniture fit, general hosted-session continuity, adoption, or automatic skill routing. The `native-host-validation: source-hash-recorded-separately` metadata points to versioned evidence rather than promising a blanket pass.

Expand Down
8 changes: 5 additions & 3 deletions skills/furniture-fit/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ description: Assess whether furniture fits in a measured Pascal room or layout.
license: MIT
compatibility: Requires a Pascal MCP connection for verified scene checks. Can still produce an input-gap report when the scene or measurements are unavailable.
metadata:
version: "0.1.1"
source-reviewed: "2026-09-08"
version: "0.1.2"
source-reviewed: "2026-09-09"
native-host-validation: "source-hash-recorded-separately"
---

Expand All @@ -27,6 +27,8 @@ Collect or verify:

Reject zero, negative, non-finite, or ambiguous dimensions. Treat `"1,234"` as ambiguous until the user clarifies the decimal/thousands convention. If a photo, listing, or scan has no trustworthy scale, return `insufficient evidence` and name the minimum measurement needed. Do not infer product dimensions from appearance.

Validate the inputs needed for the requested conclusion before assessing fit. When the request itself already establishes that a decisive input—such as a dimension, room scale, target, pose, or explicit clearance—is missing, invalid, or ambiguous, stop with `insufficient evidence` before assessment or mutation calls. Preserve the valid values already supplied, identify only the blocking input or smallest blocking set, and ask only for the measurements or choices needed to continue. Do not calculate conditional fit thresholds, maximum allowable sizes, hypothetical clearances, height comparisons, or alternative poses while that decisive input is unresolved. If an existing Pascal scene might contain a measured value needed to resolve the input, use only the minimum read-only project or geometry lookup needed to find and verify that value and its provenance; if it remains unresolved, stop. Do not call candidate, collision, placement, validation, or save tools, and do not mutate the project. A preliminary calculation is appropriate only when all inputs decisive for that calculation are exact and the connected release lacks the read-only candidate capability; it is not a substitute for missing measurements.

Before calling tools, record the user's constraints: item width, height, depth, original unit and meter conversion, target level/zone, position, rotations, and required clearance. Re-read the request when filling this record; scene metadata and examples cannot replace supplied values. Preserve known dimensions when asking for a missing one. Never replace a supplied height with a placeholder just because the footprint test ignores height.

Treat numeric `level.height`, `zone.ceilingHeight`, wall height, asset labels, and imported metadata as nominal unless their provenance records a measurement of the clear floor-to-obstacle height over the exact proposed footprint. A categorical height pass or failure requires either that user-supplied measurement or modeled ceiling, soffit, sill, railing, or obstacle geometry whose recorded measurement provenance and spatial extent cover the tested pose. Merely having a ceiling-shaped node, a template default, or a numeric metadata field is not measured evidence. A nominal value can identify a possible mismatch worth measuring, but it cannot by itself support a categorical height pass or failure.
Expand Down Expand Up @@ -72,7 +74,7 @@ Use this as a transparent cross-check of the tool-backed pose, with radians in s

Prefer a server tool that accepts the supplied candidate dimensions if the connected release advertises one. Inspect its schema before calling it. In the current repository source, `check_collisions.candidate` accepts an ID, name, level ID, `[width, height, depth]`, position, Y rotation, and optional source identifiers. It creates an in-memory prospective item for that call and never adds it to the scene. Confirm `candidateItemId` in the result, use its returned footprint and collision evidence, and assess room containment separately against the measured zone boundary.

Compare every candidate call against the recorded user constraints before executing it. Pass all supplied dimensions exactly after unit conversion, and pass the requested clearance rather than silently substituting zero. If a required candidate dimension is missing, ask only for that value or give a clearly preliminary planar calculation; do not invent a value to satisfy the schema. Check the returned source dimensions, pose, and clearance against the request before treating the result as evidence.
Compare every candidate call against the recorded user constraints before executing it. Pass all supplied dimensions exactly after unit conversion, and pass the requested clearance rather than silently substituting zero. If a required candidate dimension or scale is missing, follow the input gate above: use a minimal read-only scene lookup only when it can resolve the value from existing measured evidence; otherwise stop before assessment or mutation calls and ask only for the blocking value. Do not invent a value to satisfy the schema. Check the returned source dimensions, pose, and clearance against the request before treating the result as evidence.

`verify_scene` checks saved or active scene items, not this prospective candidate. Its clean result cannot pass the candidate's default spacing or door access. Mark those candidate rows `not checked` unless a separate check includes the candidate and the required geometry; identify that evidence explicitly. A candidate collision check at the requested gap supports that gap only.

Expand Down
13 changes: 13 additions & 0 deletions skills/furniture-fit/evals/evals.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@
"Labels the conclusion as a manual height-versus-clear-height comparison rather than a Pascal footprint-tool result.",
"Keeps the project unchanged."
]
},
{
"id": 8,
"prompt": "My measured Pascal room is 4.00 m wide by 3.00 m deep. The wardrobe is 1.80 m wide and 2.20 m tall, but its depth is missing. Check whether it fits centered in the room. This is read only. Do not infer a depth; request only the decisive missing measurement.",
"expected_output": "Stops with insufficient evidence, preserves the supplied dimensions and target, asks only for wardrobe depth, and does not calculate conditional fit thresholds or call assessment tools.",
"files": [],
"expectations": [
"Returns insufficient evidence because wardrobe depth is decisive for the requested footprint conclusion.",
"Preserves the supplied 1.80 m width, 2.20 m height, 4.00 m by 3.00 m room, centered pose, and read-only scope without substituting values.",
"Asks only for the wardrobe depth in a clear unit.",
"Does not state a maximum fitting depth, a conditional 'would fit' threshold, a height result, or an alternative pose while depth is missing.",
"Does not call candidate, collision, placement, validation, or save tools and does not mutate the project."
]
}
]
}
2 changes: 2 additions & 0 deletions skills/furniture-fit/examples/insufficient-evidence.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ Request the smallest decisive measurements:
2. Clear soffit height at the intended location.
3. Narrowest clear width and height along the entry route, including tight turns.

Stop there. Do not add conditional maximum-size, fit, height, or route thresholds while those decisive measurements are missing.

Do not create a placeholder with guessed dimensions and report it as a verified fit.
16 changes: 10 additions & 6 deletions skills/furniture-fit/references/setup.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Connect Pascal for a furniture-fit assessment

Source and public-documentation review date: 2026-09-08. Native task results are recorded separately with the evaluated source hash; source review alone does not prove every host or published runtime works.
Source and public-documentation review date: 2026-09-09. Native task results are recorded separately with the evaluated source hash; source review alone does not prove every host or published runtime works.

## Local project

Expand Down Expand Up @@ -47,30 +47,34 @@ Use only one active agent client with each local CLI service. The standalone HTT

## Existing hosted project

Create an API key in Pascal Settings for the same user or organization that owns the target project. Store it in the host's credential facility or an environment variable. The hosted Streamable HTTP endpoint is:
Create an API key in Pascal Settings for the same user or organization that owns the target project. Set `PASCAL_API_KEY` to that key without printing it. If you assign it in a shell command, avoid or remove that command from shell history. The hosted Streamable HTTP endpoint is:

```text
https://editor.pascal.app/api/mcp
```

Codex CLI:

Replace `paste_key_here` with the API key before running this example.

```bash
export PASCAL_API_KEY="paste_key_here"
codex mcp add pascal \
--url https://editor.pascal.app/api/mcp \
--bearer-token-env-var PASCAL_API_KEY
```

Codex stores the environment-variable name, not its value. Set `PASCAL_API_KEY` again in each new terminal before starting Codex, or supply it through the user's existing shell or secret-manager configuration.

Claude Code:

```bash
export PASCAL_API_KEY="paste_key_here"
claude mcp add --scope project --transport http pascal https://editor.pascal.app/api/mcp \
--header 'Authorization: Bearer ${PASCAL_API_KEY}'
: "${PASCAL_API_KEY:?Set PASCAL_API_KEY to the apiKey returned by Pascal}" && \
claude mcp add --scope user --transport http pascal https://editor.pascal.app/api/mcp \
--header "Authorization: Bearer $PASCAL_API_KEY"
```

The single quotes preserve the environment reference in `.mcp.json`; the variable must be available when Claude starts. Never paste the key into a project file, report, prompt, screenshot, or URL.
The guard exits before changing Claude Code configuration when the variable is unset or empty. Claude Code expands the variable during registration and stores the static Authorization header, including the key, in its private user configuration. The connection is then available in all Claude Code projects for that user. Keep the configuration private; use `--scope local` instead when the connection should remain local to the current project. Never paste the key into a project file, report, prompt, screenshot, or URL.

## Separate autonomous workspace

Expand Down
18 changes: 12 additions & 6 deletions skills/pascal-3d/references/setup.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Pascal connection and credential setup

Source and public-documentation review date: 2026-09-08. Native task results are recorded separately with the evaluated source hash; source review alone does not prove every host or published runtime works.
Source and public-documentation review date: 2026-09-09. Native task results are recorded separately with the evaluated source hash; source review alone does not prove every host or published runtime works.

Choose one path. Do not switch storage boundaries without the user's instruction.

Expand Down Expand Up @@ -82,26 +82,32 @@ Use the hosted endpoint when the user wants the agent to work in a Pascal accoun
https://editor.pascal.app/api/mcp
```

The user creates an API key in Pascal Settings and chooses the intended personal or organization workspace. Keep the key in an environment variable or the client's credential store.
The user creates an API key in Pascal Settings and chooses the intended personal or organization workspace. Set `PASCAL_API_KEY` to that key without printing it. If you assign it in a shell command, avoid or remove that command from shell history.

Codex CLI:

Replace `paste_key_here` with the API key before running this example.

```bash
export PASCAL_API_KEY="paste_key_here"
codex mcp add pascal \
--url https://editor.pascal.app/api/mcp \
--bearer-token-env-var PASCAL_API_KEY
```

Codex stores the environment-variable name, not its value. Set `PASCAL_API_KEY` again in each new terminal before starting Codex, or supply it through the user's existing shell or secret-manager configuration.

Claude Code:

```bash
export PASCAL_API_KEY="paste_key_here"
claude mcp add --scope project --transport http pascal https://editor.pascal.app/api/mcp \
--header 'Authorization: Bearer ${PASCAL_API_KEY}'
: "${PASCAL_API_KEY:?Set PASCAL_API_KEY to the apiKey returned by Pascal}" && \
claude mcp add --scope user --transport http pascal https://editor.pascal.app/api/mcp \
--header "Authorization: Bearer $PASCAL_API_KEY"
```

The single quotes preserve the environment reference in `.mcp.json`; the variable must be available when Claude starts. For JSON-based clients, prefer their environment-variable or secret interpolation rather than a literal key:
The guard exits before changing Claude Code configuration when the variable is unset or empty. Claude Code expands the variable during registration and stores the static Authorization header, including the key, in its private user configuration. The connection is then available in all Claude Code projects for that user. Keep the configuration private; use `--scope local` instead when the connection should remain local to the current project.

For other JSON-based clients, prefer their supported environment-variable or secret interpolation rather than a literal key:

```json
{
Expand Down
Loading