@aefree/pi-plastic 0.4.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 +109 -0
- package/CONTRIBUTING.md +88 -0
- package/LICENSE +21 -0
- package/README.md +181 -0
- package/SECURITY.md +31 -0
- package/evals/tool-loading/README.md +38 -0
- package/evals/tool-loading/RESULTS.md +57 -0
- package/evals/tool-loading/baseline.json +34 -0
- package/evals/tool-loading/cases.json +70 -0
- package/evals/tool-loading/config.json +19 -0
- package/evals/tool-loading/mutation-guard.ts +30 -0
- package/evals/tool-loading/provider-capture.ts +22 -0
- package/evals/tool-loading/results/.gitignore +3 -0
- package/evals/tool-loading/run-eval.ts +372 -0
- package/extensions/bash-cm-diff-guard.ts +49 -0
- package/extensions/bash-cm-merge-guard.ts +53 -0
- package/extensions/plastic-branch-status.ts +285 -0
- package/extensions/repository-search-provider.ts +66 -0
- package/extensions/shared/bash-command-guards.ts +67 -0
- package/index.ts +777 -0
- package/package.json +76 -0
- package/skills/_shared/references/conventional-commits.md +198 -0
- package/skills/using-plastic/SKILL.md +50 -0
- package/skills/using-plastic/references/branch-management.md +78 -0
- package/skills/using-plastic/references/changeset-operations.md +96 -0
- package/skills/using-plastic/references/code-review-creation.md +30 -0
- package/skills/using-plastic/references/integration.md +47 -0
- package/skills/using-plastic/references/quick-reference.md +32 -0
- package/skills/using-plastic/references/resources.md +7 -0
- package/skills/using-plastic/references/reviewing-changes.md +71 -0
- package/skills/using-plastic/references/shelving.md +25 -0
- package/skills/using-plastic/references/troubleshooting.md +115 -0
- package/skills/using-plastic/references/workspaces.md +33 -0
- package/src/pi-tool-compat.ts +56 -0
- package/src/plastic-core.ts +4204 -0
- package/src/plastic-tool-loading.ts +234 -0
- package/src/plastic-workspace.ts +176 -0
- package/src/repository-search-provider.ts +64 -0
- package/tests/bash-cm-diff-guard-validation.ts +55 -0
- package/tests/fixtures/plastic.selector +3 -0
- package/tests/fixtures/status-compact.txt +1 -0
- package/tests/fixtures/status-normal.txt +1 -0
- package/tests/packed-copy-owner-conflict.test.ts +28 -0
- package/tests/pi-tool-harness.ts +116 -0
- package/tests/plastic-branch-create-live.test.ts +78 -0
- package/tests/plastic-branch-query.test.ts +26 -0
- package/tests/plastic-branch-status.test.ts +241 -0
- package/tests/plastic-checkin-path-resolution.ts +219 -0
- package/tests/plastic-constrained-sampling.test.ts +77 -0
- package/tests/plastic-diff-workflow.test.ts +86 -0
- package/tests/plastic-dynamic-tool-loading.test.ts +224 -0
- package/tests/plastic-extension-registration.test.ts +34 -0
- package/tests/plastic-live-smoke.test.ts +37 -0
- package/tests/plastic-mutation-execution.test.ts +61 -0
- package/tests/plastic-patch-command.test.ts +118 -0
- package/tests/plastic-process-lifecycle.test.ts +148 -0
- package/tests/plastic-tool-rendering.test.ts +16 -0
- package/tests/plastic-tool-validation.ts +153 -0
- package/tests/plastic-workspace.test.ts +62 -0
- package/tests/repository-search-provider-registration.test.ts +37 -0
- package/tests/repository-search-provider.test.ts +27 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Reviewing Changes
|
|
2
|
+
|
|
3
|
+
## Critical Rule
|
|
4
|
+
|
|
5
|
+
Never run `cm diff` in Pi. It may open a GUI window and block CLI automation.
|
|
6
|
+
|
|
7
|
+
`plastic_diff` is disabled by design.
|
|
8
|
+
|
|
9
|
+
## Focused Patch Generation
|
|
10
|
+
|
|
11
|
+
Use `plastic_patch` when you need a branch-review patch for AI assistance, code review, or sharing outside the Plastic GUI:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
plastic_patch(source="<branch-spec>", integration=true)
|
|
15
|
+
plastic_patch(source="<branch-spec>", clean=true, integration=true, output="<patch-file>")
|
|
16
|
+
plastic_patch(source="<left-spec>", destination="<right-spec>")
|
|
17
|
+
plastic_patch(source="<branch-spec>", toolPath="<path-to-diff-tool>")
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`integration=true` shows changes pending merge into the parent branch. `clean=true` strips content that arrived via merges. Use `output` for large patches; Plastic refuses to overwrite an existing output file. Inspect patch contents before sharing because patches can contain source code, binary data, local paths, or secrets present in changed files.
|
|
21
|
+
|
|
22
|
+
## Text-Only Diff Options
|
|
23
|
+
|
|
24
|
+
Prefer tool-first:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
plastic_status(machineReadable=true) # “what changed?” / changed-path listing
|
|
28
|
+
plastic_diffFile(path="<workspace-path>") # common workspace vs Plastic-base comparison
|
|
29
|
+
plastic_diffFile(path="<workspace-path>", revision="cs:<number>") # explicit advanced comparison
|
|
30
|
+
plastic_diffRevisions(leftRevision="<left-file-qualified-revspec>", rightRevision="<right-file-qualified-revspec>")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The diff tools materialize historical bytes and remove their temporary files internally. They use a bounded portable text diff, treat valid Unity YAML as text, and report genuine binary content explicitly. Do not construct `cm cat` temporary-file recipes for ordinary review.
|
|
34
|
+
|
|
35
|
+
## Metadata Listing (No GUI Diff)
|
|
36
|
+
|
|
37
|
+
Use changeset metadata to understand branch activity:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cm find changeset "where branch = '<branch-name>' order by changesetid desc limit 20" --format="{changesetid} {owner} {date} {comment}" --nototal
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Read Files Directly
|
|
44
|
+
|
|
45
|
+
Use the Read tool for full context instead of GUI diffs.
|
|
46
|
+
|
|
47
|
+
## CLI-Safe File Diff
|
|
48
|
+
|
|
49
|
+
Use the common no-revision path first; `base`, `head`, and `cs:head` are rejected rather than guessed:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
plastic_diffFile(path="<workspace-path>")
|
|
53
|
+
plastic_diffFile(path="<workspace-path>", revision="br:/<branch>")
|
|
54
|
+
plastic_diffRevisions(leftRevision="<left-file-qualified-revspec>", rightRevision="<right-file-qualified-revspec>")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Pending Changes
|
|
58
|
+
|
|
59
|
+
Prefer tool-first:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
plastic_status()
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Manual shell fallback:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cm status --all
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
When pending changes include deletions, verify deleted paths in status output before checkin.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Shelving
|
|
2
|
+
|
|
3
|
+
## Save Work
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
cm shelveset create -c="Working on feature X"
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## List Shelves
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
cm find shelve "where owner='me'" --format="{shelveid} {date} {comment}"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Restore Work
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
cm shelveset apply sh:5
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Delete Shelve
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cm shelveset delete sh:5
|
|
25
|
+
```
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
## Branch Already Exists
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
cm find branch "where name='<branch-name>'"
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Cannot Switch (Pending Changes)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
cm shelveset create --all -c="Auto-save before switch"
|
|
13
|
+
cm switch --silent --noinput <branch-spec>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- In unattended mode, `pendingChanges="bring"` is blocked only when tracked pending changes exist.
|
|
17
|
+
- Private-only pending changes do not require interactive bring; `plastic_switchBranch` now performs a direct switch.
|
|
18
|
+
- `pendingChanges="shelve"` may report `There are no changes in the workspace` when pending items are private-only;
|
|
19
|
+
the tool recovers by skipping shelve and switching directly.
|
|
20
|
+
|
|
21
|
+
Agent preference: use runtime `plastic_*` methods first; keep shell commands as manual fallback.
|
|
22
|
+
|
|
23
|
+
## Code Review Creation Failed
|
|
24
|
+
|
|
25
|
+
- Use GUI or document changeset in plan/issue tracker.
|
|
26
|
+
|
|
27
|
+
## Reviewer Not Assigned
|
|
28
|
+
|
|
29
|
+
- Reviewer assignment is required for code review workflow.
|
|
30
|
+
- Preferred: gather branch/status via `plastic_status()` first, then assign reviewer in review edit flow.
|
|
31
|
+
- Shell fallback:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
cm codereview -e <review-id> --reviewer="reviewer-name"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- If the reviewer flag differs in your server, use `cm codereview --help` and apply the equivalent reviewer option.
|
|
38
|
+
|
|
39
|
+
## GUI Opens When Using cm diff
|
|
40
|
+
|
|
41
|
+
- `cm diff` is blocked in Pi because it can launch GUI windows and hang the CLI.
|
|
42
|
+
- Use text-only alternatives:
|
|
43
|
+
- `plastic_status(machineReadable=true)` for changed paths/statuses.
|
|
44
|
+
- `plastic_diffFile(path="<workspace-path>")` for the common workspace-base comparison.
|
|
45
|
+
- `plastic_diffFile(path="<workspace-path>", revision="cs:<number>")` for an explicit supported revision.
|
|
46
|
+
- `plastic_diffRevisions(leftRevision="<left-file-qualified-revspec>", rightRevision="<right-file-qualified-revspec>")` for two historical files.
|
|
47
|
+
|
|
48
|
+
## GUI/Prompt Opens During Merge
|
|
49
|
+
|
|
50
|
+
- Do not run interactive `cm merge --merge` in Pi.
|
|
51
|
+
- Preferred:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
plastic_merge(source="<source-branch-spec>")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- Shell fallback must be non-interactive and use safe auto-resolution:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cm merge <source-branch-spec> --merge --nointeractiveresolution --mergetype=try
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- Explicit override (only when intentional):
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
plastic_merge(source="<source-branch-spec>", strategy="destination")
|
|
67
|
+
plastic_merge(source="<source-branch-spec>", strategy="source")
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- If Plastic reports a delete/change directory conflict and you intentionally want to accept the source-side deletion, use:
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
plastic_resolveDeleteChangeConflict(paths=["<workspace-path>"], keepOnDisk=true)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- Then rerun `plastic_merge(...)`.
|
|
77
|
+
- Even when `plastic_merge(...)` reports success, run `plastic_status()` before checkin. Merge output is not authoritative if Plastic still reports merge state.
|
|
78
|
+
|
|
79
|
+
## Merge Checkin Says Merge Is Still In Progress
|
|
80
|
+
|
|
81
|
+
- Symptom:
|
|
82
|
+
- `plastic_merge(...)` reports `FILE_CONFLICT` paths or checkin later fails with a merge-in-progress error.
|
|
83
|
+
- The files have been reviewed/resolved and compile/tests pass.
|
|
84
|
+
- `plastic_status()` still shows pending merge metadata.
|
|
85
|
+
- Treat `plastic_status()` merge-state hints as the source of truth. Pending merge links are expected until checkin; explicit merge-in-progress hints are blockers.
|
|
86
|
+
- Recovery flow:
|
|
87
|
+
1. Run `plastic_status()` and inspect merge-state details plus any `FILE_CONFLICT` paths reported by `plastic_merge(...)`.
|
|
88
|
+
2. Resolve/review the listed files manually and run compile/tests as appropriate.
|
|
89
|
+
3. Run `plastic_finalizeMerge(source="<source-branch-spec>", strategy="destination")` to finalize Plastic merge metadata while preserving the reviewed destination/manual result. Use `strategy="source"` only when accepting source is intentional.
|
|
90
|
+
4. Run `plastic_status()` again.
|
|
91
|
+
5. Retry `plastic_checkin(...)` after merge-in-progress hints are gone.
|
|
92
|
+
- If you are unsure whether the reviewed workspace result will be preserved, create a shelveset before finalizing.
|
|
93
|
+
|
|
94
|
+
## Invalid cm diff --summary Usage
|
|
95
|
+
|
|
96
|
+
- Do not use `cm diff --summary`; this form is invalid.
|
|
97
|
+
- Also avoid all other `cm diff` forms in Pi.
|
|
98
|
+
- Use the same text-only alternatives listed above.
|
|
99
|
+
|
|
100
|
+
## Deleted Files Missing From Checkin
|
|
101
|
+
|
|
102
|
+
- Run `cm status --all` and confirm deleted items are listed before checkin.
|
|
103
|
+
- Use `plastic_checkin(preflight=true, paths=[...])` first; the tool can auto-rewrite moved/deleted file scopes to parent directories.
|
|
104
|
+
- If a path-scoped checkin is rejected as "not changed", rerun with `applyChanged=true` and a parent-directory scope.
|
|
105
|
+
- Re-run `cm status --all` just before checkin to validate scope.
|
|
106
|
+
|
|
107
|
+
## Checkin says "No changes" but files were expected
|
|
108
|
+
|
|
109
|
+
- `includeAll=true` does not include private items automatically.
|
|
110
|
+
- `plastic_checkin` now pre-checks machine-readable status and can auto-add safe private files in scope,
|
|
111
|
+
then retry checkin once when Plastic returns `There are no changes in the workspace`.
|
|
112
|
+
- If only sensitive private paths are found (for example `.env*`, key material, `.npmrc`, credentials/secrets JSON),
|
|
113
|
+
auto-add is blocked and the tool returns an actionable error requiring explicit add/include choice.
|
|
114
|
+
- Check JSON metadata fields (`decisionPath`, `prePendingSummary`, `postPendingSummary`, `autoAddedPrivatePaths`,
|
|
115
|
+
`blockedPrivateAutoAddPaths`) to understand what unattended recovery path was used.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Review Workspaces
|
|
2
|
+
|
|
3
|
+
## Strategy
|
|
4
|
+
|
|
5
|
+
- Use a separate review workspace for isolation.
|
|
6
|
+
- Reuse `-review-1` by default (Unity workspaces are large).
|
|
7
|
+
|
|
8
|
+
## Create or Reuse
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
main_workspace=$(basename "$PWD")
|
|
12
|
+
review_workspace_name="${main_workspace}-review-1"
|
|
13
|
+
review_workspace="../${review_workspace_name}"
|
|
14
|
+
|
|
15
|
+
if [ -d "$review_workspace" ]; then
|
|
16
|
+
cd "$review_workspace"
|
|
17
|
+
cm switch --silent --noinput "$review_branch" || {
|
|
18
|
+
cm shelveset create --all -c="Auto-shelve before review switch"
|
|
19
|
+
cm switch --silent --noinput "$review_branch"
|
|
20
|
+
}
|
|
21
|
+
else
|
|
22
|
+
repo_spec=$(cm status --wkconfig | grep "^Repository:" | cut -d: -f2- | xargs)
|
|
23
|
+
cm workspace create "$review_workspace_name" "$review_workspace" "$repo_spec"
|
|
24
|
+
cd "$review_workspace"
|
|
25
|
+
cm switch --silent --noinput "$review_branch"
|
|
26
|
+
fi
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Agent preference: use runtime `plastic_*` methods first for branch/status operations; keep shell commands as manual fallback.
|
|
30
|
+
|
|
31
|
+
## Cleanup
|
|
32
|
+
|
|
33
|
+
Only remove review workspaces when disk space is tight or requested.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
type SchemaNode = {
|
|
2
|
+
kind: string;
|
|
3
|
+
values?: unknown;
|
|
4
|
+
inner?: unknown;
|
|
5
|
+
metadata?: Record<string, unknown>;
|
|
6
|
+
optional(): SchemaNode;
|
|
7
|
+
describe(description: string): SchemaNode;
|
|
8
|
+
min(value: number): SchemaNode;
|
|
9
|
+
max(value: number): SchemaNode;
|
|
10
|
+
int(): SchemaNode;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function createSchemaNode(kind: string, values?: unknown, inner?: unknown): SchemaNode {
|
|
14
|
+
const node: SchemaNode = {
|
|
15
|
+
kind,
|
|
16
|
+
values,
|
|
17
|
+
inner,
|
|
18
|
+
metadata: {},
|
|
19
|
+
optional() {
|
|
20
|
+
this.metadata = { ...(this.metadata ?? {}), optional: true };
|
|
21
|
+
return this;
|
|
22
|
+
},
|
|
23
|
+
describe(description: string) {
|
|
24
|
+
this.metadata = { ...(this.metadata ?? {}), description };
|
|
25
|
+
return this;
|
|
26
|
+
},
|
|
27
|
+
min(value: number) {
|
|
28
|
+
this.metadata = { ...(this.metadata ?? {}), min: value };
|
|
29
|
+
return this;
|
|
30
|
+
},
|
|
31
|
+
max(value: number) {
|
|
32
|
+
this.metadata = { ...(this.metadata ?? {}), max: value };
|
|
33
|
+
return this;
|
|
34
|
+
},
|
|
35
|
+
int() {
|
|
36
|
+
this.metadata = { ...(this.metadata ?? {}), int: true };
|
|
37
|
+
return this;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
return node;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const tool = Object.assign(
|
|
44
|
+
<T extends Record<string, unknown>>(definition: T): T => definition,
|
|
45
|
+
{
|
|
46
|
+
schema: {
|
|
47
|
+
string: () => createSchemaNode("string"),
|
|
48
|
+
number: () => createSchemaNode("number"),
|
|
49
|
+
boolean: () => createSchemaNode("boolean"),
|
|
50
|
+
any: () => createSchemaNode("any"),
|
|
51
|
+
enum: (values: readonly unknown[]) => createSchemaNode("enum", [...values]),
|
|
52
|
+
union: (values: readonly unknown[]) => createSchemaNode("union", [...values]),
|
|
53
|
+
array: (inner: unknown) => createSchemaNode("array", undefined, inner),
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
);
|