@piagent/platform 1.0.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 (159) hide show
  1. package/.gitattributes +7 -0
  2. package/AGENTS.md +31 -0
  3. package/CHANGELOG.md +296 -0
  4. package/CODE_OF_CONDUCT.md +36 -0
  5. package/CONTRIBUTING.md +66 -0
  6. package/LICENSE +21 -0
  7. package/README.md +588 -0
  8. package/SECURITY.md +38 -0
  9. package/adapters/backend-api/profile.json +88 -0
  10. package/adapters/be-readonly-fe/profile.json +120 -0
  11. package/adapters/data/profile.json +88 -0
  12. package/adapters/devops/profile.json +92 -0
  13. package/adapters/docs/profile.json +74 -0
  14. package/adapters/fullstack/profile.json +94 -0
  15. package/adapters/generic/profile.json +95 -0
  16. package/adapters/mobile/profile.json +87 -0
  17. package/adapters/node-typescript/profile.json +76 -0
  18. package/adapters/python/profile.json +75 -0
  19. package/adapters/web-frontend/profile.json +101 -0
  20. package/catalog/capabilities.json +206 -0
  21. package/docs/architecture.md +64 -0
  22. package/docs/auto-delegation-policy.md +192 -0
  23. package/docs/capability-packs.md +234 -0
  24. package/docs/command-reference-vietnamese.md +484 -0
  25. package/docs/context-window-policy.md +85 -0
  26. package/docs/distribution-standard.md +229 -0
  27. package/docs/herdr-workflow.md +58 -0
  28. package/docs/mcp-and-tools.md +316 -0
  29. package/docs/memory-policy.md +164 -0
  30. package/docs/model-options.md +165 -0
  31. package/docs/oauth-providers.md +53 -0
  32. package/docs/operator-manual-vietnamese.md +1080 -0
  33. package/docs/package-architecture-notes.md +101 -0
  34. package/docs/project-adapters.md +174 -0
  35. package/docs/project-onboarding.md +135 -0
  36. package/docs/publishing-for-teams.md +64 -0
  37. package/docs/quality-benchmark.md +74 -0
  38. package/docs/quickstart-vietnamese.md +350 -0
  39. package/docs/release-install-policy.md +223 -0
  40. package/docs/runtime-harness-standard.md +118 -0
  41. package/docs/runtime-policy-design.md +132 -0
  42. package/docs/runtime-quality-baseline.md +257 -0
  43. package/docs/security-redaction-benchmark.md +56 -0
  44. package/docs/security-threat-model.md +66 -0
  45. package/docs/subagent-orchestration-capabilities.md +104 -0
  46. package/docs/subagents-and-multiagent.md +346 -0
  47. package/docs/task-implementation-contract.md +200 -0
  48. package/docs/team-onboarding.md +333 -0
  49. package/docs/usage-observability.md +130 -0
  50. package/docs/vercel-docs-site.md +115 -0
  51. package/docs/workflow-recipes.md +125 -0
  52. package/docs-site/assets/piagent-logo.svg +35 -0
  53. package/docs-site/favicon.svg +18 -0
  54. package/docs-site/index.html +1613 -0
  55. package/docs-site/vercel.json +24 -0
  56. package/evals/fixtures/action-proposal.invalid.json +34 -0
  57. package/evals/fixtures/action-proposal.valid.json +34 -0
  58. package/evals/fixtures/capability-pack.invalid.json +123 -0
  59. package/evals/fixtures/capability-pack.valid.json +123 -0
  60. package/evals/fixtures/capability-recipe.invalid.json +81 -0
  61. package/evals/fixtures/capability-recipe.valid.json +82 -0
  62. package/evals/fixtures/context-index.invalid.json +25 -0
  63. package/evals/fixtures/context-index.valid.json +25 -0
  64. package/evals/fixtures/eval-scenario.invalid.json +40 -0
  65. package/evals/fixtures/eval-scenario.valid.json +45 -0
  66. package/evals/fixtures/project-profile.invalid.json +88 -0
  67. package/evals/fixtures/project-profile.valid.json +95 -0
  68. package/evals/fixtures/task-contract.invalid.json +73 -0
  69. package/evals/fixtures/task-contract.valid.json +74 -0
  70. package/evals/golden/enforcement-decisions.json +329 -0
  71. package/evals/scenarios/capability-resolution.json +45 -0
  72. package/package.json +132 -0
  73. package/packages/piagent-core/README.md +147 -0
  74. package/packages/piagent-core/capabilities/capability-core.js +1023 -0
  75. package/packages/piagent-core/capabilities/capability-sources.js +265 -0
  76. package/packages/piagent-core/extensions/guard-io.js +45 -0
  77. package/packages/piagent-core/extensions/guard-shell-analysis.ts +558 -0
  78. package/packages/piagent-core/extensions/guard-types.ts +406 -0
  79. package/packages/piagent-core/extensions/piagent-guard.ts +5760 -0
  80. package/packages/piagent-core/extensions/policy-core.js +1070 -0
  81. package/packages/piagent-core/extensions/redaction-core.js +4 -0
  82. package/packages/piagent-core/extensions/runtime-evidence.js +215 -0
  83. package/packages/piagent-core/package.json +46 -0
  84. package/packages/piagent-core/policies/base-policy.json +249 -0
  85. package/packages/piagent-core/prompts/be-to-fe.md +82 -0
  86. package/packages/piagent-core/prompts/commit.md +27 -0
  87. package/packages/piagent-core/prompts/discuss.md +35 -0
  88. package/packages/piagent-core/prompts/memory-policy.md +52 -0
  89. package/packages/piagent-core/prompts/model-options.md +68 -0
  90. package/packages/piagent-core/prompts/onboard-project.md +147 -0
  91. package/packages/piagent-core/prompts/piagent-commands.md +68 -0
  92. package/packages/piagent-core/prompts/plan.md +35 -0
  93. package/packages/piagent-core/prompts/platform-improve.md +69 -0
  94. package/packages/piagent-core/prompts/pr.md +26 -0
  95. package/packages/piagent-core/prompts/review.md +38 -0
  96. package/packages/piagent-core/prompts/scout.md +50 -0
  97. package/packages/piagent-core/prompts/task.md +69 -0
  98. package/packages/piagent-core/security/sensitive-data.js +187 -0
  99. package/packages/piagent-core/skills/piagent-ops/SKILL.md +44 -0
  100. package/packages/piagent-core/skills/piagent-source-cache/SKILL.md +59 -0
  101. package/packages/piagent-core/skills/piagent-source-cache/checkout-source-repo.sh +144 -0
  102. package/packages/piagent-core/subagents/piagent-oracle.md +29 -0
  103. package/packages/piagent-core/subagents/piagent-planner.md +46 -0
  104. package/packages/piagent-core/subagents/piagent-reviewer.md +48 -0
  105. package/packages/piagent-core/subagents/piagent-scout.md +37 -0
  106. package/packages/piagent-core/subagents/piagent-worker.md +44 -0
  107. package/packs/engineering-base/pack.json +123 -0
  108. package/packs/engineering-base/recipes/bounded-change.json +82 -0
  109. package/packs/web-delivery/pack.json +72 -0
  110. package/packs/web-delivery/recipes/verified-web-change.json +57 -0
  111. package/schemas/action-proposal.schema.json +90 -0
  112. package/schemas/capability-pack.schema.json +190 -0
  113. package/schemas/capability-recipe.schema.json +72 -0
  114. package/schemas/context-index.schema.json +258 -0
  115. package/schemas/eval-scenario.schema.json +67 -0
  116. package/schemas/project-profile.schema.json +555 -0
  117. package/schemas/task-contract.schema.json +314 -0
  118. package/scripts/audit-runtime-host.sh +78 -0
  119. package/scripts/bootstrap-local.sh +25 -0
  120. package/scripts/capability-catalog.mjs +290 -0
  121. package/scripts/check-runtime-advisories.mjs +114 -0
  122. package/scripts/configure-mcp.sh +301 -0
  123. package/scripts/configure-model-scope.sh +143 -0
  124. package/scripts/configure-subagents.sh +241 -0
  125. package/scripts/import-agent-instructions.mjs +199 -0
  126. package/scripts/init-project.sh +369 -0
  127. package/scripts/install-global.sh +532 -0
  128. package/scripts/link-project.sh +25 -0
  129. package/scripts/migrate-project-state.mjs +176 -0
  130. package/scripts/pi-auto.sh +79 -0
  131. package/scripts/pi-model-catalog.sh +154 -0
  132. package/scripts/pi-session-stats.sh +135 -0
  133. package/scripts/piagent-cli.mjs +53 -0
  134. package/scripts/profile-doctor.sh +238 -0
  135. package/scripts/quality-benchmark.sh +185 -0
  136. package/scripts/redaction-benchmark.mjs +227 -0
  137. package/scripts/runtime-policy-smoke.sh +48 -0
  138. package/scripts/setup.sh +425 -0
  139. package/scripts/team-doctor.sh +461 -0
  140. package/scripts/verify-local.sh +540 -0
  141. package/scripts/verify-release-identity.mjs +85 -0
  142. package/scripts/verify-vercel-link.mjs +64 -0
  143. package/templates/global/mcp.json +9 -0
  144. package/templates/global/settings.json +37 -0
  145. package/templates/project/.mcp.json +9 -0
  146. package/templates/project/.pi/context-index.json +25 -0
  147. package/templates/project/.pi/gitignore.template +22 -0
  148. package/templates/project/.pi/mcp.json +9 -0
  149. package/templates/project/.pi/memory/MEMORY.md +11 -0
  150. package/templates/project/.pi/memory/memory_summary.md +9 -0
  151. package/templates/project/.pi/piagent-profile.json +107 -0
  152. package/templates/project/.pi/project-context.md +30 -0
  153. package/templates/project/.pi/settings.json +17 -0
  154. package/templates/project/.pi/task-contract.template.json +74 -0
  155. package/templates/project/.pi/tech-context/README.md +7 -0
  156. package/templates/project/.pi/tech-stack.json +10 -0
  157. package/templates/project/AGENTS.md +34 -0
  158. package/templates/project/REVIEW_GUIDELINES.md +23 -0
  159. package/types/pi-runtime-shims.d.ts +13 -0
@@ -0,0 +1,4 @@
1
+ export {
2
+ redactForStorage,
3
+ redactSensitiveText
4
+ } from "../security/sensitive-data.js";
@@ -0,0 +1,215 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { redactSensitiveText } from "../security/sensitive-data.js";
5
+
6
+ export function normalizeEvidenceCommand(command) {
7
+ return String(command ?? "")
8
+ .replace(/\r\n/g, "\n")
9
+ .trim();
10
+ }
11
+
12
+ export function hashEvidenceCommand(command) {
13
+ return crypto
14
+ .createHash("sha256")
15
+ .update(normalizeEvidenceCommand(command))
16
+ .digest("hex");
17
+ }
18
+
19
+ export function commandMatchesVerifyPlan(command, verifyCommands) {
20
+ const normalized = normalizeEvidenceCommand(command);
21
+ if (!normalized || !Array.isArray(verifyCommands)) return false;
22
+ return verifyCommands.some((verifyCommand) => normalizeEvidenceCommand(verifyCommand) === normalized);
23
+ }
24
+
25
+ function normalizeCwd(cwd) {
26
+ return String(cwd ?? "").trim();
27
+ }
28
+
29
+ function parseTimeMs(value, fallback = Date.now()) {
30
+ if (typeof value === "number" && Number.isFinite(value)) return value;
31
+ const parsed = Date.parse(String(value ?? ""));
32
+ return Number.isFinite(parsed) ? parsed : fallback;
33
+ }
34
+
35
+ function numericExitCode(value) {
36
+ if (typeof value === "number" && Number.isInteger(value)) return value;
37
+ if (typeof value === "string" && /^-?\d+$/.test(value.trim())) return Number.parseInt(value, 10);
38
+ return undefined;
39
+ }
40
+
41
+ export function claimedExitMatchesObserved(exitCode, observed) {
42
+ const claimed = numericExitCode(exitCode);
43
+ if (claimed === undefined) return false;
44
+ if (typeof observed?.exitCode === "number") return observed.exitCode === claimed;
45
+ return observed?.isError === true ? claimed !== 0 : claimed === 0;
46
+ }
47
+
48
+ export function extractBashCommandFromToolResultEvent(event) {
49
+ if (!event || event.toolName !== "bash") return "";
50
+ const input = event.input;
51
+ if (input && typeof input.command === "string") return input.command;
52
+ if (input && typeof input === "object" && input.args && typeof input.args.command === "string") return input.args.command;
53
+ return "";
54
+ }
55
+
56
+ export function observedBashResultFromToolResultEvent(event, cwd, nowMs = Date.now()) {
57
+ const command = extractBashCommandFromToolResultEvent(event);
58
+ const normalizedCommand = normalizeEvidenceCommand(command);
59
+ if (!normalizedCommand) return undefined;
60
+ const commandHash = hashEvidenceCommand(normalizedCommand);
61
+ const exitCode = numericExitCode(event?.details?.exitCode ?? event?.details?.status ?? event?.exitCode);
62
+ const recordedAtMs = parseTimeMs(event?.timestamp, nowMs);
63
+ return {
64
+ cwd: normalizeCwd(cwd),
65
+ command: redactSensitiveText(command).text,
66
+ normalizedCommand: redactSensitiveText(normalizedCommand).text,
67
+ commandHash,
68
+ isError: event?.isError === true,
69
+ exitCode,
70
+ recordedAt: new Date(recordedAtMs).toISOString(),
71
+ recordedAtMs,
72
+ toolCallId: event?.toolCallId ?? event?.id
73
+ };
74
+ }
75
+
76
+ function canonicalObservedEntry(entry) {
77
+ const rawNormalizedCommand = normalizeEvidenceCommand(entry?.normalizedCommand ?? entry?.command);
78
+ const commandHash = entry?.commandHash || (rawNormalizedCommand ? hashEvidenceCommand(rawNormalizedCommand) : "");
79
+ if (!commandHash) return undefined;
80
+ const command = typeof entry?.command === "string" ? redactSensitiveText(entry.command).text : "";
81
+ const normalizedCommand = redactSensitiveText(rawNormalizedCommand).text;
82
+ const recordedAtMs = parseTimeMs(entry?.recordedAtMs ?? entry?.recordedAt);
83
+ return {
84
+ cwd: normalizeCwd(entry?.cwd),
85
+ command,
86
+ normalizedCommand,
87
+ commandHash,
88
+ isError: entry?.isError === true,
89
+ exitCode: numericExitCode(entry?.exitCode),
90
+ recordedAt: entry?.recordedAt ?? new Date(recordedAtMs).toISOString(),
91
+ recordedAtMs,
92
+ toolCallId: entry?.toolCallId
93
+ };
94
+ }
95
+
96
+ function observedCommandsMatch(entry, normalizedCommand, commandHash) {
97
+ if (entry.commandHash) return entry.commandHash === commandHash;
98
+ return normalizeEvidenceCommand(entry.normalizedCommand ?? entry.command) === normalizedCommand;
99
+ }
100
+
101
+ export function findMatchingObservedBashResult(entries, { cwd, command, notBefore, exitCode }) {
102
+ const normalizedCommand = normalizeEvidenceCommand(command);
103
+ const commandHash = hashEvidenceCommand(normalizedCommand);
104
+ const normalizedCwd = normalizeCwd(cwd);
105
+ const notBeforeMs = notBefore ? parseTimeMs(notBefore, 0) : 0;
106
+ if (!normalizedCommand) {
107
+ return { ok: false, reason: "Verify command is empty after normalization." };
108
+ }
109
+
110
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
111
+ const entry = canonicalObservedEntry(entries[index]);
112
+ if (!entry) continue;
113
+ if (entry.cwd !== normalizedCwd) continue;
114
+ if (!observedCommandsMatch(entry, normalizedCommand, commandHash)) continue;
115
+ if (entry.recordedAtMs < notBeforeMs) continue;
116
+ if (!claimedExitMatchesObserved(exitCode, entry)) {
117
+ return {
118
+ ok: false,
119
+ reason: `Observed command status does not match claimed exitCode ${exitCode}.`,
120
+ entry
121
+ };
122
+ }
123
+ return { ok: true, entry };
124
+ }
125
+
126
+ return {
127
+ ok: false,
128
+ reason: "No matching bash tool_result observed for this command after task start."
129
+ };
130
+ }
131
+
132
+ function persistedObservedEntry(entry) {
133
+ const observed = canonicalObservedEntry(entry);
134
+ if (!observed) return undefined;
135
+ const command = typeof entry?.redactedCommand === "string"
136
+ ? redactSensitiveText(entry.redactedCommand).text
137
+ : observed.command;
138
+ return {
139
+ schemaVersion: 1,
140
+ cwd: observed.cwd,
141
+ commandHash: observed.commandHash,
142
+ command,
143
+ isError: observed.isError,
144
+ exitCode: observed.exitCode,
145
+ recordedAt: observed.recordedAt,
146
+ recordedAtMs: observed.recordedAtMs,
147
+ toolCallId: observed.toolCallId
148
+ };
149
+ }
150
+
151
+ export function readObservedBashResults(filePath, options = {}) {
152
+ if (!filePath || !fs.existsSync(filePath)) return [];
153
+ const maxEntries = Number.isInteger(options.maxEntries) ? options.maxEntries : 5000;
154
+ const text = fs.readFileSync(filePath, "utf8");
155
+ const entries = [];
156
+ for (const line of text.split(/\n/)) {
157
+ const trimmed = line.trim();
158
+ if (!trimmed) continue;
159
+ try {
160
+ const parsed = JSON.parse(trimmed);
161
+ const entry = canonicalObservedEntry(parsed);
162
+ if (entry) entries.push(entry);
163
+ } catch {
164
+ // Ignore a partially written/corrupt JSONL line. The ledger is advisory evidence,
165
+ // and the final gate remains fail-closed when no valid observation is available.
166
+ }
167
+ }
168
+ return entries.slice(-maxEntries);
169
+ }
170
+
171
+ function pruneObservedBashFile(filePath, maxPersistedEntries) {
172
+ if (!Number.isInteger(maxPersistedEntries) || maxPersistedEntries <= 0) return;
173
+ const entries = readObservedBashResults(filePath, { maxEntries: maxPersistedEntries });
174
+ const lines = entries.map((entry) => JSON.stringify(persistedObservedEntry(entry))).filter(Boolean);
175
+ fs.writeFileSync(filePath, `${lines.join("\n")}${lines.length ? "\n" : ""}`);
176
+ }
177
+
178
+ export function appendObservedBashResult(filePath, entry, options = {}) {
179
+ if (!filePath) return undefined;
180
+ const persisted = persistedObservedEntry(entry);
181
+ if (!persisted) return undefined;
182
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
183
+ fs.appendFileSync(filePath, `${JSON.stringify(persisted)}\n`);
184
+ if (Number.isInteger(options.maxPersistedEntries)) {
185
+ pruneObservedBashFile(filePath, options.maxPersistedEntries);
186
+ }
187
+ return persisted;
188
+ }
189
+
190
+ export function createBashResultLedger(options = {}) {
191
+ const maxEntries = Number.isInteger(options.maxEntries) ? options.maxEntries : 300;
192
+ const entries = [];
193
+
194
+ function prune() {
195
+ while (entries.length > maxEntries) entries.shift();
196
+ }
197
+
198
+ return {
199
+ record(entry) {
200
+ const observed = canonicalObservedEntry(entry);
201
+ if (!observed) return undefined;
202
+ entries.push(observed);
203
+ prune();
204
+ return observed;
205
+ },
206
+
207
+ findMatching({ cwd, command, notBefore, exitCode }) {
208
+ return findMatchingObservedBashResult(entries, { cwd, command, notBefore, exitCode });
209
+ },
210
+
211
+ list() {
212
+ return entries.map((entry) => ({ ...entry }));
213
+ }
214
+ };
215
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@piagent/core",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "private": true,
6
+ "license": "MIT",
7
+ "description": "Pi agent package: guard extension, prompts, skills, and policy defaults.",
8
+ "homepage": "https://piagent.io.vn",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/Vt-mmm/piagent.git",
12
+ "directory": "packages/piagent-core"
13
+ },
14
+ "keywords": [
15
+ "pi-package",
16
+ "coding-agent",
17
+ "agent-harness"
18
+ ],
19
+ "pi": {
20
+ "extensions": [
21
+ "extensions/piagent-guard.ts"
22
+ ],
23
+ "skills": [
24
+ "skills"
25
+ ],
26
+ "prompts": [
27
+ "prompts"
28
+ ],
29
+ "subagents": {
30
+ "agents": [
31
+ "subagents"
32
+ ]
33
+ }
34
+ },
35
+ "peerDependencies": {
36
+ "@earendil-works/pi-coding-agent": "0.81.1",
37
+ "typebox": "1.1.38"
38
+ },
39
+ "peerDependenciesMeta": {
40
+ "@earendil-works/pi-coding-agent": { "optional": true },
41
+ "typebox": { "optional": true }
42
+ },
43
+ "engines": {
44
+ "node": ">=22.19.0"
45
+ }
46
+ }
@@ -0,0 +1,249 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "name": "piagent-base-policy",
4
+ "protectedPaths": [
5
+ ".git/**",
6
+ "**/auth.json",
7
+ "**/.env",
8
+ "**/.env.*",
9
+ "**/node_modules/**",
10
+ "**/dist/**",
11
+ ".pi/piagent-state/**",
12
+ ".pi/settings.json",
13
+ ".pi/piagent-profile.json",
14
+ ".pi/piagent-profile.lock.json",
15
+ ".pi/context-index.json"
16
+ ],
17
+ "shellProtectedPaths": [
18
+ ".git/**",
19
+ "**/auth.json",
20
+ "**/.env",
21
+ "**/.env.*",
22
+ ".pi/piagent-state/**",
23
+ ".pi/settings.json",
24
+ ".pi/piagent-profile.json",
25
+ ".pi/piagent-profile.lock.json",
26
+ ".pi/context-index.json"
27
+ ],
28
+ "blockedCommandPatterns": [
29
+ "rm -rf /",
30
+ "rm -rf ~",
31
+ "rm -rf $HOME",
32
+ "git reset --hard",
33
+ "git clean -fd",
34
+ "sudo ",
35
+ "chmod -R 777"
36
+ ],
37
+ "requireConfirmationPatterns": [
38
+ "deploy",
39
+ "release",
40
+ "publish",
41
+ "migration",
42
+ "terraform apply",
43
+ "kubectl apply",
44
+ "gh pr merge",
45
+ "git push"
46
+ ],
47
+ "defaultRequiredContext": [
48
+ "AGENTS.md",
49
+ "README.md"
50
+ ],
51
+ "permissionProfiles": {
52
+ "defaultMode": "workspace-write",
53
+ "allowedModes": [
54
+ "read-only",
55
+ "workspace-write",
56
+ "trusted-full-access"
57
+ ]
58
+ },
59
+ "execPolicy": {
60
+ "defaultMode": "enforce",
61
+ "bannedPrefixSuggestions": [
62
+ ["python"],
63
+ ["python3"],
64
+ ["node"],
65
+ ["node", "-e"],
66
+ ["bash"],
67
+ ["bash", "-lc"],
68
+ ["sh"],
69
+ ["sh", "-c"],
70
+ ["zsh"],
71
+ ["zsh", "-lc"],
72
+ ["git"],
73
+ ["sudo"],
74
+ ["env"]
75
+ ],
76
+ "rules": [
77
+ {
78
+ "id": "prompt-git-add-broad",
79
+ "action": "prompt",
80
+ "match": "regex",
81
+ "value": "(?:^|\\s)git\\s+(?:-C\\s+\\S+\\s+)?add\\s+(?:(?:--all|-A)(?:\\s+(?:\\.|:/))?|--\\s+(?:\\.|:/)|(?:\\.|:/))(?:\\s|$)",
82
+ "reason": "Broad git staging can include unrelated or sensitive changes; inspect git status/diff and confirm the exact scope first."
83
+ },
84
+ {
85
+ "id": "forbid-docker-volume-prune",
86
+ "action": "forbid",
87
+ "match": "contains",
88
+ "value": "docker volume prune",
89
+ "reason": "Volume prune can delete unrecoverable local data."
90
+ },
91
+ {
92
+ "id": "prompt-docker-compose-down-volume",
93
+ "action": "prompt",
94
+ "match": "regex",
95
+ "value": "docker\\s+compose\\s+down\\s+.*-v",
96
+ "reason": "docker compose down -v removes volumes."
97
+ },
98
+ {
99
+ "id": "prompt-database-migration",
100
+ "action": "prompt",
101
+ "match": "contains",
102
+ "value": "migrate",
103
+ "reason": "Database migrations require explicit human confirmation."
104
+ }
105
+ ]
106
+ },
107
+ "contextBudget": {
108
+ "defaultMode": "enforce",
109
+ "maxContextFileChars": 50000,
110
+ "maxMemoryFileChars": 20000,
111
+ "maxManifestFiles": 80,
112
+ "warnFragmentChars": 4000
113
+ },
114
+ "toolRegistry": {
115
+ "defaultMode": "advisory",
116
+ "alwaysAllowedTools": [
117
+ "piagent_context",
118
+ "piagent_permission_status",
119
+ "piagent_exec_policy_check",
120
+ "piagent_context_budget",
121
+ "piagent_tool_policy_check",
122
+ "piagent_task_gate_check",
123
+ "piagent_usage_snapshot",
124
+ "piagent_orchestration_policy",
125
+ "piagent_memory_status",
126
+ "piagent_memory_note",
127
+ "piagent_memory_search",
128
+ "piagent_memory_citation_record",
129
+ "piagent_context_index_status",
130
+ "piagent_context_index_record",
131
+ "piagent_context_index_search",
132
+ "piagent_profile_options",
133
+ "piagent_profile_apply",
134
+ "piagent_profile_tech_options",
135
+ "piagent_profile_tech_apply",
136
+ "piagent_profile_tech_context_record",
137
+ "piagent_project_onboarding_record",
138
+ "piagent_task_start",
139
+ "piagent_source_checkout",
140
+ "piagent_context_record",
141
+ "piagent_verify_record",
142
+ "piagent_trace_record"
143
+ ],
144
+ "toolCapabilities": {
145
+ "bash": ["shell"],
146
+ "shell": ["shell"],
147
+ "exec": ["shell"],
148
+ "read": ["filesystem-readonly"],
149
+ "grep": ["filesystem-readonly"],
150
+ "find": ["filesystem-readonly"],
151
+ "ls": ["filesystem-readonly"],
152
+ "write": ["filesystem-write"],
153
+ "edit": ["filesystem-write"],
154
+ "browser": ["browser"],
155
+ "github": ["github"]
156
+ }
157
+ },
158
+ "externalActionPolicy": {
159
+ "defaultMode": "enforce",
160
+ "providerKeywords": [
161
+ "github",
162
+ "gitlab",
163
+ "bitbucket",
164
+ "vercel",
165
+ "netlify",
166
+ "cloudflare",
167
+ "aws",
168
+ "gcp",
169
+ "azure",
170
+ "slack",
171
+ "teams",
172
+ "jira",
173
+ "linear",
174
+ "notion",
175
+ "figma",
176
+ "stripe",
177
+ "supabase",
178
+ "firebase"
179
+ ],
180
+ "writeVerbs": [
181
+ "add",
182
+ "approve",
183
+ "archive",
184
+ "assign",
185
+ "close",
186
+ "comment",
187
+ "create",
188
+ "delete",
189
+ "deploy",
190
+ "dispatch",
191
+ "merge",
192
+ "open",
193
+ "post",
194
+ "publish",
195
+ "push",
196
+ "release",
197
+ "remove",
198
+ "reopen",
199
+ "run",
200
+ "send",
201
+ "submit",
202
+ "trigger",
203
+ "update",
204
+ "upload",
205
+ "write"
206
+ ],
207
+ "safeVerbs": [
208
+ "fetch",
209
+ "find",
210
+ "get",
211
+ "inspect",
212
+ "list",
213
+ "read",
214
+ "search",
215
+ "show",
216
+ "view"
217
+ ]
218
+ },
219
+ "finalGate": {
220
+ "defaultMode": "enforce",
221
+ "requireTaskContract": true,
222
+ "requireContextManifest": true,
223
+ "requireVerifyEvidence": true,
224
+ "requireTrace": true,
225
+ "requirePassingVerify": true
226
+ },
227
+ "orchestrationPolicy": {
228
+ "defaultMode": "solo-first",
229
+ "maxConcurrentSubagents": 2,
230
+ "defaultReviewLenses": [
231
+ "correctness",
232
+ "tests",
233
+ "scope"
234
+ ],
235
+ "roleModelGuidance": {
236
+ "planner": "Use the strongest available model for decomposition, architecture, risk, and acceptance criteria.",
237
+ "worker": "Use the fastest reliable model for a bounded, already-planned single write set.",
238
+ "reviewer": "Use a model or thinking setting decorrelated from the worker when review quality matters.",
239
+ "watchdog": "Use a strong model only for final risk review, security, release, or high-impact changes."
240
+ },
241
+ "fieldGuide": {
242
+ "enabled": true,
243
+ "path": ".pi/memory/MEMORY.md",
244
+ "maxLines": 80,
245
+ "writePolicy": "explicit-only",
246
+ "readBeforeTask": true
247
+ }
248
+ }
249
+ }
@@ -0,0 +1,82 @@
1
+ ---
2
+ description: Implement frontend from backend spec/contract with backend read-only
3
+ argument-hint: "<BE spec/change + FE outcome>"
4
+ ---
5
+
6
+ Implement a frontend change from a backend spec, backend diff, or backend source contract without modifying backend source.
7
+
8
+ Request:
9
+
10
+ ```text
11
+ $ARGUMENTS
12
+ ```
13
+
14
+ Use this for tasks like:
15
+
16
+ - BE endpoint/DTO changed and FE must consume it.
17
+ - BE feature spec must be surfaced in FE.
18
+ - FE needs to map validation/errors/state from backend contract.
19
+ - Backend source must be scouted but not edited.
20
+
21
+ Mandatory flow:
22
+
23
+ 0. Call `piagent_context_preflight` with `workflow=be-to-fe`. If it recommends `fresh-session`, stop loading context in this session and tell the user to use `/fresh-be-to-fe <request>` unless this command already runs in a fresh session.
24
+ 1. Call `piagent_context` with `detail=full` and confirm profile/protected backend paths.
25
+ 2. Call `piagent_orchestration_policy`; keep the workflow solo-first unless bounded BE/FE scouting or review is worth the extra token/tool cost.
26
+ 3. Call `piagent_memory_status`; search memory or Field Guide for prior BE/FE mapping decisions if relevant, record citations with `piagent_memory_citation_record`, then verify against current BE/FE files.
27
+ 4. Read `.pi/project-context.md`. If pending, stop and ask for `/onboard-project`.
28
+ 5. Read required context from the active profile and call `piagent_context_budget` for BE/FE files that look large.
29
+ 6. Classify the task:
30
+ - BE scout: read-only.
31
+ - FE implementation: source-write.
32
+ - Auth/data migration/external provider: high-risk, ask before implementation.
33
+ 7. Decide whether bounded subagents are useful. If the bundled `pi-subagents` parent skill is available, use it for delegation patterns and safety boundaries. If `pi-subagents`/`subagent(...)` is available, prefer read-only delegation only when BE/FE mapping has independent lanes:
34
+ - `piagent-scout` maps backend contract read-only;
35
+ - `piagent-scout` maps frontend touchpoints read-only;
36
+ - builtin `context-builder` may create handoff context when the BE→FE mapping touches multiple journeys/forms/contracts;
37
+ - `piagent-planner` produces the FE implementation plan when the contract touches multiple layers;
38
+ - `piagent-reviewer` reviews diff/verification after implementation.
39
+ Continue single-agent if subagents are unavailable, the task is tiny, or requirements are unresolved.
40
+ 8. Scout backend contract read-only:
41
+ - controller/route/handler;
42
+ - request/response DTO/schema;
43
+ - validation/error model;
44
+ - backend tests;
45
+ - OpenAPI/spec/docs if available;
46
+ - migration/schema only when it affects API shape or UI constraints.
47
+ 9. Produce a contract snapshot before FE writes:
48
+
49
+ | Contract area | Backend evidence | FE implication |
50
+ |---|---|---|
51
+
52
+ 10. If backend contract is missing/contradictory, do not guess and do not edit BE. Record the gap in the final response or a project report if requested.
53
+ 11. Map FE touchpoints:
54
+ - API client/query/mutation layer;
55
+ - types/decoders;
56
+ - state/cache invalidation;
57
+ - route/page/component/form;
58
+ - tests/e2e.
59
+ 12. Before source writes, create a Task Implementation Contract with `piagent_task_start`, including review lenses and a compact workPlan.
60
+ 13. Record BE/FE context files with `piagent_context_record`.
61
+ 14. Before shell commands beyond simple read/list/test, call `piagent_exec_policy_check`.
62
+ 15. Implement FE only.
63
+ 16. Run the exact FE verify command from the profile/task through Pi bash and record the observed result with `piagent_verify_record`. Ad-hoc commands are advisory only and will not satisfy the passing gate.
64
+ 17. Record handoff with `piagent_trace_record`.
65
+ 18. Call `piagent_task_gate_check`; if it fails, report blocked/partial instead of done.
66
+
67
+ For generic projects, use profile `be-readonly-fe` when the repo policy is “BE scout only, FE write allowed”.
68
+
69
+ Do not ask the user to paste the mandatory flow. The platform prompt already contains it. If the user asks only for scout/audit, stay read-only and prefer `/scout` or `/fresh-scout`.
70
+
71
+ Final output:
72
+
73
+ - Backend files read and why.
74
+ - Contract snapshot summary.
75
+ - FE files changed.
76
+ - Verify command/result.
77
+ - Subagents used/not used and why.
78
+ - Review lenses applied.
79
+ - Task gate result.
80
+ - Memory cited, if any.
81
+ - Backend gaps, if any.
82
+ - Residual risk.
@@ -0,0 +1,27 @@
1
+ ---
2
+ description: Create a guarded local Git commit for reviewed project changes
3
+ argument-hint: "[commit message or scope]"
4
+ ---
5
+
6
+ Create a local Git commit for the current project changes.
7
+
8
+ Request:
9
+
10
+ ```text
11
+ $ARGUMENTS
12
+ ```
13
+
14
+ Rules:
15
+
16
+ 1. This command creates a local commit only. Do not push, tag, publish, release, merge, or open external provider flows.
17
+ 2. Use normal shell Git commands so the piagent guard, protected paths, redaction, and confirmation gates remain active.
18
+ 3. Start with `git status --short` and `git diff --stat`. If there are no changes, stop with one short line.
19
+ 4. Inspect the relevant diff before staging. Do not stage files that look unrelated to the requested commit.
20
+ 5. Prefer explicit path staging such as `git add README.md packages/piagent-core/prompts/commit.md`.
21
+ 6. Do not use broad staging (`git add .`, `git add -A`, `git add --all`, `git add -- .`, `git add :/`) unless the human operator explicitly confirms that broad staging is intended.
22
+ 7. Refuse to stage protected or local-secret material such as `.env`, `.env.*`, `auth.json`, `.pi/settings.json`, `.pi/piagent-profile.json`, `.pi/piagent-profile.lock.json`, session files, caches, keys, or credentials.
23
+ 8. If `$ARGUMENTS` contains a usable commit message, use it. Otherwise derive a concise Conventional Commit message from the inspected diff.
24
+ 9. Run a lightweight verification before committing. At minimum use `git diff --check`; if source, policy, prompts, or package metadata changed, run the relevant project verification command.
25
+ 10. After committing, report only the commit hash, message, files committed, verification result, and whether anything remains uncommitted.
26
+
27
+ Output at most 8 short lines. Keep it action-first and avoid long explanations.
@@ -0,0 +1,35 @@
1
+ ---
2
+ description: Clarify an unclear task before planning or implementation
3
+ argument-hint: "<rough idea>"
4
+ ---
5
+
6
+ Clarify this request before implementation:
7
+
8
+ ```text
9
+ $ARGUMENTS
10
+ ```
11
+
12
+ Operating rules:
13
+
14
+ 1. Call `piagent_context` first when available.
15
+ 2. Call `piagent_memory_status`; use memory only to avoid repeated context questions, not as authority.
16
+ 3. Read `.pi/project-context.md` if available; if it is still pending, recommend `/onboard-project` before implementation.
17
+ 4. Inspect relevant files/docs before asking; do not ask what can be answered from the project.
18
+ 5. Identify the next unresolved decision, dependency, constraint, or risk.
19
+ 6. Ask at most 3 focused questions per round.
20
+ 7. For each question, include:
21
+ - recommended/default answer
22
+ - short reason
23
+ - impact if the user chooses differently
24
+ 8. Resolve prerequisite decisions before dependent decisions.
25
+ 9. Stop when the task is clear enough to produce a bounded plan.
26
+ 10. Do not edit files and do not implement.
27
+
28
+ Final output when clear:
29
+
30
+ - agreed decisions
31
+ - remaining open questions, if any
32
+ - implementation approach
33
+ - required context
34
+ - verify commands
35
+ - recommended next command: `/plan` or `/task`