@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.
Files changed (54) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +8 -7
  3. package/extensions/bash-cm-diff-guard.ts +2 -1
  4. package/extensions/file-discovery-filter.ts +67 -0
  5. package/index.ts +12 -0
  6. package/package.json +7 -8
  7. package/skills/_shared/references/conventional-commits.md +198 -198
  8. package/skills/using-plastic/SKILL.md +2 -2
  9. package/skills/using-plastic/references/changeset-operations.md +2 -1
  10. package/skills/using-plastic/references/code-review-creation.md +30 -30
  11. package/skills/using-plastic/references/integration.md +2 -1
  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 +4 -3
  15. package/skills/using-plastic/references/shelving.md +25 -25
  16. package/skills/using-plastic/references/troubleshooting.md +2 -1
  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 +438 -152
  21. package/src/plastic-tool-loading.ts +2 -1
  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,23 @@ 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.0] - 2026-08-05
9
+
10
+ ### Added
11
+
12
+ - 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.
13
+
14
+ ### Changed
15
+
16
+ - 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.
17
+ - 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.
18
+ - 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`.
19
+
20
+ - 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.
21
+ - 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.
22
+ - Excluded development-only tests and behavioral evals from published npm artifacts.
23
+ - Publish verified GitHub releases to npm through resumable OIDC trusted-publishing automation, and canonicalized the package repository URL for GitHub identity matching.
24
+
8
25
  ## [0.4.0] - 2026-08-01
9
26
 
10
27
  ### 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,7 @@ 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, `plastic_diffFile` for one file, `plastic_workspaceDiff` for pending review, or `plastic_diffRevisions` for an explicit historical pair.
74
75
  - `plastic_patch` generates review patches with `cm patch`, including `clean` and `integration` filters for branch review workflows. It does not expose patch apply.
75
76
  - Bash safety rails block `cm diff` and unsafe interactive `cm merge --merge` usage.
76
77
  - Merge tooling surfaces Plastic `FILE_CONFLICT` records and merge-state metadata from `cm status`.
@@ -129,9 +130,9 @@ pi install -l <path-to-pi-plastic>
129
130
  - Node.js 22.19.0 or newer
130
131
  - Pi 0.82.0 or newer; the current development and eval baseline is Pi 0.83
131
132
  - 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
133
+ - 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
134
  - 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.
135
+ - `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
136
 
136
137
  ## Testing
137
138
 
@@ -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` to list changed paths, `plastic_diffFile` for one file, `plastic_workspaceDiff` for pending review, or `plastic_diffRevisions` for two explicit revisions.";
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",
@@ -181,6 +182,17 @@ const TOOL_CONFIG: Partial<Record<PlasticExportName, ToolConfig>> = {
181
182
  return input;
182
183
  },
183
184
  },
185
+ workspaceDiff: {
186
+ prepareArguments(args) {
187
+ const input = normalizeOutputFormatAlias(normalizeArgs(args));
188
+ normalizeWorkdirAliases(input);
189
+ promoteSinglePath(input);
190
+ assignAlias(input, "paths", ["items", "files"]);
191
+ assignAlias(input, "includePrivate", ["include_private"]);
192
+ assignAlias(input, "maxFiles", ["max_files"]);
193
+ return input;
194
+ },
195
+ },
184
196
  branchCreate: {
185
197
  prepareArguments(args) {
186
198
  const input = normalizeArgs(args);
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.0",
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": {
@@ -1,198 +1,198 @@
1
- # Conventional Commits
2
-
3
- This reference file documents the conventional commit format used across the project.
4
-
5
- ---
6
-
7
- ## Format
8
-
9
- ```
10
- <type>(<scope>): <subject>
11
-
12
- [optional body]
13
-
14
- [optional footer]
15
- ```
16
-
17
- ---
18
-
19
- ## Types
20
-
21
- | Type | Description | Example |
22
- |------|-------------|---------|
23
- | **feat** | New feature | `feat(auth): add OAuth login` |
24
- | **fix** | Bug fix | `fix(cart): calculate tax correctly` |
25
- | **refactor** | Code restructuring (no behavior change) | `refactor(api): extract service layer` |
26
- | **perf** | Performance improvement | `perf(query): optimize user lookup` |
27
- | **test** | Adding or updating tests | `test(auth): add login edge cases` |
28
- | **docs** | Documentation changes | `docs(readme): update installation steps` |
29
- | **style** | Code style changes (formatting, etc.) | `style(lint): fix indentation` |
30
- | **chore** | Build process or auxiliary tool changes | `chore(deps): update to Rails 7.1` |
31
- | **ci** | CI/CD configuration changes | `ci(github): add test workflow` |
32
-
33
- ---
34
-
35
- ## Scope
36
-
37
- The scope is optional but recommended. It specifies which part of the codebase was affected:
38
-
39
- **Examples:**
40
- - `feat(player): add dash mechanic`
41
- - `fix(inventory): prevent negative quantities`
42
- - `refactor(ui): simplify menu navigation`
43
- - `perf(rendering): batch sprite draws`
44
-
45
- **Guidelines:**
46
- - Use lowercase
47
- - Be specific but concise
48
- - Match your module/component names
49
- - Omit if change is global
50
-
51
- ---
52
-
53
- ## Subject
54
-
55
- The subject contains a succinct description of the change:
56
-
57
- - **Use imperative mood:** "add" not "added" or "adds"
58
- - **Don't capitalize first letter:** "add feature" not "Add feature"
59
- - **No period at the end:** "fix bug" not "fix bug."
60
- - **Limit to 50 characters**
61
-
62
- **Good examples:**
63
- - `feat(auth): add password reset flow`
64
- - `fix(api): handle null responses`
65
- - `refactor(utils): extract string helpers`
66
-
67
- **Bad examples:**
68
- - `feat(auth): Added password reset flow` (not imperative)
69
- - `feat(auth): Add Password Reset Flow` (capitalized)
70
- - `feat(auth): add password reset flow.` (period at end)
71
-
72
- ---
73
-
74
- ## Body (Optional)
75
-
76
- Use the body to explain **what** and **why**, not **how**:
77
-
78
- ```
79
- feat(player): add dash mechanic
80
-
81
- Adds a dash ability to the player character for enhanced mobility.
82
- Dash has 1-second cooldown and consumes 10 stamina.
83
-
84
- Closes #42
85
- ```
86
-
87
- **Guidelines:**
88
- - Wrap at 72 characters
89
- - Separate from subject with blank line
90
- - Focus on context and reasoning
91
- - Link to issues if applicable
92
-
93
- ---
94
-
95
- ## Footer (Optional)
96
-
97
- Use footer for metadata:
98
-
99
- **Breaking changes:**
100
- ```
101
- feat(api)!: change authentication endpoint
102
-
103
- BREAKING CHANGE: /api/login now requires email instead of username
104
- ```
105
-
106
- **Issue references:**
107
- ```
108
- fix(cart): calculate tax correctly
109
-
110
- Fixes #123
111
- Closes #124
112
- Related to #125
113
- ```
114
-
115
- **Attribution:**
116
- ```
117
- feat(dashboard): add analytics widget
118
-
119
- Co-Authored-By: <AI Assistant Name (e.g., Codex, Claude, Pi Coding Agent)>
120
- ```
121
-
122
- ---
123
-
124
- ## Attribution Footer
125
-
126
- Add a simple attribution line in the footer when needed:
127
-
128
- ```
129
- feat(feature): implement new capability
130
-
131
- [Body explaining the change]
132
-
133
- Co-Authored-By: <AI Assistant Name (e.g., Codex, Claude, Pi Coding Agent)>
134
- ```
135
-
136
- ---
137
-
138
- ## Examples
139
-
140
- ### Simple Feature
141
- ```
142
- feat(player): add jump mechanic
143
- ```
144
-
145
- ### Bug Fix with Context
146
- ```
147
- fix(inventory): prevent item duplication
148
-
149
- Items were duplicating when rapidly clicking the pickup button.
150
- Added debounce logic to prevent double-processing.
151
-
152
- Fixes #156
153
- ```
154
-
155
- ### Refactor with Explanation
156
- ```
157
- refactor(rendering): extract camera controller
158
-
159
- Moved camera logic from PlayerController to dedicated CameraController
160
- for better separation of concerns and reusability.
161
- ```
162
-
163
- ### Performance Improvement
164
- ```
165
- perf(physics): optimize collision detection
166
-
167
- Changed from O(n²) all-pairs check to spatial hashing.
168
- Reduces frame time by ~15ms with 100+ objects.
169
- ```
170
-
171
- ### Attribution Example
172
- ```
173
- feat(multiplayer): add lobby system
174
-
175
- Implements matchmaking lobby with room creation, joining, and ready-up.
176
- Uses WebSocket for real-time updates.
177
-
178
- Closes #89
179
-
180
- Co-Authored-By: <AI Assistant Name (e.g., Codex, Claude, Pi Coding Agent)>
181
- ```
182
-
183
- ---
184
-
185
- ## Usage in Skills
186
-
187
- **Reference this file when:**
188
- - Creating commits (Git or Plastic)
189
- - Generating commit messages
190
- - Validating commit format
191
- - Writing PR/code review descriptions
192
-
193
- **Load this file:**
194
- ```markdown
195
- Load conventional commit format from ../../_shared/references/conventional-commits.md
196
- ```
197
-
198
- Then format all commits according to this standard.
1
+ # Conventional Commits
2
+
3
+ This reference file documents the conventional commit format used across the project.
4
+
5
+ ---
6
+
7
+ ## Format
8
+
9
+ ```
10
+ <type>(<scope>): <subject>
11
+
12
+ [optional body]
13
+
14
+ [optional footer]
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Types
20
+
21
+ | Type | Description | Example |
22
+ |------|-------------|---------|
23
+ | **feat** | New feature | `feat(auth): add OAuth login` |
24
+ | **fix** | Bug fix | `fix(cart): calculate tax correctly` |
25
+ | **refactor** | Code restructuring (no behavior change) | `refactor(api): extract service layer` |
26
+ | **perf** | Performance improvement | `perf(query): optimize user lookup` |
27
+ | **test** | Adding or updating tests | `test(auth): add login edge cases` |
28
+ | **docs** | Documentation changes | `docs(readme): update installation steps` |
29
+ | **style** | Code style changes (formatting, etc.) | `style(lint): fix indentation` |
30
+ | **chore** | Build process or auxiliary tool changes | `chore(deps): update to Rails 7.1` |
31
+ | **ci** | CI/CD configuration changes | `ci(github): add test workflow` |
32
+
33
+ ---
34
+
35
+ ## Scope
36
+
37
+ The scope is optional but recommended. It specifies which part of the codebase was affected:
38
+
39
+ **Examples:**
40
+ - `feat(player): add dash mechanic`
41
+ - `fix(inventory): prevent negative quantities`
42
+ - `refactor(ui): simplify menu navigation`
43
+ - `perf(rendering): batch sprite draws`
44
+
45
+ **Guidelines:**
46
+ - Use lowercase
47
+ - Be specific but concise
48
+ - Match your module/component names
49
+ - Omit if change is global
50
+
51
+ ---
52
+
53
+ ## Subject
54
+
55
+ The subject contains a succinct description of the change:
56
+
57
+ - **Use imperative mood:** "add" not "added" or "adds"
58
+ - **Don't capitalize first letter:** "add feature" not "Add feature"
59
+ - **No period at the end:** "fix bug" not "fix bug."
60
+ - **Limit to 50 characters**
61
+
62
+ **Good examples:**
63
+ - `feat(auth): add password reset flow`
64
+ - `fix(api): handle null responses`
65
+ - `refactor(utils): extract string helpers`
66
+
67
+ **Bad examples:**
68
+ - `feat(auth): Added password reset flow` (not imperative)
69
+ - `feat(auth): Add Password Reset Flow` (capitalized)
70
+ - `feat(auth): add password reset flow.` (period at end)
71
+
72
+ ---
73
+
74
+ ## Body (Optional)
75
+
76
+ Use the body to explain **what** and **why**, not **how**:
77
+
78
+ ```
79
+ feat(player): add dash mechanic
80
+
81
+ Adds a dash ability to the player character for enhanced mobility.
82
+ Dash has 1-second cooldown and consumes 10 stamina.
83
+
84
+ Closes #42
85
+ ```
86
+
87
+ **Guidelines:**
88
+ - Wrap at 72 characters
89
+ - Separate from subject with blank line
90
+ - Focus on context and reasoning
91
+ - Link to issues if applicable
92
+
93
+ ---
94
+
95
+ ## Footer (Optional)
96
+
97
+ Use footer for metadata:
98
+
99
+ **Breaking changes:**
100
+ ```
101
+ feat(api)!: change authentication endpoint
102
+
103
+ BREAKING CHANGE: /api/login now requires email instead of username
104
+ ```
105
+
106
+ **Issue references:**
107
+ ```
108
+ fix(cart): calculate tax correctly
109
+
110
+ Fixes #123
111
+ Closes #124
112
+ Related to #125
113
+ ```
114
+
115
+ **Attribution:**
116
+ ```
117
+ feat(dashboard): add analytics widget
118
+
119
+ Co-Authored-By: <AI Assistant Name (e.g., Codex, Claude, Pi Coding Agent)>
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Attribution Footer
125
+
126
+ Add a simple attribution line in the footer when needed:
127
+
128
+ ```
129
+ feat(feature): implement new capability
130
+
131
+ [Body explaining the change]
132
+
133
+ Co-Authored-By: <AI Assistant Name (e.g., Codex, Claude, Pi Coding Agent)>
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Examples
139
+
140
+ ### Simple Feature
141
+ ```
142
+ feat(player): add jump mechanic
143
+ ```
144
+
145
+ ### Bug Fix with Context
146
+ ```
147
+ fix(inventory): prevent item duplication
148
+
149
+ Items were duplicating when rapidly clicking the pickup button.
150
+ Added debounce logic to prevent double-processing.
151
+
152
+ Fixes #156
153
+ ```
154
+
155
+ ### Refactor with Explanation
156
+ ```
157
+ refactor(rendering): extract camera controller
158
+
159
+ Moved camera logic from PlayerController to dedicated CameraController
160
+ for better separation of concerns and reusability.
161
+ ```
162
+
163
+ ### Performance Improvement
164
+ ```
165
+ perf(physics): optimize collision detection
166
+
167
+ Changed from O(n²) all-pairs check to spatial hashing.
168
+ Reduces frame time by ~15ms with 100+ objects.
169
+ ```
170
+
171
+ ### Attribution Example
172
+ ```
173
+ feat(multiplayer): add lobby system
174
+
175
+ Implements matchmaking lobby with room creation, joining, and ready-up.
176
+ Uses WebSocket for real-time updates.
177
+
178
+ Closes #89
179
+
180
+ Co-Authored-By: <AI Assistant Name (e.g., Codex, Claude, Pi Coding Agent)>
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Usage in Skills
186
+
187
+ **Reference this file when:**
188
+ - Creating commits (Git or Plastic)
189
+ - Generating commit messages
190
+ - Validating commit format
191
+ - Writing PR/code review descriptions
192
+
193
+ **Load this file:**
194
+ ```markdown
195
+ Load conventional commit format from ../../_shared/references/conventional-commits.md
196
+ ```
197
+
198
+ Then format all commits according to this standard.