@aefree/pi-plastic 0.4.0 → 0.5.1

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +9 -7
  3. package/extensions/bash-cm-diff-guard.ts +2 -1
  4. package/extensions/file-discovery-filter.ts +67 -0
  5. package/index.ts +18 -2
  6. package/package.json +7 -8
  7. package/skills/_shared/references/conventional-commits.md +198 -198
  8. package/skills/using-plastic/SKILL.md +3 -3
  9. package/skills/using-plastic/references/changeset-operations.md +5 -5
  10. package/skills/using-plastic/references/code-review-creation.md +30 -30
  11. package/skills/using-plastic/references/integration.md +5 -3
  12. package/skills/using-plastic/references/quick-reference.md +2 -1
  13. package/skills/using-plastic/references/resources.md +7 -7
  14. package/skills/using-plastic/references/reviewing-changes.md +9 -7
  15. package/skills/using-plastic/references/shelving.md +25 -25
  16. package/skills/using-plastic/references/troubleshooting.md +5 -3
  17. package/skills/using-plastic/references/workspaces.md +33 -33
  18. package/src/file-discovery-filter-rendezvous.ts +104 -0
  19. package/src/{repository-search-provider.ts → file-discovery-filter.ts} +21 -17
  20. package/src/plastic-core.ts +579 -170
  21. package/src/plastic-tool-loading.ts +3 -3
  22. package/evals/tool-loading/README.md +0 -38
  23. package/evals/tool-loading/RESULTS.md +0 -57
  24. package/evals/tool-loading/baseline.json +0 -34
  25. package/evals/tool-loading/cases.json +0 -70
  26. package/evals/tool-loading/config.json +0 -19
  27. package/evals/tool-loading/mutation-guard.ts +0 -30
  28. package/evals/tool-loading/provider-capture.ts +0 -22
  29. package/evals/tool-loading/results/.gitignore +0 -3
  30. package/evals/tool-loading/run-eval.ts +0 -372
  31. package/extensions/repository-search-provider.ts +0 -66
  32. package/tests/bash-cm-diff-guard-validation.ts +0 -55
  33. package/tests/fixtures/plastic.selector +0 -3
  34. package/tests/fixtures/status-compact.txt +0 -1
  35. package/tests/fixtures/status-normal.txt +0 -1
  36. package/tests/packed-copy-owner-conflict.test.ts +0 -28
  37. package/tests/pi-tool-harness.ts +0 -116
  38. package/tests/plastic-branch-create-live.test.ts +0 -78
  39. package/tests/plastic-branch-query.test.ts +0 -26
  40. package/tests/plastic-branch-status.test.ts +0 -241
  41. package/tests/plastic-checkin-path-resolution.ts +0 -219
  42. package/tests/plastic-constrained-sampling.test.ts +0 -77
  43. package/tests/plastic-diff-workflow.test.ts +0 -86
  44. package/tests/plastic-dynamic-tool-loading.test.ts +0 -224
  45. package/tests/plastic-extension-registration.test.ts +0 -34
  46. package/tests/plastic-live-smoke.test.ts +0 -37
  47. package/tests/plastic-mutation-execution.test.ts +0 -61
  48. package/tests/plastic-patch-command.test.ts +0 -118
  49. package/tests/plastic-process-lifecycle.test.ts +0 -148
  50. package/tests/plastic-tool-rendering.test.ts +0 -16
  51. package/tests/plastic-tool-validation.ts +0 -153
  52. package/tests/plastic-workspace.test.ts +0 -62
  53. package/tests/repository-search-provider-registration.test.ts +0 -37
  54. package/tests/repository-search-provider.test.ts +0 -27
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project follows semantic versioning for public package releases.
7
7
 
8
+ ## [0.5.1] - 2026-08-05
9
+
10
+ ### Changed
11
+
12
+ - Clarified that preflight is situational rather than routine and that status, focused tests, and direct reads should precede intentional diff output.
13
+ - Reduced agent-facing diff defaults, added caller-controlled body bounds and complete JSON response bounds, required selected paths or explicit `allPending=true` for workspace diffs (including direct-call guards), and limited generic diff discovery to one focused tool.
14
+
15
+ ## [0.5.0] - 2026-08-05
16
+
17
+ ### Added
18
+
19
+ - Added dynamically loadable `plastic_workspaceDiff` for bounded pending review: one machine-readable status pass, per-file text/binary/unavailable outcomes, selected-path and private-file policy, and intentional file/output limits.
20
+
21
+ ### Changed
22
+
23
+ - Kept GNU/POSIX `diff` as the only text-diff backend, improved `PI_PLASTIC_DIFF_EXECUTABLE`/bare-PATH diagnostics (including Windows-like missing-diff guidance), and removed unused Git diff fallback code.
24
+ - Made workspace `plastic_diffFile` use machine-readable pending status for private/new, added, changed, moved, and deleted comparisons; status revision IDs materialize safe bases and `--nodata` base failures now explain recovery.
25
+ - Updated diff routing guidance: changed listing uses `plastic_status`, one file uses `plastic_diffFile`, pending review uses `plastic_workspaceDiff`, and explicit historical pairs use `plastic_diffRevisions`.
26
+
27
+ - Replaced the optional `@aefree/pi-repo-search` integration with `@aefree/pi-file-discovery`. Plastic ignore/cloak data is now an advisory file-discovery filter: only roots with readable ignore/cloak files emit `filterDecision: "applied"` records with a nearest-workspace `filterBoundary`; no-op roots are omitted and unavailable or malformed filter data degrades to generic discovery as routine execution hygiene.
28
+ - Register the optional Plastic filter through the package-qualified global capability-registry rendezvous instead of importing `pi-file-discovery` from Plastic's separate module root. Registration remains session-scoped, transactional, and safe against stale shutdown tokens.
29
+ - Excluded development-only tests and behavioral evals from published npm artifacts.
30
+ - Publish verified GitHub releases to npm through resumable OIDC trusted-publishing automation, and canonicalized the package repository URL for GitHub identity matching.
31
+
8
32
  ## [0.4.0] - 2026-08-01
9
33
 
10
34
  ### Added
package/README.md CHANGED
@@ -8,9 +8,9 @@ When Pi starts inside a Plastic workspace, this package adds a themed `Plastic <
8
8
 
9
9
  The extension owns only the `plastic-branch` status key. It does not replace Pi's footer or suppress Pi's Git branch display, so Git and Plastic information can appear together in nested workspaces. If the Plastic marker exists but neither the selector nor `cm` yields a branch, the footer shows `Plastic branch unavailable`. Non-Plastic directories show no Plastic status.
10
10
 
11
- ## Repository-search policy
11
+ ## File-discovery filter
12
12
 
13
- When `@aefree/pi-repo-search` is also installed, Pi session startup registers the independent `plastic.ignore-files` repository-search policy. The marker-based policy discovers readable `ignore.conf` and `cloaked.conf` only from the nearest Plastic workspace to each requested root, then adds them as ripgrep ignore files without replacing native ripgrep/Git-ignore behavior. The integration is optional: without `pi-repo-search`, all Plastic tools and skills still load and only this policy registration is omitted. It does not register workflow guidance or perform Plastic CLI readiness checks; owning `plastic_*` tools validate their own workspace and CLI requirements.
13
+ When `@aefree/pi-file-discovery` is also loaded, Pi session startup registers the independent advisory `plastic.ignore-files` file-discovery filter through the package-qualified capability-registry rendezvous key. The packages may have separate module roots; Plastic does not import file-discovery from its own root. It discovers readable `ignore.conf` and `cloaked.conf` only from the nearest Plastic workspace to each requested root, then supplies them as ripgrep ignore files without replacing native ripgrep/Git-ignore behavior. A root is emitted only when it has at least one readable ignore/cloak file; each emitted root declares `filterDecision: "applied"`, decision code `plastic_ignore_files_applied`, and that workspace as its `filterBoundary`. No-op Plastic roots are omitted from mixed requests, and a request with no effective ignore/cloak records is `not_applicable`. The integration is optional: without `pi-file-discovery`, all Plastic tools and skills still load and no filter registry is created. Missing, malformed, or unavailable Plastic filter data degrades to generic discovery; `pi-file-discovery` owns that execution hygiene and disclosure behavior. It does not register workflow guidance or perform Plastic CLI readiness checks; owning `plastic_*` tools validate their own workspace and CLI requirements.
14
14
 
15
15
 
16
16
  ## Mutation execution
@@ -32,6 +32,7 @@ Removing the approval layer does not relax Plastic safety guards. Command allowl
32
32
  - `plastic_patch`
33
33
  - `plastic_diffRevisions`
34
34
  - `plastic_diffFile`
35
+ - `plastic_workspaceDiff`
35
36
  - `plastic_branchCreate`
36
37
  - `plastic_switchBranch`
37
38
  - `plastic_merge`
@@ -53,7 +54,7 @@ Removing the approval layer does not relax Plastic safety guards. Command allowl
53
54
 
54
55
  ## Dynamic tool loading
55
56
 
56
- The package exposes 28 public `plastic_*` tools. `plastic_workspaceCreate` is intentionally not registered or discoverable until the package provides a paired, safe workspace-cleanup capability. `plastic_tool_search` is a package-owned loader that searches the explicit Plastic capability catalog, reports bounded matches and safety guidance, and additively enables selected tools for the next model request.
57
+ The package exposes 29 public `plastic_*` tools. `plastic_workspaceCreate` is intentionally not registered or discoverable until the package provides a paired, safe workspace-cleanup capability. `plastic_tool_search` is a package-owned loader that searches the explicit Plastic capability catalog, reports bounded matches and safety guidance, and additively enables selected tools for the next model request.
57
58
 
58
59
  The default **balanced** session set keeps `plastic_tool_search`, `plastic_status`, and `plastic_currentBranch` active. The other Plastic tools remain registered but inactive until selected; built-in and other-extension tools are not removed. Previous loader additions on the active session branch are restored on startup, resume, fork, and reload.
59
60
 
@@ -62,7 +63,7 @@ For controlled comparisons, set `PI_PLASTIC_TOOL_LOADING_MODE` before starting P
62
63
  ```bash
63
64
  PI_PLASTIC_TOOL_LOADING_MODE=balanced # default production candidate
64
65
  PI_PLASTIC_TOOL_LOADING_MODE=loader-only # maximum initial schema reduction
65
- PI_PLASTIC_TOOL_LOADING_MODE=all-active # all 28 currently exposed tools; loader omitted
66
+ PI_PLASTIC_TOOL_LOADING_MODE=all-active # all 29 currently exposed tools; loader omitted
66
67
  ```
67
68
 
68
69
  Pi 0.82 and newer use canonical `sourceInfo` provenance to identify this package's effective tools before deferring, restoring, or activating them. If canonical provenance or ownership of the effective loader cannot be proven, `pi-plastic` fails safe: it preserves the complete current active set exactly, does not defer, remove, or activate any `plastic_*` name, and an effective package loader can only report known tools that are already active rather than activating inactive names. On sourceInfo-capable Pi instances, providers without native deferred definitions still receive the complete current active set after a loader call. Reload or restart Pi after source edits; source files are not watched automatically.
@@ -70,7 +71,8 @@ Pi 0.82 and newer use canonical `sourceInfo` provenance to identify this package
70
71
  ## Safety behavior
71
72
 
72
73
  - `plastic_branchCreate` supports an explicit parent branch independent of the loaded workspace branch, defaults relative names to the current branch when no parent is supplied, and rejects top-level paths unless `allowRootBranch=true` is explicit.
73
- - `plastic_diff` remains a disabled alias by design; use `plastic_diffFile` or `plastic_diffRevisions` for text-only file diffs.
74
+ - `plastic_diff` remains a disabled alias by design. Use `plastic_status` for changed-path listing; do not diff as routine post-edit validation or checkin preflight. When change-boundary evidence is needed, use `plastic_diffFile` for one exact file, `plastic_workspaceDiff` with selected paths or explicit `allPending=true`, or `plastic_diffRevisions` for an explicit historical pair. Diff responses use small defaults and caller-controlled `maxChars` bounds.
75
+ - Preflight is not routine confirmation. Use it for ambiguous or broad mutation scope, moved/deleted path rewriting, compound operations, or explicit preview requests; otherwise rely on exact targets and the tools' runtime guards.
74
76
  - `plastic_patch` generates review patches with `cm patch`, including `clean` and `integration` filters for branch review workflows. It does not expose patch apply.
75
77
  - Bash safety rails block `cm diff` and unsafe interactive `cm merge --merge` usage.
76
78
  - Merge tooling surfaces Plastic `FILE_CONFLICT` records and merge-state metadata from `cm status`.
@@ -129,9 +131,9 @@ pi install -l <path-to-pi-plastic>
129
131
  - Node.js 22.19.0 or newer
130
132
  - Pi 0.82.0 or newer; the current development and eval baseline is Pi 0.83
131
133
  - Plastic SCM / Unity Version Control CLI (`cm`) available on `PATH`, or `PI_PLASTIC_CM_EXECUTABLE` set to its full executable path
132
- - A compatible `diff` executable available on `PATH`, or `PI_PLASTIC_DIFF_EXECUTABLE` set to its full executable path, for text-only diff and patch tools
134
+ - GNU/POSIX-compatible `diff` available on `PATH`, or `PI_PLASTIC_DIFF_EXECUTABLE` set to its full executable path (including paths containing spaces), for text-only diff and patch tools. Pi does not discover Git Bash paths automatically.
133
135
  - A configured Plastic workspace for workspace-scoped operations
134
- - `@aefree/pi-repo-search` is an optional peer. When installed, it receives the Plastic ignore/cloak policy; when absent, `pi-plastic` loads without repository-search integration. The tarball does not embed linked sibling workspaces or `node_modules` paths.
136
+ - `pi-file-discovery` is an optional independently loaded integration. When its `discover_candidate_files` tool is active, it receives the advisory Plastic ignore/cloak filter through the shared global capability protocol; when absent, `pi-plastic` loads without file-discovery filtering. The tarball does not embed linked sibling workspaces or `node_modules` paths.
135
137
 
136
138
  ## Testing
137
139
 
@@ -6,7 +6,7 @@ import {
6
6
  } from "./shared/bash-command-guards";
7
7
 
8
8
  const BLOCK_MESSAGE =
9
- "`cm diff` is blocked in Pi because it can launch a GUI window and hang CLI automation. Use `plastic_status` to list changed paths, `plastic_diffFile` for a file diff, or `plastic_diffRevisions` for two explicit revisions.";
9
+ "`cm diff` is blocked in Pi because it can launch a GUI window and hang CLI automation. Use `plastic_status` when only changed paths are needed. Do not diff routinely; when change-boundary evidence is necessary, use a focused `plastic_diffFile`, explicitly scoped `plastic_workspaceDiff`, or `plastic_diffRevisions`.";
10
10
 
11
11
  const DIRECT_CM_DIFF = /^(?:[A-Za-z_][A-Za-z0-9_]*=\S+\s+)*(?:(?:"[^"]*[\\/]cm(?:\.exe)?"|'[^']*[\\/]cm(?:\.exe)?')|(?:[^"'\s]*[\\/])?cm(?:\.exe)?)\s+diff(?:\s|$)/i;
12
12
 
@@ -24,6 +24,7 @@ function commandRunsCmDiff(command: string): boolean {
24
24
  }
25
25
 
26
26
  export const __bashCmDiffGuardInternals = {
27
+ blockMessage: BLOCK_MESSAGE,
27
28
  segmentRunsCmDiff,
28
29
  commandRunsCmDiff,
29
30
  stripAssignments,
@@ -0,0 +1,67 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { createPlasticFileDiscoveryFilterV1, loadPlasticOwnerV1 } from "../src/file-discovery-filter.ts";
3
+ import {
4
+ createPlasticFileDiscoveryFilterRegistryV1,
5
+ type PlasticFileDiscoveryRegistrationToken,
6
+ } from "../src/file-discovery-filter-rendezvous.ts";
7
+
8
+ type ScopeRegistration = Readonly<{ token: PlasticFileDiscoveryRegistrationToken }>;
9
+ type ScopeLifecycle = { generation: number; active: boolean };
10
+
11
+ function hasFileDiscoveryTool(pi: Pick<ExtensionAPI, "getActiveTools">): boolean {
12
+ return pi.getActiveTools?.().includes("discover_candidate_files") ?? false;
13
+ }
14
+
15
+ /**
16
+ * Session-scoped optional Plastic file-discovery filter registration.
17
+ *
18
+ * Independently loaded packages rendezvous through the published global
19
+ * capability-registry protocol. No import is attempted from Plastic's module
20
+ * root, so an absent file-discovery package leaves Plastic unchanged.
21
+ */
22
+ export function createPlasticFileDiscoveryFilterExtension(): (pi: ExtensionAPI) => void {
23
+ return (pi) => {
24
+ const registrations = new WeakMap<object, ScopeRegistration>();
25
+ const lifecycles = new WeakMap<object, ScopeLifecycle>();
26
+
27
+ pi.on("session_start", async (_event, ctx) => {
28
+ if (!hasFileDiscoveryTool(pi)) return;
29
+ const scope = ctx.sessionManager;
30
+ const previous = lifecycles.get(scope);
31
+ const lifecycle = { generation: (previous?.generation ?? 0) + 1, active: true };
32
+ lifecycles.set(scope, lifecycle);
33
+
34
+ const owner = await loadPlasticOwnerV1(import.meta.url);
35
+ // Do not revive a scope whose shutdown occurred while owner discovery was pending.
36
+ if (lifecycles.get(scope) !== lifecycle || !lifecycle.active) return;
37
+ const registry = createPlasticFileDiscoveryFilterRegistryV1();
38
+ const token = registry.register(scope, createPlasticFileDiscoveryFilterV1(owner));
39
+ // Registration succeeds before the prior token is retired, preserving a valid
40
+ // record if construction or validation fails. Nonces make stale retirement safe.
41
+ const current = registrations.get(scope);
42
+ if (lifecycles.get(scope) !== lifecycle || !lifecycle.active) {
43
+ registry.unregister(token);
44
+ return;
45
+ }
46
+ registrations.set(scope, Object.freeze({ token }));
47
+ if (current !== undefined) registry.unregister(current.token);
48
+ });
49
+ pi.on("session_shutdown", (_event, ctx) => {
50
+ const scope = ctx.sessionManager;
51
+ const lifecycle = lifecycles.get(scope);
52
+ if (lifecycle !== undefined) {
53
+ lifecycle.active = false;
54
+ lifecycle.generation += 1;
55
+ }
56
+ const current = registrations.get(scope);
57
+ if (current === undefined) return;
58
+ createPlasticFileDiscoveryFilterRegistryV1().unregister(current.token);
59
+ // A stale shutdown must not erase a replacement registration.
60
+ if (registrations.get(scope) === current) registrations.delete(scope);
61
+ });
62
+ };
63
+ }
64
+
65
+ export default function registerPlasticFileDiscoveryFilters(pi: ExtensionAPI): void {
66
+ createPlasticFileDiscoveryFilterExtension()(pi);
67
+ }
package/index.ts CHANGED
@@ -64,6 +64,7 @@ const PLASTIC_EXPORTS = [
64
64
  "patch",
65
65
  "diffRevisions",
66
66
  "diffFile",
67
+ "workspaceDiff",
67
68
  "branchCreate",
68
69
  "switchBranch",
69
70
  "merge",
@@ -171,6 +172,7 @@ const TOOL_CONFIG: Partial<Record<PlasticExportName, ToolConfig>> = {
171
172
  normalizeWorkdirAliases(input);
172
173
  assignAlias(input, "leftRevision", ["left_revision"]);
173
174
  assignAlias(input, "rightRevision", ["right_revision"]);
175
+ assignAlias(input, "maxChars", ["max_chars"]);
174
176
  return input;
175
177
  },
176
178
  },
@@ -178,6 +180,20 @@ const TOOL_CONFIG: Partial<Record<PlasticExportName, ToolConfig>> = {
178
180
  prepareArguments(args) {
179
181
  const input = normalizeArgs(args);
180
182
  normalizeWorkdirAliases(input);
183
+ assignAlias(input, "maxChars", ["max_chars"]);
184
+ return input;
185
+ },
186
+ },
187
+ workspaceDiff: {
188
+ prepareArguments(args) {
189
+ const input = normalizeOutputFormatAlias(normalizeArgs(args));
190
+ normalizeWorkdirAliases(input);
191
+ promoteSinglePath(input);
192
+ assignAlias(input, "paths", ["items", "files"]);
193
+ assignAlias(input, "allPending", ["all_pending"]);
194
+ assignAlias(input, "includePrivate", ["include_private"]);
195
+ assignAlias(input, "maxFiles", ["max_files"]);
196
+ assignAlias(input, "maxChars", ["max_chars"]);
181
197
  return input;
182
198
  },
183
199
  },
@@ -696,12 +712,12 @@ export default function plasticTools(pi: ExtensionAPI) {
696
712
  description: "Search and enable Plastic SCM / Unity Version Control tools for workspace status and sync, changes and checkins, text-only diffs and patches, branches and merges, shelvesets, code reviews, and workspaces.",
697
713
  promptSnippet: "Use plastic_tool_search to find and enable Plastic SCM capabilities that are not active.",
698
714
  promptGuidelines: [
699
- "Use plastic_tool_search before a Plastic SCM action when an appropriate plastic_* tool is not active. Inspect exact targets and use each tool's preflight and safety options before mutations.",
715
+ "Use plastic_tool_search before a Plastic SCM action when an appropriate plastic_* tool is not active. Inspect exact mutation targets. Do not preflight routinely: use preflight for ambiguous or broad scope, moved/deleted path rewriting, compound operations, or an explicit preview request.",
700
716
  ],
701
717
  parameters: Type.Object({
702
718
  query: Type.Optional(Type.String({ description: "Capability or workflow to search for." })),
703
719
  toolNames: Type.Optional(Type.Array(Type.String({ description: "Exact public Plastic tool name." }), { maxItems: 4, description: "Optional exact tool names to enable." })),
704
- limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 4, description: "Maximum matching tools to enable. Defaults to the single best keyword match, except generic diff loads both safe text-only alternatives; exact toolNames requests may enable up to four." })),
720
+ limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 4, description: "Maximum matching tools to enable. Defaults to the single best keyword match; exact toolNames requests may enable up to four." })),
705
721
  }),
706
722
  async execute(_toolCallId, params) {
707
723
  if (isPlasticToolBrowseRequest(params)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aefree/pi-plastic",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22.19.0"
@@ -17,8 +17,6 @@
17
17
  "src/",
18
18
  "references/",
19
19
  "skills/",
20
- "evals/tool-loading/",
21
- "tests/",
22
20
  "CHANGELOG.md",
23
21
  "CONTRIBUTING.md",
24
22
  "LICENSE",
@@ -31,24 +29,25 @@
31
29
  "./extensions/plastic-branch-status.ts",
32
30
  "./extensions/bash-cm-diff-guard.ts",
33
31
  "./extensions/bash-cm-merge-guard.ts",
34
- "./extensions/repository-search-provider.ts"
32
+ "./extensions/file-discovery-filter.ts"
35
33
  ],
36
34
  "skills": [
37
35
  "./skills"
38
36
  ]
39
37
  },
40
38
  "scripts": {
41
- "test": "npx --yes tsx tests/plastic-tool-validation.ts && npx --yes tsx tests/plastic-checkin-path-resolution.ts && npx --yes tsx tests/plastic-diff-workflow.test.ts && npx --yes tsx tests/plastic-process-lifecycle.test.ts && npx --yes tsx tests/plastic-patch-command.test.ts && npx --yes tsx tests/plastic-extension-registration.test.ts && npx --yes tsx tests/plastic-dynamic-tool-loading.test.ts && npx --yes tsx tests/plastic-tool-rendering.test.ts && npx --yes tsx tests/plastic-branch-query.test.ts && npx --yes tsx tests/plastic-workspace.test.ts && npx --yes tsx tests/plastic-mutation-execution.test.ts && npx --yes tsx tests/repository-search-provider.test.ts && npx --yes tsx tests/repository-search-provider-registration.test.ts && npx --yes tsx tests/packed-copy-owner-conflict.test.ts && npx --yes tsx tests/plastic-branch-status.test.ts && npx --yes tsx tests/plastic-constrained-sampling.test.ts && npx --yes tsx tests/bash-cm-diff-guard-validation.ts",
39
+ "test": "npx --yes tsx tests/plastic-tool-validation.ts && npx --yes tsx tests/plastic-checkin-path-resolution.ts && npx --yes tsx tests/plastic-diff-workflow.test.ts && npx --yes tsx tests/plastic-workspace-diff.test.ts && npx --yes tsx tests/plastic-process-lifecycle.test.ts && npx --yes tsx tests/plastic-patch-command.test.ts && npx --yes tsx tests/plastic-extension-registration.test.ts && npx --yes tsx tests/plastic-dynamic-tool-loading.test.ts && npx --yes tsx tests/plastic-tool-rendering.test.ts && npx --yes tsx tests/plastic-branch-query.test.ts && npx --yes tsx tests/plastic-workspace.test.ts && npx --yes tsx tests/plastic-mutation-execution.test.ts && npx --yes tsx tests/file-discovery-filter.test.ts && npx --yes tsx tests/file-discovery-filter-registration.test.ts && npx --yes tsx tests/packed-copy-owner-conflict.test.ts && npx --yes tsx tests/plastic-branch-status.test.ts && npx --yes tsx tests/plastic-constrained-sampling.test.ts && npx --yes tsx tests/bash-cm-diff-guard-validation.ts",
42
40
  "test:live": "npx --yes tsx tests/plastic-live-smoke.test.ts",
43
41
  "test:live:branch-create": "npx --yes tsx tests/plastic-branch-create-live.test.ts",
44
42
  "eval:tool-loading": "npx --yes tsx evals/tool-loading/run-eval.ts"
45
43
  },
46
44
  "devDependencies": {
45
+ "@aefree/pi-file-discovery": "^0.1.1",
47
46
  "@earendil-works/pi-coding-agent": "0.83.0",
48
47
  "typebox": "^1.3.8"
49
48
  },
50
49
  "peerDependencies": {
51
- "@aefree/pi-repo-search": "^0.1.0",
50
+ "@aefree/pi-file-discovery": "^0.1.0",
52
51
  "@earendil-works/pi-coding-agent": "*",
53
52
  "typebox": "*"
54
53
  },
@@ -56,14 +55,14 @@
56
55
  "license": "MIT",
57
56
  "repository": {
58
57
  "type": "git",
59
- "url": "git+ssh://git@github.com/aefreedman/pi-plastic.git"
58
+ "url": "git+https://github.com/aefreedman/pi-plastic.git"
60
59
  },
61
60
  "bugs": {
62
61
  "url": "https://github.com/aefreedman/pi-plastic/issues"
63
62
  },
64
63
  "homepage": "https://github.com/aefreedman/pi-plastic#readme",
65
64
  "peerDependenciesMeta": {
66
- "@aefree/pi-repo-search": {
65
+ "@aefree/pi-file-discovery": {
67
66
  "optional": true
68
67
  },
69
68
  "@earendil-works/pi-coding-agent": {