@aefree/pi-plastic 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +8 -7
- package/extensions/bash-cm-diff-guard.ts +2 -1
- package/extensions/file-discovery-filter.ts +67 -0
- package/index.ts +12 -0
- package/package.json +7 -8
- package/skills/_shared/references/conventional-commits.md +198 -198
- package/skills/using-plastic/SKILL.md +2 -2
- package/skills/using-plastic/references/changeset-operations.md +2 -1
- package/skills/using-plastic/references/code-review-creation.md +30 -30
- package/skills/using-plastic/references/integration.md +2 -1
- package/skills/using-plastic/references/quick-reference.md +2 -1
- package/skills/using-plastic/references/resources.md +7 -7
- package/skills/using-plastic/references/reviewing-changes.md +4 -3
- package/skills/using-plastic/references/shelving.md +25 -25
- package/skills/using-plastic/references/troubleshooting.md +2 -1
- package/skills/using-plastic/references/workspaces.md +33 -33
- package/src/file-discovery-filter-rendezvous.ts +104 -0
- package/src/{repository-search-provider.ts → file-discovery-filter.ts} +21 -17
- package/src/plastic-core.ts +438 -152
- package/src/plastic-tool-loading.ts +2 -1
- package/evals/tool-loading/README.md +0 -38
- package/evals/tool-loading/RESULTS.md +0 -57
- package/evals/tool-loading/baseline.json +0 -34
- package/evals/tool-loading/cases.json +0 -70
- package/evals/tool-loading/config.json +0 -19
- package/evals/tool-loading/mutation-guard.ts +0 -30
- package/evals/tool-loading/provider-capture.ts +0 -22
- package/evals/tool-loading/results/.gitignore +0 -3
- package/evals/tool-loading/run-eval.ts +0 -372
- package/extensions/repository-search-provider.ts +0 -66
- package/tests/bash-cm-diff-guard-validation.ts +0 -55
- package/tests/fixtures/plastic.selector +0 -3
- package/tests/fixtures/status-compact.txt +0 -1
- package/tests/fixtures/status-normal.txt +0 -1
- package/tests/packed-copy-owner-conflict.test.ts +0 -28
- package/tests/pi-tool-harness.ts +0 -116
- package/tests/plastic-branch-create-live.test.ts +0 -78
- package/tests/plastic-branch-query.test.ts +0 -26
- package/tests/plastic-branch-status.test.ts +0 -241
- package/tests/plastic-checkin-path-resolution.ts +0 -219
- package/tests/plastic-constrained-sampling.test.ts +0 -77
- package/tests/plastic-diff-workflow.test.ts +0 -86
- package/tests/plastic-dynamic-tool-loading.test.ts +0 -224
- package/tests/plastic-extension-registration.test.ts +0 -34
- package/tests/plastic-live-smoke.test.ts +0 -37
- package/tests/plastic-mutation-execution.test.ts +0 -61
- package/tests/plastic-patch-command.test.ts +0 -118
- package/tests/plastic-process-lifecycle.test.ts +0 -148
- package/tests/plastic-tool-rendering.test.ts +0 -16
- package/tests/plastic-tool-validation.ts +0 -153
- package/tests/plastic-workspace.test.ts +0 -62
- package/tests/repository-search-provider-registration.test.ts +0 -37
- package/tests/repository-search-provider.test.ts +0 -27
|
@@ -27,7 +27,8 @@ export const PLASTIC_SEARCH_CATALOG: readonly PlasticSearchCatalogEntry[] = [
|
|
|
27
27
|
{ name: "plastic_undo", aliases: ["undo changes", "revert changes", "discard changes"], tags: ["changes", "mutation", "destructive"], guidance: ["Confirm the exact paths before discarding pending changes."] },
|
|
28
28
|
{ name: "plastic_resolveDeleteChangeConflict", aliases: ["resolve delete conflict", "deleted conflict"], tags: ["merge", "conflict", "resolution"], guidance: ["Inspect the conflict and choose whether files should remain on disk before resolving it."] },
|
|
29
29
|
{ name: "plastic_patch", aliases: ["patch", "generate patch", "review patch"], tags: ["diff", "patch", "export"], guidance: ["Inspect generated patches before sharing because they can include source, paths, or secrets."] },
|
|
30
|
-
{ name: "plastic_diffFile", aliases: ["diff", "diff file", "file diff", "
|
|
30
|
+
{ name: "plastic_diffFile", aliases: ["diff", "diff file", "file diff", "compare one file", "compare file"], tags: ["diff", "file", "workspace", "inspect"], guidance: ["For one workspace file, pass path and omit revision; use a documented changeset, branch, label, file-qualified, or global revision only when needed."] },
|
|
31
|
+
{ name: "plastic_workspaceDiff", aliases: ["workspace diff", "pending review", "review pending changes", "review workspace changes", "diff pending files"], tags: ["diff", "workspace", "review", "inspect"], guidance: ["For pending-change review, runs status once and returns bounded per-file outcomes. Private files are excluded unless explicitly selected or includePrivate=true."] },
|
|
31
32
|
{ name: "plastic_diffRevisions", aliases: ["diff revisions", "compare revisions", "revision diff"], tags: ["diff", "revision", "inspect"], guidance: ["Use this only for two explicit file-qualified revision specifications."] },
|
|
32
33
|
{ name: "plastic_branchCreate", aliases: ["create branch", "new branch"], tags: ["branch", "mutation", "workflow"], guidance: ["Create normal work branches beneath an intended parent, which may differ from the loaded branch. Use allowRootBranch only for intentional top-level branches."] },
|
|
33
34
|
{ name: "plastic_switchBranch", aliases: ["switch branch", "checkout branch", "change branch"], tags: ["branch", "workspace", "mutation"], guidance: ["Check pending changes and choose how to handle them before switching branches."] },
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Dynamic tool-loading behavioral eval
|
|
2
|
-
|
|
3
|
-
This package-local eval compares `all-active`, `balanced`, and `loader-only` Plastic tool-loading modes through fresh Pi 0.83 JSON subprocesses. It is intentionally **not** a skill eval: skills, prompt templates, built-in tools, discovered extensions, context files, and sessions are disabled.
|
|
4
|
-
|
|
5
|
-
## What it measures
|
|
6
|
-
|
|
7
|
-
- Required Plastic tool calls for status, branch listing, read-only switch/checkin preflight, compound branch list + `/main` verification, no-operation, ambiguous branch discovery, and two implicit contextual discovery prompts (inspect branches; find code reviews) that name neither the loader nor the target public tool.
|
|
8
|
-
- Loader behavior: exactly one `plastic_tool_search` only when a required tool is initially deferred; none for all-active, balanced cases whose target is already active, or the negative case. Whenever a loader is expected, the runner requires its activation result to be exactly the case's smallest sufficient deferred target set.
|
|
9
|
-
- Tool errors, assistant errors, call/output/time bounds, maximum four activation results, and no destructive activation in negative or ambiguous discovery cases. An eval-only extension blocks every destructive Plastic call unless that tool's registered schema supports `preflight` and the call supplies `preflight: true`.
|
|
10
|
-
- JSONL events, assistant usage/cache totals, wall time, initial provider `tools` serialization size, and native `tool_search_call` / `tool_search_output` markers when Pi/provider payloads expose them.
|
|
11
|
-
|
|
12
|
-
`baseline.json` preserves the legacy 29-tool measurement for comparison. The current all-active mode omits the loader and exposes `28 / 21071` after withholding workspace creation; balanced records `3 / 2133` (89.93% legacy reduction), and loader-only records `1 / 1121` (94.71%). The loader's prompt metadata is 278 characters; the untouched legacy baseline has none.
|
|
13
|
-
|
|
14
|
-
## Run
|
|
15
|
-
|
|
16
|
-
A live run requires an explicit approved model and **both** sandbox attestations. `PI_PLASTIC_EVAL_SANDBOX` must resolve to a dedicated workspace containing `.pi-plastic-eval-sandbox` whose complete, exact UTF-8 content is `pi-plastic-eval-sandbox` followed by one LF newline (no other bytes):
|
|
17
|
-
|
|
18
|
-
```text
|
|
19
|
-
pi-plastic-eval-sandbox
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
For example, create the marker with `printf 'pi-plastic-eval-sandbox\n' > /absolute/path/to/sandbox/.pi-plastic-eval-sandbox`. Also set `PI_PLASTIC_EVAL_ALLOW=dedicated-sandbox`; this explicit opt-in prevents accidentally targeting an ordinary workspace. Dry runs validate configuration and do **not** require either attestation.
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
PI_PLASTIC_EVAL_SANDBOX=/absolute/path/to/sandbox PI_PLASTIC_EVAL_ALLOW=dedicated-sandbox npm run eval:tool-loading -- --model openai-codex/gpt-5.6-luna
|
|
26
|
-
PI_PLASTIC_EVAL_SANDBOX=/absolute/path/to/sandbox PI_PLASTIC_EVAL_ALLOW=dedicated-sandbox npm run eval:tool-loading -- --model openai-codex/gpt-5.6-terra:medium --condition balanced --cases branch-listing,compound-list-branches-verify-main --trials 2
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Only `openai-codex/gpt-5.6-(luna|terra|sol)` with an optional supported thinking level such as `:medium` is accepted. Trials are sequential and bounded to 1–5. Never target an ordinary production workspace.
|
|
30
|
-
|
|
31
|
-
Validate the configuration without calling a model:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
npm run eval:tool-loading -- --dry-run
|
|
35
|
-
npm run eval:tool-loading -- --help
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Each trial writes provider payloads only to a unique system-temp capture file, never stdout. The runner deletes raw captures by default. Pass `--keep` only when you explicitly need those sensitive raw payloads. Sanitized timestamped summaries are written to ignored `results/`; use `--include-events` to include event type/tool-name crumbs only.
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Dynamic tool-loading pilot results
|
|
2
|
-
|
|
3
|
-
Date: 2026-07-25
|
|
4
|
-
Package: `@aefree/pi-plastic`
|
|
5
|
-
Pi: 0.82.0
|
|
6
|
-
Model: `openai-codex/gpt-5.6-terra:medium`
|
|
7
|
-
Sandbox: dedicated `plastic-tool-sandbox` repository
|
|
8
|
-
|
|
9
|
-
## Decision
|
|
10
|
-
|
|
11
|
-
The Plastic pilot passes its rollout criteria. Keep the balanced initial set as the production default: `plastic_tool_search`, `plastic_status`, and `plastic_currentBranch`.
|
|
12
|
-
|
|
13
|
-
- Existing 29 public Plastic tools retain their names and behavior; the loader is additive.
|
|
14
|
-
- Balanced public metadata is 2,117 serialized characters versus the untouched 21,192-character legacy baseline, a 90.01% reduction.
|
|
15
|
-
- Stable live provider payloads contained 1,908 serialized initial tool characters in balanced mode versus 22,120 in the 29-tool legacy all-active mode, a 91.37% reduction.
|
|
16
|
-
- A deferred capability added exactly one loader call/provider round trip and no repeated loader call after activation.
|
|
17
|
-
- Native OpenAI deferred-loading markers (`tool_search_call` and `tool_search_output`) appeared in every deferred GPT-5.6 case and were absent when no loader call was expected.
|
|
18
|
-
- Core outcomes, preflight argument checks, negative controls, and ambiguous branch discovery passed.
|
|
19
|
-
|
|
20
|
-
## Behavioral evidence
|
|
21
|
-
|
|
22
|
-
The final expanded diagnostic matrix passed 27/27 trials: nine explicit, implicit, contextual, ambiguous, compound, preflight, and negative cases under all-active, balanced, and loader-only conditions. Five stable status, branch, switch-preflight, checkin-preflight, and compound branch cases passed 45/45 trials over three repetitions per condition. A focused three-trial loader-only regression for contextual branch discovery also passed 3/3 after plural/domain query coverage was added.
|
|
23
|
-
|
|
24
|
-
Stable-trial measurements:
|
|
25
|
-
|
|
26
|
-
| Condition | Pass | Initial provider tool chars | Median wall time | Mean wall time | Mean reported total tokens | Mean tool calls |
|
|
27
|
-
|---|---:|---:|---:|---:|---:|---:|
|
|
28
|
-
| all-active | 15/15 | 22,120 | 8.78 s | 9.39 s | 7,180 | 1.20 |
|
|
29
|
-
| balanced | 15/15 | 1,908 | 10.50 s | 10.41 s | 3,295 | 2.00 |
|
|
30
|
-
| loader-only | 15/15 | 832 | 10.23 s | 10.84 s | 3,183 | 2.20 |
|
|
31
|
-
|
|
32
|
-
The balanced median added about 1.73 seconds (19.7%) in these short cases while reducing initial provider tool serialization by 91.37% and mean reported total tokens by about 54%. Mean provider requests were 2.0 all-active, 2.8 balanced, and 3.0 loader-only; deferred cases account for the accepted first-use loader request, while balanced status remained immediate. Results remain separate because cache reads, input tokens, wall time, and provider requests have different cost/latency implications.
|
|
33
|
-
|
|
34
|
-
The first diagnostic attempt used a 24,000-character JSONL capture bound and terminated normal Pi event streams before their follow-up tool turn. Raising the bounded capture limit to 2 MiB corrected the harness; no package behavior changed for the passing diagnostic and stable runs. Final live runs also required a sandbox marker, an explicit authorization environment value, and an eval-only guard that blocked mutation-capable tools unless the tool supported and received `preflight: true`.
|
|
35
|
-
|
|
36
|
-
## Session and compatibility evidence
|
|
37
|
-
|
|
38
|
-
A persisted loader-only session first called `plastic_tool_search` and `plastic_branchList`. Its tool result stored `addedToolNames: ["plastic_branchList"]`. A fresh Pi process resumed that session, restored `plastic_branchList`, called it directly, and made no second loader call.
|
|
39
|
-
|
|
40
|
-
Package harness coverage also verifies additive activation without Pi 0.82 `sourceInfo`, representing older/fallback active-list behavior. Pi/provider fallback serialization itself is owned by Pi; this package does not claim a live non-GPT-5.6 provider test.
|
|
41
|
-
|
|
42
|
-
## Sandbox mutation evidence
|
|
43
|
-
|
|
44
|
-
The dedicated sandbox was used for real branch, changeset, shelveset, review, merge, conflict-signal, and cleanup operations:
|
|
45
|
-
|
|
46
|
-
- Created and switched to disposable branch `/dynamic-tool-loading-eval-20260725-1538`.
|
|
47
|
-
- Added a synthetic fixture and created disposable changeset `cs:4`.
|
|
48
|
-
- Created, listed, previewed/applied, undid, and deleted shelveset `sh:2`.
|
|
49
|
-
- Created, found, updated, and deleted code review `21`.
|
|
50
|
-
- Attempted a merge to `/main`; Plastic reported an evil-twin directory conflict before establishing merge state. Explicit source finalization also stopped on that directory conflict, demonstrating the existing safe failure signal rather than silently checking in.
|
|
51
|
-
- Deleted the disposable branch and changeset after the stopped merge.
|
|
52
|
-
|
|
53
|
-
Final verification found `/main` active, no pending or merge state, and no remaining test branch, shelveset, or review. The private `.pi-plastic-eval-sandbox` attestation marker was removed after the eval; future guarded runs must recreate it deliberately. Workspace creation was not exercised because the package exposes create/list but no paired workspace-delete tool; leaving an account-level test workspace would not improve loader evidence.
|
|
54
|
-
|
|
55
|
-
## Scope
|
|
56
|
-
|
|
57
|
-
This result covers the `pi-plastic` pilot only. The recorded seven-case live matrix predates the current two implicit contextual discovery cases, exact smallest-sufficient activation assertion, eval-only preflight mutation guard, and marker/authorization sandbox attestations; no live re-run is implied by those later harness hardenings. Future live runs require `PI_PLASTIC_EVAL_SANDBOX` to contain the documented `.pi-plastic-eval-sandbox` marker and `PI_PLASTIC_EVAL_ALLOW=dedicated-sandbox`. It does not authorize package publishing or version changes, and it does not begin the separate Codecks guidance design or any skill evaluation.
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schemaVersion": 1,
|
|
3
|
-
"measurement": "serializedSchemaChars is JSON.stringify of public registered tool metadata (name, description, parameters, prompt metadata, constrainedSampling); estimated tokens are chars / 4 rounded up. Live provider payload tool serialization is recorded separately by the eval runner.",
|
|
4
|
-
"legacyBaseline": {
|
|
5
|
-
"label": "untouched legacy public Plastic tools",
|
|
6
|
-
"toolCount": 29,
|
|
7
|
-
"serializedSchemaChars": 21192,
|
|
8
|
-
"estimatedTokens": 5298,
|
|
9
|
-
"promptMetadataChars": 0
|
|
10
|
-
},
|
|
11
|
-
"implementedConditions": {
|
|
12
|
-
"all-active": {
|
|
13
|
-
"toolCount": 28,
|
|
14
|
-
"serializedSchemaChars": 21071,
|
|
15
|
-
"estimatedTokens": 5268,
|
|
16
|
-
"promptMetadataChars": 0,
|
|
17
|
-
"legacySchemaReductionPercent": 0.57
|
|
18
|
-
},
|
|
19
|
-
"balanced": {
|
|
20
|
-
"toolCount": 3,
|
|
21
|
-
"serializedSchemaChars": 2133,
|
|
22
|
-
"estimatedTokens": 534,
|
|
23
|
-
"promptMetadataChars": 278,
|
|
24
|
-
"legacySchemaReductionPercent": 89.93
|
|
25
|
-
},
|
|
26
|
-
"loader-only": {
|
|
27
|
-
"toolCount": 1,
|
|
28
|
-
"serializedSchemaChars": 1121,
|
|
29
|
-
"estimatedTokens": 281,
|
|
30
|
-
"promptMetadataChars": 278,
|
|
31
|
-
"legacySchemaReductionPercent": 94.71
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schemaVersion": 2,
|
|
3
|
-
"cases": [
|
|
4
|
-
{
|
|
5
|
-
"id": "status-inspection",
|
|
6
|
-
"prompt": "In the dedicated Plastic sandbox, inspect the workspace status now. Call plastic_status exactly once, do not call any other Plastic operation unless plastic_tool_search is required to make plastic_status available, then reply with a one-sentence status summary.",
|
|
7
|
-
"requiredTools": ["plastic_status"],
|
|
8
|
-
"minimalActivatedTools": ["plastic_status"],
|
|
9
|
-
"forbiddenTools": []
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"id": "branch-listing",
|
|
13
|
-
"prompt": "In the dedicated Plastic sandbox, list the available branches. Call plastic_branchList exactly once. If it is not active, first call plastic_tool_search exactly once and activate only plastic_branchList. Do not mutate the workspace; then give a short result.",
|
|
14
|
-
"requiredTools": ["plastic_branchList"],
|
|
15
|
-
"minimalActivatedTools": ["plastic_branchList"],
|
|
16
|
-
"forbiddenTools": []
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"id": "preflight-branch-switch",
|
|
20
|
-
"prompt": "Preview, but do not perform, switching the dedicated Plastic sandbox to /main. Call plastic_switchBranch exactly once with branch /main, pendingChanges cancel, preflight true, and the sandbox workdir. If the tool is inactive, first call plastic_tool_search exactly once to activate only plastic_switchBranch. Do not call any other Plastic operation, then summarize the preview.",
|
|
21
|
-
"requiredTools": ["plastic_switchBranch"],
|
|
22
|
-
"minimalActivatedTools": ["plastic_switchBranch"],
|
|
23
|
-
"requiredPreflightTools": ["plastic_switchBranch"],
|
|
24
|
-
"forbiddenTools": ["plastic_status", "plastic_currentBranch", "plastic_branchCreate", "plastic_merge"]
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"id": "preflight-checkin",
|
|
28
|
-
"prompt": "Preview, but do not perform, a checkin in the dedicated Plastic sandbox. Call plastic_checkin exactly once with message 'dynamic-loader eval preflight', preflight true, includeAll true, and the sandbox workdir. If the tool is inactive, first call plastic_tool_search exactly once to activate only plastic_checkin. Do not add, undo, or otherwise mutate anything, then summarize the preview.",
|
|
29
|
-
"requiredTools": ["plastic_checkin"],
|
|
30
|
-
"minimalActivatedTools": ["plastic_checkin"],
|
|
31
|
-
"requiredPreflightTools": ["plastic_checkin"],
|
|
32
|
-
"forbiddenTools": ["plastic_add", "plastic_undo"]
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"id": "compound-list-branches-verify-main",
|
|
36
|
-
"prompt": "In the dedicated Plastic sandbox, list branches and verify whether /main exists. Call plastic_branchList and plastic_branchExists once each; use /main as the branch-existence argument. If either is inactive, make exactly one plastic_tool_search call that activates both exact tools together. Do not mutate the workspace, then give a short answer.",
|
|
37
|
-
"requiredTools": ["plastic_branchList", "plastic_branchExists"],
|
|
38
|
-
"minimalActivatedTools": ["plastic_branchList", "plastic_branchExists"],
|
|
39
|
-
"forbiddenTools": []
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
"id": "negative-no-operation",
|
|
43
|
-
"prompt": "No Plastic operation is requested. Do not call plastic_tool_search or any plastic_* tool. Reply exactly: NO_OPERATION.",
|
|
44
|
-
"requiredTools": [],
|
|
45
|
-
"minimalActivatedTools": [],
|
|
46
|
-
"forbiddenTools": []
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"id": "ambiguous-branch-discovery",
|
|
50
|
-
"prompt": "In the dedicated Plastic sandbox, safely discover branch information for a later decision. Prefer a read-only branch listing and call plastic_branchList exactly once. If it is inactive, call plastic_tool_search exactly once with a branch discovery request and activate only read-only branch tools. Do not create, switch, merge, or delete branches; then give a short answer.",
|
|
51
|
-
"requiredTools": ["plastic_branchList"],
|
|
52
|
-
"minimalActivatedTools": ["plastic_branchList"],
|
|
53
|
-
"forbiddenTools": ["plastic_branchCreate", "plastic_switchBranch", "plastic_merge", "plastic_mergeToBranch", "plastic_branchDelete"]
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"id": "contextual-branch-inspection",
|
|
57
|
-
"prompt": "Before choosing a branch for later work, inspect all available branches in the dedicated sandbox exactly once and give a short read-only summary. Use only the smallest sufficient capability; do not change anything.",
|
|
58
|
-
"requiredTools": ["plastic_branchList"],
|
|
59
|
-
"minimalActivatedTools": ["plastic_branchList"],
|
|
60
|
-
"forbiddenTools": ["plastic_branchCreate", "plastic_switchBranch", "plastic_merge", "plastic_mergeToBranch", "plastic_branchDelete"]
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"id": "contextual-review-discovery",
|
|
64
|
-
"prompt": "Before planning follow-up work, find the existing code reviews in the dedicated sandbox exactly once and summarize them briefly. Use only the smallest sufficient read-only capability; do not change anything.",
|
|
65
|
-
"requiredTools": ["plastic_codeReviewFind"],
|
|
66
|
-
"minimalActivatedTools": ["plastic_codeReviewFind"],
|
|
67
|
-
"forbiddenTools": ["plastic_codeReviewCreate", "plastic_codeReviewUpdate", "plastic_codeReviewDelete"]
|
|
68
|
-
}
|
|
69
|
-
]
|
|
70
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schemaVersion": 2,
|
|
3
|
-
"piVersionPrefix": "0.83.",
|
|
4
|
-
"sandboxCwdEnv": "PI_PLASTIC_EVAL_SANDBOX",
|
|
5
|
-
"sandboxMarkerFile": ".pi-plastic-eval-sandbox",
|
|
6
|
-
"sandboxMarkerContent": "pi-plastic-eval-sandbox\n",
|
|
7
|
-
"sandboxAuthorizationEnv": "PI_PLASTIC_EVAL_ALLOW",
|
|
8
|
-
"sandboxAuthorizationValue": "dedicated-sandbox",
|
|
9
|
-
"timeoutMs": 90000,
|
|
10
|
-
"maxToolCalls": 12,
|
|
11
|
-
"maxOutputChars": 2097152,
|
|
12
|
-
"conditions": ["all-active", "balanced", "loader-only"],
|
|
13
|
-
"destructiveTools": [
|
|
14
|
-
"plastic_add", "plastic_checkin", "plastic_undo", "plastic_resolveDeleteChangeConflict",
|
|
15
|
-
"plastic_branchCreate", "plastic_switchBranch", "plastic_merge", "plastic_mergeToBranch",
|
|
16
|
-
"plastic_finalizeMerge", "plastic_branchDelete", "plastic_shelvesetCreate", "plastic_shelvesetApply",
|
|
17
|
-
"plastic_shelvesetDelete", "plastic_codeReviewCreate", "plastic_codeReviewUpdate", "plastic_codeReviewDelete"
|
|
18
|
-
]
|
|
19
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Eval-only defense in depth. Live trials may exercise only Plastic operations
|
|
5
|
-
* that expose a preflight parameter and explicitly request that preview mode.
|
|
6
|
-
*/
|
|
7
|
-
const DESTRUCTIVE_PLASTIC_TOOLS = new Set([
|
|
8
|
-
"plastic_add", "plastic_checkin", "plastic_undo", "plastic_resolveDeleteChangeConflict",
|
|
9
|
-
"plastic_branchCreate", "plastic_switchBranch", "plastic_merge", "plastic_mergeToBranch",
|
|
10
|
-
"plastic_finalizeMerge", "plastic_branchDelete", "plastic_shelvesetCreate", "plastic_shelvesetApply",
|
|
11
|
-
"plastic_shelvesetDelete", "plastic_codeReviewCreate", "plastic_codeReviewUpdate", "plastic_codeReviewDelete",
|
|
12
|
-
]);
|
|
13
|
-
|
|
14
|
-
function supportsPreflight(parameters: unknown): boolean {
|
|
15
|
-
if (!parameters || typeof parameters !== "object") return false;
|
|
16
|
-
const properties = (parameters as { properties?: unknown }).properties;
|
|
17
|
-
return Boolean(properties && typeof properties === "object" && Object.prototype.hasOwnProperty.call(properties, "preflight"));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default function evalMutationGuard(pi: ExtensionAPI): void {
|
|
21
|
-
pi.on("tool_call", (event) => {
|
|
22
|
-
if (!DESTRUCTIVE_PLASTIC_TOOLS.has(event.toolName)) return;
|
|
23
|
-
const tool = pi.getAllTools().find((candidate) => candidate.name === event.toolName);
|
|
24
|
-
if (supportsPreflight(tool?.parameters) && event.input.preflight === true) return;
|
|
25
|
-
return {
|
|
26
|
-
block: true,
|
|
27
|
-
reason: `Eval mutation guard blocked ${event.toolName}: live evals allow destructive Plastic tools only when their schema supports preflight and the call includes preflight: true.`,
|
|
28
|
-
};
|
|
29
|
-
});
|
|
30
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { appendFileSync } from "node:fs";
|
|
2
|
-
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Eval-only provider payload capture. The runner gives each subprocess a unique
|
|
6
|
-
* temporary file and deletes it unless --keep is requested. Never log payloads:
|
|
7
|
-
* JSON mode stdout must remain a clean Pi event stream.
|
|
8
|
-
*/
|
|
9
|
-
const CAPTURE_ENV = "PI_PLASTIC_EVAL_PROVIDER_CAPTURE";
|
|
10
|
-
|
|
11
|
-
export default function providerCapture(pi: ExtensionAPI): void {
|
|
12
|
-
const capturePath = process.env[CAPTURE_ENV];
|
|
13
|
-
if (!capturePath) return;
|
|
14
|
-
|
|
15
|
-
pi.on("before_provider_request", (event) => {
|
|
16
|
-
try {
|
|
17
|
-
appendFileSync(capturePath, `${JSON.stringify({ timestamp: Date.now(), payload: event.payload })}\n`, { encoding: "utf8", mode: 0o600 });
|
|
18
|
-
} catch {
|
|
19
|
-
// Capture must not make a model trial fail or contaminate stdout.
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
}
|