@aefree/pi-plastic 0.5.4 → 0.5.6

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 CHANGED
@@ -5,6 +5,20 @@ 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
+ ## Unreleased
9
+
10
+ ## [0.5.6] - 2026-08-27
11
+
12
+ ### Fixed
13
+
14
+ - Warn once per interactive Pi runtime when a configured `PI_PLASTIC_PATCH_EXECUTABLE` cannot launch or Windows lacks its required patch backend setting. Warnings redact configured paths; `plastic_patch` retains its existing tool-time validation.
15
+
16
+ ## [0.5.5] - 2026-08-14
17
+
18
+ ### Changed
19
+
20
+ - Made `plastic_status(machineReadable=true, format="json")` return compact parsed pending-item records, aggregate counts, and bounded-item metadata, with package-owned field separation and revision IDs. It returns at most 100 items by default (configurable up to 500); raw, unbounded Plastic output is omitted by default and available with `includeRaw=true` only for diagnostics.
21
+
8
22
  ## [0.5.4] - 2026-08-13
9
23
 
10
24
  ### Fixed
package/README.md CHANGED
@@ -74,6 +74,7 @@ The Bash guards run only in Pi processes that actually load this package. A proj
74
74
 
75
75
  - `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.
76
76
  - `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. Historical and workspace bytes are copied to ASCII-safe package-owned paths before the backend runs, while normalized headers retain the logical Unicode labels.
77
+ - `plastic_status(machineReadable=true, format="json")` returns parsed `items`, aggregate `summary`, and `itemCount` (`total`, `returned`, `omitted`) rather than requiring agents to parse Plastic rows. It returns at most 100 items by default; set `maxItems` (up to 500) when more are intentional. `includeRaw=true` adds the original unbounded Plastic output for diagnostics, so omit it for normal agent use to conserve context tokens.
77
78
  - 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.
78
79
  - `plastic_patch` generates review patches with `cm patch`, including `clean` and `integration` filters for branch review workflows. It does not expose patch apply. Unqualified `br:/...` selectors are qualified only with the current workspace selector's exact repository; otherwise pass `br:/<branch>@<repository>@<server>`.
79
80
  - Bash safety rails block `cm diff` and unsafe interactive `cm merge --merge` usage.
@@ -142,7 +143,7 @@ Project-local installation protects only Pi processes that load those project se
142
143
  - Pi 0.82.0 or newer; the current development and eval baseline is Pi 0.83
143
144
  - Plastic SCM / Unity Version Control CLI (`cm`) available on `PATH`, or `PI_PLASTIC_CM_EXECUTABLE` set to its full executable path
144
145
  - A GNU/POSIX-compatible text `diff` available on `PATH`, or `PI_PLASTIC_DIFF_EXECUTABLE` set to its full executable path (including paths containing spaces), for text-only diff tools. Pi invokes that resolved executable as-is and does not discover Git Bash paths automatically. On macOS, bare `diff` is PATH-dependent: it may be GNU Diffutils (often installed as `diff` ahead of system paths) or Apple’s BSD `/usr/bin/diff`; the package does not substitute one for the other. Configure the intended text executable explicitly when that distinction matters.
145
- - Patch generation has a separate executable policy: `toolPath` is the one-call highest-priority override, followed by `PI_PLASTIC_PATCH_EXECUTABLE`. On Windows, set one to a verified patch-capable non-GUI executable such as Git's `diff.exe`; the package deliberately does not reuse `PI_PLASTIC_DIFF_EXECUTABLE`/GnuWin32 as a patch default. macOS validation with Plastic 11 found that Apple BSD `/usr/bin/diff` supports text-only diffs but rejects the `--binary` argument supplied by `cm patch`; configure a verified GNU Diffutils-compatible executable explicitly for `plastic_patch`. The non-Windows fallback to `PI_PLASTIC_DIFF_EXECUTABLE` or bare `diff` remains only for environments whose resolved executable satisfies that patch contract.
146
+ - Patch generation has a separate executable policy: `toolPath` is the one-call highest-priority override, followed by `PI_PLASTIC_PATCH_EXECUTABLE`. On Windows, set one to a verified patch-capable non-GUI executable such as Git's `diff.exe`; the package deliberately does not reuse `PI_PLASTIC_DIFF_EXECUTABLE`/GnuWin32 as a patch default. macOS validation with Plastic 11 found that Apple BSD `/usr/bin/diff` supports text-only diffs but rejects the `--binary` argument supplied by `cm patch`; configure a verified GNU Diffutils-compatible executable explicitly for `plastic_patch`. The non-Windows fallback to `PI_PLASTIC_DIFF_EXECUTABLE` or bare `diff` remains only for environments whose resolved executable satisfies that patch contract. In an interactive Pi session, an invalid configured patch override or missing Windows patch setting produces one package capability warning per Pi runtime; the warning omits configured paths, and `plastic_patch` retains its tool-time validation.
146
147
  - A configured Plastic workspace for workspace-scoped operations. Text diffs require an ASCII-safe temporary directory; if the configured backend cannot accept Unicode paths, set `TEMP` and `TMP` to a writable ASCII-only location.
147
148
  - `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.
148
149
 
package/index.ts CHANGED
@@ -94,6 +94,8 @@ const TOOL_CONFIG: Partial<Record<PlasticExportName, ToolConfig>> = {
94
94
  normalizeWorkdirAliases(input);
95
95
  assignAlias(input, "includeRevId", ["include_rev_id"]);
96
96
  assignAlias(input, "machineReadable", ["machine_readable", "machine"]);
97
+ assignAlias(input, "maxItems", ["max_items"]);
98
+ assignAlias(input, "includeRaw", ["include_raw"]);
97
99
  return input;
98
100
  },
99
101
  },
@@ -654,6 +656,28 @@ function metadataDescription(node: CoreSchemaNode): string {
654
656
  return node.metadata?.description ?? "Allowed values.";
655
657
  }
656
658
 
659
+ type CapabilityDiagnosticContext = {
660
+ hasUI?: boolean;
661
+ ui?: { notify?: (message: string, level: "warning") => void };
662
+ };
663
+
664
+ type PatchCapabilityWarningGetter = () => Promise<string | undefined>;
665
+
666
+ export const __plasticCapabilityDiagnosticInternals = {
667
+ createPatchCapabilityWarningNotifier(getWarning: PatchCapabilityWarningGetter = () => core.getPatchBackendCapabilityWarning()) {
668
+ let emitted = false;
669
+ return async (ctx: CapabilityDiagnosticContext): Promise<void> => {
670
+ if (emitted || !ctx.hasUI || typeof ctx.ui?.notify !== "function") return;
671
+ const warning = await getWarning();
672
+ if (!warning) return;
673
+ emitted = true;
674
+ ctx.ui.notify(warning, "warning");
675
+ };
676
+ },
677
+ };
678
+
679
+ const notifyPatchCapabilityWarning = __plasticCapabilityDiagnosticInternals.createPatchCapabilityWarningNotifier();
680
+
657
681
  function buildParameters(args: Record<string, unknown> | undefined): TSchema {
658
682
  if (!args || Object.keys(args).length === 0) {
659
683
  return EMPTY_PARAMETERS;
@@ -768,7 +792,8 @@ export default function plasticTools(pi: ExtensionAPI) {
768
792
  },
769
793
  });
770
794
 
771
- pi.on("session_start", (_event, ctx) => {
795
+ pi.on("session_start", async (_event, ctx) => {
796
+ await notifyPatchCapabilityWarning(ctx as CapabilityDiagnosticContext);
772
797
  const ownership = getEffectivePlasticToolOwnership(pi.getAllTools(), EXTENSION_SOURCE_PATH);
773
798
  const active = pi.getActiveTools();
774
799
  const mode = getPlasticToolLoadingMode();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aefree/pi-plastic",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22.19.0"
@@ -18,8 +18,7 @@
18
18
  "skills/",
19
19
  "CHANGELOG.md",
20
20
  "LICENSE",
21
- "README.md",
22
- "SECURITY.md"
21
+ "README.md"
23
22
  ],
24
23
  "pi": {
25
24
  "extensions": [
@@ -34,7 +33,7 @@
34
33
  ]
35
34
  },
36
35
  "scripts": {
37
- "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",
36
+ "test": "npx --yes tsx tests/plastic-tool-validation.ts && npx --yes tsx tests/plastic-status-machine-readable.test.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-capability-diagnostics.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",
38
37
  "test:live": "npx --yes tsx tests/plastic-live-smoke.test.ts",
39
38
  "test:live:branch-create": "npx --yes tsx tests/plastic-branch-create-live.test.ts",
40
39
  "eval:tool-loading": "npx --yes tsx evals/tool-loading/run-eval.ts"
@@ -22,7 +22,7 @@ Plastic merges are workspace- and branch-oriented, not Git fast-forwards: the me
22
22
 
23
23
  `plastic_workspaceDiff` requires selected paths or explicit `allPending=true`, runs status once, has small default file/per-file/combined-output bounds, and returns per-file outcomes without aborting when one file is unavailable. Selected private paths are included; whole-workspace private review additionally requires `includePrivate=true`. Keep `maxChars` small unless more output is intentional. Text-diff selection and patch-backend selection are distinct: text tools use `PI_PLASTIC_DIFF_EXECUTABLE` or bare PATH `diff`. On macOS, bare `diff` can resolve either to GNU Diffutils or Apple’s BSD `/usr/bin/diff`; Pi uses the resolved executable and does not auto-select `gdiff`.
24
24
 
25
- Use `plastic_patch` for review patch generation with `clean` and `integration` filters; it is generation-only and does not apply patches. `toolPath` is its highest-priority one-call patch-backend override, followed by `PI_PLASTIC_PATCH_EXECUTABLE`. On Windows, configure one to a verified patch-capable non-GUI executable such as Git's `diff.exe`: patch generation deliberately does not reuse `PI_PLASTIC_DIFF_EXECUTABLE`/GnuWin32. On macOS with Plastic 11, Apple BSD `/usr/bin/diff` works for text-only `plastic_diffFile` but rejects the `--binary` argument used by `cm patch`; set the patch-specific policy to a verified GNU Diffutils-compatible non-GUI executable. The non-Windows fallback to the text setting or bare `diff` is only valid when that executable accepts the local Plastic patch arguments. Unqualified `br:/...` patch selectors are qualified only from the current workspace's exact selector repository; otherwise pass `br:/<branch>@<repository>@<server>`. For a large patch, pass an intentional new `output` path: the package stages and atomically publishes it, never overwriting an existing path. Do not use `cm cat --raw`: it is unsupported for this workflow. Typed retrieval owns cleanup; the low-level byte-preserving fallback is `cm cat --file` only when a typed tool cannot represent the case. Plastic/server output may represent moves as moves or delete/add records, so inspect generated patches rather than assuming a move-aware encoding.
25
+ Use `plastic_patch` for review patch generation with `clean` and `integration` filters; it is generation-only and does not apply patches. `toolPath` is its highest-priority one-call patch-backend override, followed by `PI_PLASTIC_PATCH_EXECUTABLE`. On Windows, configure one to a verified patch-capable non-GUI executable such as Git's `diff.exe`: patch generation deliberately does not reuse `PI_PLASTIC_DIFF_EXECUTABLE`/GnuWin32. On macOS with Plastic 11, Apple BSD `/usr/bin/diff` works for text-only `plastic_diffFile` but rejects the `--binary` argument used by `cm patch`; set the patch-specific policy to a verified GNU Diffutils-compatible non-GUI executable. The non-Windows fallback to the text setting or bare `diff` is only valid when that executable accepts the local Plastic patch arguments. Interactive Pi sessions issue one path-redacted package capability warning per runtime for an invalid configured patch override or missing Windows setting; fix `PI_PLASTIC_PATCH_EXECUTABLE` and retry, while headless sessions retain `plastic_patch` tool-time validation. Unqualified `br:/...` patch selectors are qualified only from the current workspace's exact selector repository; otherwise pass `br:/<branch>@<repository>@<server>`. For a large patch, pass an intentional new `output` path: the package stages and atomically publishes it, never overwriting an existing path. Do not use `cm cat --raw`: it is unsupported for this workflow. Typed retrieval owns cleanup; the low-level byte-preserving fallback is `cm cat --file` only when a typed tool cannot represent the case. Plastic/server output may represent moves as moves or delete/add records, so inspect generated patches rather than assuming a move-aware encoding.
26
26
 
27
27
  Prefer runtime `plastic_*` tools first. Keep `cm` shell commands as manual fallback.
28
28
 
@@ -32,6 +32,7 @@ const getCmExecutable = (): string => resolveExecutable(process.env, "PI_PLASTIC
32
32
  // Keep the executable name configurable rather than assuming a .exe suffix or package-manager path.
33
33
  const getDiffExecutable = (): string => resolveExecutable(process.env, "PI_PLASTIC_DIFF_EXECUTABLE", "diff");
34
34
  const PLASTIC_PATCH_EXECUTABLE_ENV = "PI_PLASTIC_PATCH_EXECUTABLE";
35
+ type PatchExecutableProbe = (command: string) => Promise<boolean>;
35
36
  // Plastic's server/backend determines whether a moved item is encoded as a
36
37
  // move or as delete/add records. Do not claim either without a live fixture.
37
38
  const PATCH_MOVE_REPRESENTATION = "backend-determined" as const;
@@ -326,6 +327,20 @@ type PendingItemSummary = {
326
327
  privatePaths: string[];
327
328
  };
328
329
 
330
+ type MachineReadableStatusItem = {
331
+ statusCode: string;
332
+ kind: PendingItemKind;
333
+ path: string;
334
+ isDirectory: boolean;
335
+ revisionId?: string;
336
+ sourcePath?: string;
337
+ };
338
+
339
+ type MachineReadableStatusSummary = Omit<PendingItemSummary, "privatePaths">;
340
+
341
+ const MACHINE_READABLE_STATUS_DEFAULT_MAX_ITEMS = 100;
342
+ const MACHINE_READABLE_STATUS_MAX_ITEMS = 500;
343
+
329
344
  type PrivateAutoAddSelection = {
330
345
  candidatePaths: string[];
331
346
  blockedPaths: Array<{ path: string; reason: string }>;
@@ -685,6 +700,22 @@ const getMachineReadablePendingItems = async (workdir?: string): Promise<Pending
685
700
  return parseMachineReadablePendingItems(output, cwd);
686
701
  };
687
702
 
703
+ const toMachineReadableStatusItems = (pendingItems: PendingItem[]): MachineReadableStatusItem[] =>
704
+ pendingItems.map((item) => ({
705
+ statusCode: item.statusCode,
706
+ kind: item.kind,
707
+ path: item.workspacePath,
708
+ isDirectory: item.isDirectory,
709
+ ...(item.revisionId ? { revisionId: item.revisionId } : {}),
710
+ ...(item.sourceWorkspacePath ? { sourcePath: item.sourceWorkspacePath } : {}),
711
+ }));
712
+
713
+ const toMachineReadableStatusSummary = (pendingItems: PendingItem[], cwd: string): MachineReadableStatusSummary =>
714
+ {
715
+ const { privatePaths: _privatePaths, ...summary } = summarizePendingItems(pendingItems, cwd);
716
+ return summary;
717
+ };
718
+
688
719
  const summarizePendingItems = (pendingItems: PendingItem[], cwd?: string): PendingItemSummary =>
689
720
  {
690
721
  const summary: PendingItemSummary = {
@@ -1198,6 +1229,49 @@ const assertNonBlankPatchValue = (name: keyof PatchCommandArgs, value: string |
1198
1229
  }
1199
1230
  };
1200
1231
 
1232
+ const probePatchExecutable = async (command: string): Promise<boolean> =>
1233
+ {
1234
+ try
1235
+ {
1236
+ // This establishes only that the configured executable can launch.
1237
+ // `cm patch` remains the authoritative verifier for its --binary contract.
1238
+ const result = await spawnAndCollect(command, ["--version"], process.cwd(), undefined, AbortSignal.timeout(3000), {
1239
+ abortKillDelayMs: 100,
1240
+ outputLimitChars: 1024,
1241
+ });
1242
+ return !result.aborted;
1243
+ }
1244
+ catch
1245
+ {
1246
+ return false;
1247
+ }
1248
+ };
1249
+
1250
+ export const getPatchBackendCapabilityWarning = async (
1251
+ environment: ExecutableEnvironment = process.env,
1252
+ platform: NodeJS.Platform = process.platform,
1253
+ probe: PatchExecutableProbe = probePatchExecutable,
1254
+ ): Promise<string | undefined> =>
1255
+ {
1256
+ const configuredPatchExecutable = environment[PLASTIC_PATCH_EXECUTABLE_ENV]?.trim();
1257
+ if (configuredPatchExecutable)
1258
+ {
1259
+ if (await probe(configuredPatchExecutable))
1260
+ {
1261
+ return undefined;
1262
+ }
1263
+
1264
+ return "Pi Plastic capability warning: the configured PI_PLASTIC_PATCH_EXECUTABLE could not be launched. Set it to a verified patch-capable non-GUI diff executable, or remove the override to use this platform's documented fallback. The configured path is not shown for privacy.";
1265
+ }
1266
+
1267
+ if (platform === "win32")
1268
+ {
1269
+ return "Pi Plastic capability warning: plastic_patch requires PI_PLASTIC_PATCH_EXECUTABLE on Windows. Set it to a verified patch-capable non-GUI diff executable (for example Git's diff.exe). PI_PLASTIC_DIFF_EXECUTABLE is only for text diffs.";
1270
+ }
1271
+
1272
+ return undefined;
1273
+ };
1274
+
1201
1275
  const resolvePatchToolPath = (
1202
1276
  toolPath?: string,
1203
1277
  environment: ExecutableEnvironment = process.env,
@@ -1461,6 +1535,7 @@ export const __plasticProcessInternals = {
1461
1535
  export const __plasticPatchInternals = {
1462
1536
  buildPatchCommandArgs,
1463
1537
  resolvePatchToolPath,
1538
+ getPatchBackendCapabilityWarning,
1464
1539
  qualifyPatchBranchSpec,
1465
1540
  resolvePatchBranchSpecs,
1466
1541
  createPatchOutputStaging,
@@ -2375,7 +2450,9 @@ export const status = tool({
2375
2450
  args: {
2376
2451
  workdir: workdirArg,
2377
2452
  includeRevId: tool.schema.boolean().optional().describe("Include revision IDs in the status output when supported."),
2378
- machineReadable: tool.schema.boolean().optional().describe("Return machine-readable status output when supported."),
2453
+ machineReadable: tool.schema.boolean().optional().describe("Return parsed, machine-readable pending status records when supported."),
2454
+ maxItems: tool.schema.number().int().min(1).max(MACHINE_READABLE_STATUS_MAX_ITEMS).optional().describe(`Maximum parsed items in machine-readable JSON (default ${MACHINE_READABLE_STATUS_DEFAULT_MAX_ITEMS}, maximum ${MACHINE_READABLE_STATUS_MAX_ITEMS}).`),
2455
+ includeRaw: tool.schema.boolean().optional().describe("Include unbounded raw machine-readable Plastic output in JSON diagnostics. Applies only when machineReadable=true."),
2379
2456
  short: tool.schema.boolean().optional().describe("Use short status output."),
2380
2457
  format: outputFormatArg,
2381
2458
  },
@@ -2396,15 +2473,32 @@ export const status = tool({
2396
2473
 
2397
2474
  if (args.machineReadable)
2398
2475
  {
2399
- cmdArgs.push("--machinereadable");
2476
+ // Package-owned separators make paths with whitespace unambiguous, and
2477
+ // revision IDs let agents safely identify the base of moved/deleted items.
2478
+ if (!cmdArgs.includes("--includeRevId"))
2479
+ {
2480
+ cmdArgs.push("--includeRevId");
2481
+ }
2482
+ cmdArgs.push("--machinereadable", `--fieldseparator=${STATUS_FIELD_SEPARATOR}`);
2400
2483
  const machineOutput = await runCmRaw(cmdArgs, args.workdir);
2484
+ const cwd = args.workdir ?? process.cwd();
2485
+ const pendingItems = parseMachineReadablePendingItems(machineOutput, cwd);
2486
+ const maxItems = args.maxItems ?? MACHINE_READABLE_STATUS_DEFAULT_MAX_ITEMS;
2487
+ const returnedItems = pendingItems.slice(0, maxItems);
2401
2488
  return toStructuredResult(
2402
2489
  "status",
2403
2490
  format,
2404
2491
  machineOutput,
2405
2492
  {
2406
- rawOutput: machineOutput,
2407
2493
  machineReadable: true,
2494
+ items: toMachineReadableStatusItems(returnedItems),
2495
+ itemCount: {
2496
+ total: pendingItems.length,
2497
+ returned: returnedItems.length,
2498
+ omitted: pendingItems.length - returnedItems.length,
2499
+ },
2500
+ summary: toMachineReadableStatusSummary(pendingItems, cwd),
2501
+ ...(args.includeRaw ? { rawOutput: machineOutput } : {}),
2408
2502
  },
2409
2503
  args.workdir,
2410
2504
  );
package/SECURITY.md DELETED
@@ -1,31 +0,0 @@
1
- # Security Policy
2
-
3
- ## Supported versions
4
-
5
- Security fixes are provided for the latest tagged release. Upgrade to the newest release before reporting an issue that may already be fixed.
6
-
7
- ## Reporting a vulnerability
8
-
9
- Do not open a public issue for a suspected vulnerability, credential exposure, or unsafe command-execution path.
10
-
11
- Use GitHub's private vulnerability reporting for this repository:
12
-
13
- <https://github.com/aefreedman/pi-plastic/security/advisories/new>
14
-
15
- Include:
16
-
17
- - the affected package version or commit;
18
- - the Pi, Node.js, Git, and Plastic CLI versions;
19
- - the operating system;
20
- - reproduction steps and expected versus observed behavior;
21
- - the affected tool or extension;
22
- - impact and any known mitigations;
23
- - whether credentials, repository content, or remote Plastic objects may have been exposed or changed.
24
-
25
- Avoid including real credentials or sensitive repository content. Use a disposable Plastic workspace when a reproduction requires mutation.
26
-
27
- You should receive an acknowledgement within seven days. Release timing depends on severity, reproducibility, and coordination needs.
28
-
29
- ## Scope
30
-
31
- Security-sensitive areas include command construction, executable-path overrides, workspace/path targeting, destructive Plastic operations, provider payload capture, dynamic tool ownership, and package-install behavior. General support questions and ordinary bugs belong in the public issue tracker.