@piagent/platform 1.49.1 → 1.51.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 (125) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/catalog/capabilities.json +2 -2
  3. package/docs/command-reference-vietnamese.md +5 -3
  4. package/docs/company-dev-commands.md +1 -1
  5. package/docs/distribution-standard.md +6 -6
  6. package/docs/herdr-workflow.md +30 -0
  7. package/docs/operator-manual-vietnamese.md +7 -7
  8. package/docs/publishing-for-teams.md +2 -0
  9. package/docs/release-install-policy.md +2 -2
  10. package/docs/security-threat-model.md +2 -0
  11. package/docs/team-onboarding.md +2 -2
  12. package/docs-site/architecture.html +1 -1
  13. package/docs-site/assets/search-en.json +1 -1
  14. package/docs-site/assets/search-vi.json +1 -1
  15. package/docs-site/benchmark.html +1 -1
  16. package/docs-site/commands.html +1 -1
  17. package/docs-site/content/en/workflows.html +6 -0
  18. package/docs-site/content/workflows.html +6 -0
  19. package/docs-site/context-engine.html +1 -1
  20. package/docs-site/ecosystem.html +1 -1
  21. package/docs-site/en/architecture.html +1 -1
  22. package/docs-site/en/benchmark.html +1 -1
  23. package/docs-site/en/commands.html +1 -1
  24. package/docs-site/en/context-engine.html +1 -1
  25. package/docs-site/en/ecosystem.html +1 -1
  26. package/docs-site/en/index.html +15 -15
  27. package/docs-site/en/mcp-approval.html +1 -1
  28. package/docs-site/en/mcp-auth.html +1 -1
  29. package/docs-site/en/mcp-servers.html +1 -1
  30. package/docs-site/en/mcp.html +1 -1
  31. package/docs-site/en/permissions.html +1 -1
  32. package/docs-site/en/profiles.html +1 -1
  33. package/docs-site/en/quickstart.html +1 -1
  34. package/docs-site/en/runtime.html +1 -1
  35. package/docs-site/en/scope.html +1 -1
  36. package/docs-site/en/security.html +1 -1
  37. package/docs-site/en/team.html +1 -1
  38. package/docs-site/en/update.html +3 -3
  39. package/docs-site/en/whats-new.html +56 -26
  40. package/docs-site/en/windows.html +1 -1
  41. package/docs-site/en/workflows.html +7 -1
  42. package/docs-site/index.html +15 -15
  43. package/docs-site/mcp-approval.html +1 -1
  44. package/docs-site/mcp-auth.html +1 -1
  45. package/docs-site/mcp-servers.html +1 -1
  46. package/docs-site/mcp.html +1 -1
  47. package/docs-site/permissions.html +1 -1
  48. package/docs-site/profiles.html +1 -1
  49. package/docs-site/quickstart.html +1 -1
  50. package/docs-site/releases.json +102 -0
  51. package/docs-site/runtime.html +1 -1
  52. package/docs-site/scope.html +1 -1
  53. package/docs-site/security.html +1 -1
  54. package/docs-site/team.html +1 -1
  55. package/docs-site/update.html +3 -3
  56. package/docs-site/whats-new.html +56 -26
  57. package/docs-site/windows.html +1 -1
  58. package/docs-site/workflows.html +7 -1
  59. package/evals/private-holdout-v1/public-exposure.v2.json +2 -2
  60. package/package.json +2 -1
  61. package/packages/piagent-core/extensions/fallback-base-policy.ts +1 -1
  62. package/packages/piagent-core/extensions/guard-types.ts +4 -1
  63. package/packages/piagent-core/{managed/herdr-reporter.mjs → extensions/herdr-reporter.js} +29 -13
  64. package/packages/piagent-core/extensions/piagent-guard.ts +20 -9
  65. package/packages/piagent-core/extensions/session-status.d.ts +1 -0
  66. package/packages/piagent-core/extensions/session-status.js +217 -0
  67. package/packages/piagent-core/managed/approval-refusal.mjs +9 -0
  68. package/packages/piagent-core/managed/check-evidence.mjs +134 -0
  69. package/packages/piagent-core/managed/check-questions.mjs +34 -16
  70. package/packages/piagent-core/managed/command-tools.mjs +52 -9
  71. package/packages/piagent-core/managed/dist/workspace/assets/packages/piagent-core/policies/base-policy.json +2 -1
  72. package/packages/piagent-core/managed/dist/workspace/manifest.json +1 -1
  73. package/packages/piagent-core/managed/fetch-guard.mjs +2 -1
  74. package/packages/piagent-core/managed/helper-roles.mjs +1 -1
  75. package/packages/piagent-core/managed/helper-run.mjs +6 -3
  76. package/packages/piagent-core/managed/host-command.mjs +8 -4
  77. package/packages/piagent-core/managed/ledger.mjs +5 -5
  78. package/packages/piagent-core/managed/member-mcp.mjs +2 -0
  79. package/packages/piagent-core/managed/memory-lessons.mjs +2 -2
  80. package/packages/piagent-core/managed/permission.mjs +11 -3
  81. package/packages/piagent-core/managed/repository-operation.mjs +2 -1
  82. package/packages/piagent-core/managed/session.mjs +5 -5
  83. package/packages/piagent-core/managed/tool-boundary.mjs +5 -5
  84. package/packages/piagent-core/managed/tool-failures.mjs +1 -1
  85. package/packages/piagent-core/managed/workflow.mjs +11 -8
  86. package/packages/piagent-core/package.json +1 -1
  87. package/packages/piagent-core/policies/base-policy.json +2 -1
  88. package/packages/piagent-core/runtime/hooks/session-start-hook.ts +3 -0
  89. package/packages/piagent-core/runtime/inspection/approval-broker.ts +2 -2
  90. package/packages/piagent-core/runtime/policy/critical-removal.mjs +122 -0
  91. package/packages/piagent-core/runtime/policy/handoff-policy.mjs +23 -4
  92. package/packages/piagent-core/runtime/registration/permission-commands.ts +14 -6
  93. package/packages/piagent-core/runtime/registration/task-evidence-tools.ts +1 -1
  94. package/packages/piagent-webui/dist/client/assets/{ActivityPanel-CmjxPmNT.js → ActivityPanel-DeeJLOYx.js} +1 -1
  95. package/packages/piagent-webui/dist/client/assets/App-C9tlGPMb.js +5 -0
  96. package/packages/piagent-webui/dist/client/assets/{GatewayApp-BmkqeXih.js → GatewayApp-Dvo96qoX.js} +17 -17
  97. package/packages/piagent-webui/dist/client/assets/{InspectionApp-9jBsgkVJ.js → InspectionApp-CGgHsOyC.js} +1 -1
  98. package/packages/piagent-webui/dist/client/assets/{SessionAgentWorkspace-RQ0N65d9.js → SessionAgentWorkspace-n8UMMcrP.js} +1 -1
  99. package/packages/piagent-webui/dist/client/assets/{SessionInspectorDrawer-BWyEN4bf.js → SessionInspectorDrawer-B62kkr8J.js} +2 -2
  100. package/packages/piagent-webui/dist/client/assets/SettingsNavigation-BZijmuPt.js +3 -0
  101. package/packages/piagent-webui/dist/client/assets/SettingsPage-DKg0SfZQ.js +1 -0
  102. package/packages/piagent-webui/dist/client/assets/{TerminalPanel-DzHdSjpN.js → TerminalPanel-BPTVsNjP.js} +1 -1
  103. package/packages/piagent-webui/dist/client/assets/{WorkspaceCodeEditor-CEuPTTBd.js → WorkspaceCodeEditor-BHGFFBc2.js} +1 -1
  104. package/packages/piagent-webui/dist/client/assets/{WorkspaceExplorer-B_NwYf4S.js → WorkspaceExplorer-nd4kghwK.js} +3 -3
  105. package/packages/piagent-webui/dist/client/assets/{index-fUpioGMZ.js → index-BiLVX8S-.js} +2 -2
  106. package/packages/piagent-webui/dist/client/assets/{transcript-view-model-acWtHGyE.js → transcript-view-model-BB1niiXd.js} +1 -1
  107. package/packages/piagent-webui/dist/client/assets/{view-model-CWNiS4JN.js → view-model-BrdSO09E.js} +1 -1
  108. package/packages/piagent-webui/dist/client/index.html +1 -1
  109. package/packages/piagent-webui/gateway/managed-projection.ts +1 -1
  110. package/packages/piagent-webui/gateway/runtime-session-controls.ts +1 -1
  111. package/packages/piagent-webui/gateway/session-command-controller.ts +4 -4
  112. package/packages/piagent-webui/gateway/session-inspection-registry.ts +1 -1
  113. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +1 -1
  114. package/schemas/piagent-webui/session-catalog-v1.schema.json +1 -1
  115. package/schemas/piagent-webui/session-command-v1.schema.json +1 -1
  116. package/schemas/piagent-webui/snapshot-v1.schema.json +2 -1
  117. package/schemas/project-profile.schema.json +2 -1
  118. package/scripts/company-terminal.mjs +8 -7
  119. package/scripts/pi-auto.sh +5 -1
  120. package/scripts/piagent-cli.mjs +3 -1
  121. package/scripts/piagent-sessions.mjs +97 -0
  122. package/scripts/piagent-studio.mjs +5 -3
  123. package/packages/piagent-webui/dist/client/assets/App-JrRb7jgn.js +0 -5
  124. package/packages/piagent-webui/dist/client/assets/SettingsNavigation-Wx-q5QQk.js +0 -3
  125. package/packages/piagent-webui/dist/client/assets/SettingsPage-xAt6kSyZ.js +0 -1
@@ -1,4 +1,106 @@
1
1
  [
2
+ {
3
+ "version": "1.51.0",
4
+ "date": "2026-11-02",
5
+ "status": "stable",
6
+ "title": {
7
+ "en": "Follow every session from outside it, and a new Always bypass access",
8
+ "vi": "Theo dõi mọi session từ bên ngoài, thêm quyền Always bypass"
9
+ },
10
+ "summary": {
11
+ "en": "With many sessions open, you see which one is processing, paused or failed without opening it, from any terminal and on the Herdr sidebar. Always bypass, a new access you choose yourself, removes the sandbox and asks only about commits, pushes and removing a critical path.",
12
+ "vi": "Khi mở nhiều session, bạn biết session nào đang chạy, tạm dừng hay bị lỗi mà không cần mở từng cái, từ terminal bất kỳ và ngay trên sidebar Herdr. Always bypass, quyền mới do bạn tự chọn, bỏ sandbox và chỉ hỏi khi commit, push và xoá đường dẫn quan trọng."
13
+ },
14
+ "requires": null,
15
+ "items": [
16
+ {
17
+ "kind": "new",
18
+ "en": "Always bypass: no sandbox for the agent and its helpers; network, MCP, files and deploys run unasked. Only commit, push, gh pr merge and rm on a critical path are asked. It warns you once.",
19
+ "vi": "Always bypass: agent và helper không còn sandbox; internet, MCP, file và deploy chạy không hỏi. Chỉ hỏi commit, push, gh pr merge và rm đường dẫn quan trọng. Chỉ cảnh báo một lần."
20
+ },
21
+ {
22
+ "kind": "new",
23
+ "en": "piagent sessions lists every open session as processing, paused, failed, done or idle, company conversations included. Add --watch to keep it refreshed.",
24
+ "vi": "piagent sessions liệt kê mọi session đang mở: processing, paused, failed, done hoặc idle, gồm cả cuộc trò chuyện công ty. Thêm --watch để tự làm mới."
25
+ },
26
+ {
27
+ "kind": "new",
28
+ "en": "piagent sessions --setup-herdr shows the state on each space and agent of the Herdr sidebar.",
29
+ "vi": "piagent sessions --setup-herdr hiện trạng thái ngay trên từng space và agent ở sidebar Herdr."
30
+ },
31
+ {
32
+ "kind": "fixed",
33
+ "en": "Herdr sees piagent again: since Piagent moved to its own home, every pane read as unknown and the agents list stayed empty.",
34
+ "vi": "Herdr lại thấy piagent: từ khi Piagent có home riêng, mọi pane đều là unknown và danh sách agent trống."
35
+ },
36
+ {
37
+ "kind": "fixed",
38
+ "en": "A company Terminal no longer reads idle in Herdr between the rounds of one message, and a question that waits for you reads as blocked.",
39
+ "vi": "Terminal công ty không còn báo idle trên Herdr giữa các vòng của một tin nhắn, và câu hỏi đang chờ bạn được báo là blocked."
40
+ },
41
+ {
42
+ "kind": "security",
43
+ "en": "Always bypass gives no protection against prompt injection: a page or file that misleads the agent can send secrets out unasked. Turn it on only where you accept that.",
44
+ "vi": "Always bypass không chống được prompt injection: trang web hay file lừa được agent thì secret có thể bị gửi ra ngoài mà không hỏi. Chỉ bật khi bạn chấp nhận điều đó."
45
+ },
46
+ {
47
+ "kind": "improved",
48
+ "en": "A removal of a critical path unanswered for two minutes does not run and the agent carries on; after three, they are refused until your next message.",
49
+ "vi": "Lệnh xoá đường dẫn quan trọng không được trả lời trong 2 phút sẽ không chạy và agent làm tiếp; sau 3 lần, các lệnh này bị từ chối đến khi bạn nhắn tiếp."
50
+ }
51
+ ]
52
+ },
53
+ {
54
+ "version": "1.50.0",
55
+ "date": "2026-11-01",
56
+ "status": "stable",
57
+ "title": {
58
+ "en": "A push is judged repository by repository and reviewed first",
59
+ "vi": "Push được xét theo từng repo và review trước"
60
+ },
61
+ "summary": {
62
+ "en": "From feedback on a real three-repository task: the company Harness knows what passed where, says it before a push, and reviews the code before it leaves.",
63
+ "vi": "Từ góp ý trên một task ba repo thật: Harness công ty biết phần nào đã pass ở đâu, ghi rõ trước khi push và review code trước khi code rời máy."
64
+ },
65
+ "requires": null,
66
+ "items": [
67
+ {
68
+ "kind": "improved",
69
+ "en": "A required review now runs before a push. A finding holds that push until it is fixed or rejected, so it no longer costs an extra release.",
70
+ "vi": "Review bắt buộc giờ chạy trước push. Ý kiến review giữ push lại tới khi được sửa hoặc bác bỏ, nên không còn tốn thêm một bản phát hành."
71
+ },
72
+ {
73
+ "kind": "improved",
74
+ "en": "Before a push the question says which repositories passed in full, which only in part, how many files changed and how long the last full run took.",
75
+ "vi": "Câu hỏi trước push ghi rõ repo nào đã pass toàn bộ, repo nào mới pass một phần, đổi bao nhiêu file và lần chạy toàn bộ gần nhất mất bao lâu."
76
+ },
77
+ {
78
+ "kind": "fixed",
79
+ "en": "A whole-suite pass counts per repository: a later small run no longer erases it, and a pass in one repository no longer clears a push of another.",
80
+ "vi": "Kết quả chạy toàn bộ tính theo từng repo: lần chạy nhỏ sau không xóa nó, và pass ở repo này không còn mở khóa push của repo khác."
81
+ },
82
+ {
83
+ "kind": "fixed",
84
+ "en": "An approval card nobody answered now says it expired instead of reading as a refusal. A push card waits up to 30 minutes instead of 5.",
85
+ "vi": "Thẻ duyệt không ai trả lời giờ báo là hết hạn, không còn giống bị từ chối. Thẻ push chờ tối đa 30 phút thay vì 5 phút."
86
+ },
87
+ {
88
+ "kind": "fixed",
89
+ "en": "Findings of a later review in the same turn reach the agent, and the status names any objection left without a decision by its id.",
90
+ "vi": "Ý kiến của lần review sau trong cùng lượt nay đến được agent, và dòng trạng thái ghi mã của ý kiến chưa có quyết định."
91
+ },
92
+ {
93
+ "kind": "fixed",
94
+ "en": "Test scope reads go test -p as parallelism, not a package, and a shell function or loop that picks its files as a part of the suite.",
95
+ "vi": "Phạm vi test hiểu go test -p là số package chạy song song, không phải tên package, và hiểu hàm shell hoặc vòng lặp tự chọn file là chạy một phần."
96
+ },
97
+ {
98
+ "kind": "improved",
99
+ "en": "The checks the Harness names are those of the repositories that changed. Bypass no longer sends a quick suite another way, and tests may write .env files in their own temporary folder.",
100
+ "vi": "Harness chỉ nêu check của repo có thay đổi. Bypass không còn bắt đi đường vòng với bộ test chạy nhanh, và test được ghi file .env trong thư mục tạm của chính nó."
101
+ }
102
+ ]
103
+ },
2
104
  {
3
105
  "version": "1.49.1",
4
106
  "date": "2026-11-01",
@@ -37,7 +37,7 @@
37
37
  <span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
38
38
  <span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
39
39
  </a>
40
- <a class="version-badge" href="/whats-new" data-docs-version="v1.49.1" title="v1.49.1 docs · VI"><span class="dot"></span>v1.49.1</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.0" title="v1.51.0 docs · VI"><span class="dot"></span>v1.51.0</a>
41
41
  <nav class="top-nav" aria-label="Tài liệu">
42
42
  <a href="/quickstart">Tài liệu</a>
43
43
  <a href="/whats-new">Changelog</a>
@@ -37,7 +37,7 @@
37
37
  <span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
38
38
  <span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
39
39
  </a>
40
- <a class="version-badge" href="/whats-new" data-docs-version="v1.49.1" title="v1.49.1 docs · VI"><span class="dot"></span>v1.49.1</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.0" title="v1.51.0 docs · VI"><span class="dot"></span>v1.51.0</a>
41
41
  <nav class="top-nav" aria-label="Tài liệu">
42
42
  <a href="/quickstart">Tài liệu</a>
43
43
  <a href="/whats-new">Changelog</a>
@@ -37,7 +37,7 @@
37
37
  <span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
38
38
  <span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
39
39
  </a>
40
- <a class="version-badge" href="/whats-new" data-docs-version="v1.49.1" title="v1.49.1 docs · VI"><span class="dot"></span>v1.49.1</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.0" title="v1.51.0 docs · VI"><span class="dot"></span>v1.51.0</a>
41
41
  <nav class="top-nav" aria-label="Tài liệu">
42
42
  <a href="/quickstart">Tài liệu</a>
43
43
  <a href="/whats-new">Changelog</a>
@@ -37,7 +37,7 @@
37
37
  <span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
38
38
  <span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
39
39
  </a>
40
- <a class="version-badge" href="/whats-new" data-docs-version="v1.49.1" title="v1.49.1 docs · VI"><span class="dot"></span>v1.49.1</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.0" title="v1.51.0 docs · VI"><span class="dot"></span>v1.51.0</a>
41
41
  <nav class="top-nav" aria-label="Tài liệu">
42
42
  <a href="/quickstart">Tài liệu</a>
43
43
  <a href="/whats-new">Changelog</a>
@@ -37,7 +37,7 @@
37
37
  <span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
38
38
  <span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
39
39
  </a>
40
- <a class="version-badge" href="/whats-new" data-docs-version="v1.49.1" title="v1.49.1 docs · VI"><span class="dot"></span>v1.49.1</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.0" title="v1.51.0 docs · VI"><span class="dot"></span>v1.51.0</a>
41
41
  <nav class="top-nav" aria-label="Tài liệu">
42
42
  <a href="/quickstart">Tài liệu</a>
43
43
  <a href="/whats-new">Changelog</a>
@@ -153,9 +153,9 @@
153
153
  <h2 id="pin-cho-team">Pin một bản cho cả team</h2>
154
154
  <p>Khi rollout cho team, cài đúng bản Pi host và đúng bản platform, rồi chạy installer ở chế độ stable. Bước <code>--dry-run</code> in ra những gì sẽ đổi.</p>
155
155
  <div class="command-card">
156
- <header><span>Cài pin theo bản</span><button class="clip-btn" data-clip="npm install -g --ignore-scripts @earendil-works/pi-coding-agent@1.3.0&#10;npm install -g --ignore-scripts @piagent/platform@1.49.1&#10;piagent-install --stable --dry-run&#10;piagent-install --stable">Lấy lệnh</button></header>
156
+ <header><span>Cài pin theo bản</span><button class="clip-btn" data-clip="npm install -g --ignore-scripts @earendil-works/pi-coding-agent@1.3.0&#10;npm install -g --ignore-scripts @piagent/platform@1.51.0&#10;piagent-install --stable --dry-run&#10;piagent-install --stable">Lấy lệnh</button></header>
157
157
  <pre><code>npm install -g --ignore-scripts @earendil-works/pi-coding-agent@1.3.0
158
- npm install -g --ignore-scripts @piagent/platform@1.49.1
158
+ npm install -g --ignore-scripts @piagent/platform@1.51.0
159
159
  piagent-install --stable --dry-run
160
160
  piagent-install --stable</code></pre>
161
161
  </div>
@@ -37,7 +37,7 @@
37
37
  <span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
38
38
  <span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
39
39
  </a>
40
- <a class="version-badge" href="/whats-new" data-docs-version="v1.49.1" title="v1.49.1 docs · VI"><span class="dot"></span>v1.49.1</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.0" title="v1.51.0 docs · VI"><span class="dot"></span>v1.51.0</a>
41
41
  <nav class="top-nav" aria-label="Tài liệu">
42
42
  <a href="/quickstart">Tài liệu</a>
43
43
  <a href="/whats-new" aria-current="page">Changelog</a>
@@ -108,7 +108,39 @@
108
108
  <div class="release-filter" role="toolbar" aria-label="Lọc theo loại thay đổi"><button type="button" data-filter-kind="all" aria-pressed="true">Tất cả</button><button type="button" data-filter-kind="new" aria-pressed="false">Mới</button><button type="button" data-filter-kind="improved" aria-pressed="false">Cải thiện</button><button type="button" data-filter-kind="fixed" aria-pressed="false">Sửa lỗi</button><button type="button" data-filter-kind="security" aria-pressed="false">Bảo mật</button></div>
109
109
  <section class="section releases" data-releases>
110
110
  <h2 id="latest" class="sr-only">Mới nhất</h2>
111
- <article class="release latest" id="v1-49-1" data-release>
111
+ <article class="release latest" id="v1-51-0" data-release>
112
+ <div class="release-meta"><a class="release-version" href="#v1-51-0">v1.51.0</a><time class="release-date" datetime="2026-11-02">02/11/2026</time></div>
113
+ <div class="release-body">
114
+ <h3 data-toc-skip id="v1-51-0-title">Theo dõi mọi session từ bên ngoài, thêm quyền Always bypass</h3>
115
+ <p>Khi mở nhiều session, bạn biết session nào đang chạy, tạm dừng hay bị lỗi mà không cần mở từng cái, từ terminal bất kỳ và ngay trên sidebar Herdr. Always bypass, quyền mới do bạn tự chọn, bỏ sandbox và chỉ hỏi khi commit, push và xoá đường dẫn quan trọng.</p>
116
+ <ul class="release-items">
117
+ <li data-kind="new"><span class="kind kind-new">Mới</span><span>Always bypass: agent và helper không còn sandbox; internet, MCP, file và deploy chạy không hỏi. Chỉ hỏi commit, push, gh pr merge và rm đường dẫn quan trọng. Chỉ cảnh báo một lần.</span></li>
118
+ <li data-kind="new"><span class="kind kind-new">Mới</span><span>piagent sessions liệt kê mọi session đang mở: processing, paused, failed, done hoặc idle, gồm cả cuộc trò chuyện công ty. Thêm --watch để tự làm mới.</span></li>
119
+ <li data-kind="new"><span class="kind kind-new">Mới</span><span>piagent sessions --setup-herdr hiện trạng thái ngay trên từng space và agent ở sidebar Herdr.</span></li>
120
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Lệnh xoá đường dẫn quan trọng không được trả lời trong 2 phút sẽ không chạy và agent làm tiếp; sau 3 lần, các lệnh này bị từ chối đến khi bạn nhắn tiếp.</span></li>
121
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Herdr lại thấy piagent: từ khi Piagent có home riêng, mọi pane đều là unknown và danh sách agent trống.</span></li>
122
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Terminal công ty không còn báo idle trên Herdr giữa các vòng của một tin nhắn, và câu hỏi đang chờ bạn được báo là blocked.</span></li>
123
+ <li data-kind="security"><span class="kind kind-security">Bảo mật</span><span>Always bypass không chống được prompt injection: trang web hay file lừa được agent thì secret có thể bị gửi ra ngoài mà không hỏi. Chỉ bật khi bạn chấp nhận điều đó.</span></li>
124
+ </ul>
125
+ </div>
126
+ </article>
127
+ <article class="release" id="v1-50-0" data-release>
128
+ <div class="release-meta"><a class="release-version" href="#v1-50-0">v1.50.0</a><time class="release-date" datetime="2026-11-01">01/11/2026</time></div>
129
+ <div class="release-body">
130
+ <h3 data-toc-skip id="v1-50-0-title">Push được xét theo từng repo và review trước</h3>
131
+ <p>Từ góp ý trên một task ba repo thật: Harness công ty biết phần nào đã pass ở đâu, ghi rõ trước khi push và review code trước khi code rời máy.</p>
132
+ <ul class="release-items">
133
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Review bắt buộc giờ chạy trước push. Ý kiến review giữ push lại tới khi được sửa hoặc bác bỏ, nên không còn tốn thêm một bản phát hành.</span></li>
134
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Câu hỏi trước push ghi rõ repo nào đã pass toàn bộ, repo nào mới pass một phần, đổi bao nhiêu file và lần chạy toàn bộ gần nhất mất bao lâu.</span></li>
135
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Harness chỉ nêu check của repo có thay đổi. Bypass không còn bắt đi đường vòng với bộ test chạy nhanh, và test được ghi file .env trong thư mục tạm của chính nó.</span></li>
136
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Kết quả chạy toàn bộ tính theo từng repo: lần chạy nhỏ sau không xóa nó, và pass ở repo này không còn mở khóa push của repo khác.</span></li>
137
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Thẻ duyệt không ai trả lời giờ báo là hết hạn, không còn giống bị từ chối. Thẻ push chờ tối đa 30 phút thay vì 5 phút.</span></li>
138
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Ý kiến của lần review sau trong cùng lượt nay đến được agent, và dòng trạng thái ghi mã của ý kiến chưa có quyết định.</span></li>
139
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Phạm vi test hiểu go test -p là số package chạy song song, không phải tên package, và hiểu hàm shell hoặc vòng lặp tự chọn file là chạy một phần.</span></li>
140
+ </ul>
141
+ </div>
142
+ </article>
143
+ <article class="release" id="v1-49-1" data-release>
112
144
  <div class="release-meta"><a class="release-version" href="#v1-49-1">v1.49.1</a><time class="release-date" datetime="2026-11-01">01/11/2026</time></div>
113
145
  <div class="release-body">
114
146
  <h3 data-toc-skip id="v1-49-1-title">Lượt chạy nói rõ đang chờ gì</h3>
@@ -398,35 +430,33 @@
398
430
  </ul>
399
431
  </div>
400
432
  </article>
401
- <article class="release" id="v1-43-7" data-release>
402
- <div class="release-meta"><a class="release-version" href="#v1-43-7">v1.43.7</a><time class="release-date" datetime="2026-10-27">27/10/2026</time></div>
403
- <div class="release-body">
404
- <h3 data-toc-skip id="v1-43-7-title">Đủ skill đã cài, và mở file agent gửi lại <span class="tag">không phát hành</span></h3>
405
- <p>Đã tag nhưng chưa publish: kiểm tra wording công khai chặn release vì tên sản phẩm trong ghi chú. Thay bằng 1.43.9.</p>
406
- <ul class="release-items">
407
- <li data-kind="new"><span class="kind kind-new">Mới</span><span>File agent gắn link trong câu trả lời mở ngay trong explorer: code đúng dòng, ảnh hiện hình, PDF và file office hiện nội dung chữ.</span></li>
408
- <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Skill và lệnh trong plugin Claude và Codex của dev được liệt kê và đọc được, lấy bản mới nhất; gõ /plugin:skill cũng được.</span></li>
409
- <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Chọn thư mục project mở lại được hộp chọn thư mục của Windows, kể cả khi dashboard chạy nền.</span></li>
410
- </ul>
411
- </div>
412
- </article>
413
- <article class="release" id="v1-43-6" data-release>
414
- <div class="release-meta"><a class="release-version" href="#v1-43-6">v1.43.6</a><time class="release-date" datetime="2026-10-27">27/10/2026</time></div>
415
- <div class="release-body">
416
- <h3 data-toc-skip id="v1-43-6-title">Xem thay đổi của agent ngay khi đang chạy</h3>
417
- <p>Thay đổi và Review cập nhật theo lượt đang chạy, thấy sai thì dừng sớm được, và lượt còn chạy không còn trông như đã xong.</p>
418
- <ul class="release-items">
419
- <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Panel Workspace liệt kê file thay đổi và mở được Review khi agent đang chạy, tự làm mới vài giây một lần; Review cũng cập nhật theo.</span></li>
420
- <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Câu trả lời bị harness trả lại để chạy check được ghi là giữa chừng, và lượt vẫn hiện đang chạy kèm nút Dừng cho tới khi check xong.</span></li>
421
- </ul>
422
- </div>
423
- </article>
424
433
  </section>
425
434
  <section class="section archive">
426
435
  <h2 id="archive">Các bản trước</h2>
427
436
  <p class="section-lead">Bản cũ hơn, gom theo tháng. Mở một tháng để xem từng thay đổi.</p>
428
437
  <details class="release-archive">
429
- <summary><span>Tháng 10/2026</span><span class="archive-count">70</span></summary>
438
+ <summary><span>Tháng 10/2026</span><span class="archive-count">72</span></summary>
439
+ <div class="archive-row" id="v1-43-7">
440
+ <div class="archive-head"><a class="release-version" href="#v1-43-7">v1.43.7</a> <span class="release-date">27/10/2026</span></div>
441
+ <div class="archive-body">
442
+ <p><strong>Đủ skill đã cài, và mở file agent gửi lại</strong> <span class="tag">không phát hành</span> — Đã tag nhưng chưa publish: kiểm tra wording công khai chặn release vì tên sản phẩm trong ghi chú. Thay bằng 1.43.9.</p>
443
+ <ul class="release-items">
444
+ <li data-kind="new"><span class="kind kind-new">Mới</span><span>File agent gắn link trong câu trả lời mở ngay trong explorer: code đúng dòng, ảnh hiện hình, PDF và file office hiện nội dung chữ.</span></li>
445
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Skill và lệnh trong plugin Claude và Codex của dev được liệt kê và đọc được, lấy bản mới nhất; gõ /plugin:skill cũng được.</span></li>
446
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Chọn thư mục project mở lại được hộp chọn thư mục của Windows, kể cả khi dashboard chạy nền.</span></li>
447
+ </ul>
448
+ </div>
449
+ </div>
450
+ <div class="archive-row" id="v1-43-6">
451
+ <div class="archive-head"><a class="release-version" href="#v1-43-6">v1.43.6</a> <span class="release-date">27/10/2026</span></div>
452
+ <div class="archive-body">
453
+ <p><strong>Xem thay đổi của agent ngay khi đang chạy</strong> — Thay đổi và Review cập nhật theo lượt đang chạy, thấy sai thì dừng sớm được, và lượt còn chạy không còn trông như đã xong.</p>
454
+ <ul class="release-items">
455
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Panel Workspace liệt kê file thay đổi và mở được Review khi agent đang chạy, tự làm mới vài giây một lần; Review cũng cập nhật theo.</span></li>
456
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Câu trả lời bị harness trả lại để chạy check được ghi là giữa chừng, và lượt vẫn hiện đang chạy kèm nút Dừng cho tới khi check xong.</span></li>
457
+ </ul>
458
+ </div>
459
+ </div>
430
460
  <div class="archive-row" id="v1-43-5">
431
461
  <div class="archive-head"><a class="release-version" href="#v1-43-5">v1.43.5</a> <span class="release-date">27/10/2026</span></div>
432
462
  <div class="archive-body">
@@ -37,7 +37,7 @@
37
37
  <span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
38
38
  <span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
39
39
  </a>
40
- <a class="version-badge" href="/whats-new" data-docs-version="v1.49.1" title="v1.49.1 docs · VI"><span class="dot"></span>v1.49.1</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.0" title="v1.51.0 docs · VI"><span class="dot"></span>v1.51.0</a>
41
41
  <nav class="top-nav" aria-label="Tài liệu">
42
42
  <a href="/quickstart">Tài liệu</a>
43
43
  <a href="/whats-new">Changelog</a>
@@ -37,7 +37,7 @@
37
37
  <span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
38
38
  <span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
39
39
  </a>
40
- <a class="version-badge" href="/whats-new" data-docs-version="v1.49.1" title="v1.49.1 docs · VI"><span class="dot"></span>v1.49.1</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.0" title="v1.51.0 docs · VI"><span class="dot"></span>v1.51.0</a>
41
41
  <nav class="top-nav" aria-label="Tài liệu">
42
42
  <a href="/quickstart">Tài liệu</a>
43
43
  <a href="/whats-new">Changelog</a>
@@ -210,6 +210,12 @@ Implement frontend support cho endpoint user status mới. Backend chỉ đọc.
210
210
  </article>
211
211
  </div>
212
212
  </section>
213
+
214
+ <section class="section">
215
+ <p class="section-kicker">Nhiều session</p>
216
+ <h2 id="sessions">Xem mọi session mà không cần vào từng space</h2>
217
+ <p class="section-lead"><span class="inline-code">piagent sessions</span> liệt kê mọi session đang mở: <span class="inline-code">processing</span> đang chạy, <span class="inline-code">paused</span> đang chờ bạn, <span class="inline-code">failed</span> bị lỗi, <span class="inline-code">done</span> đã xong. Thêm <span class="inline-code">--watch</span> để tự làm mới. Dùng Herdr thì chạy <span class="inline-code">piagent sessions --setup-herdr</span> một lần để thấy trạng thái ngay trên từng space.</p>
218
+ </section>
213
219
  <nav class="pager" aria-label="Trang kế tiếp">
214
220
  <a class="pager-prev" href="/commands">
215
221
  <span class="pager-label">← Trước</span>
@@ -256,8 +256,8 @@
256
256
  },
257
257
  {
258
258
  "path": "tests",
259
- "fileCount": 648,
260
- "sha256": "c71a827c77f6d8a2557cc956bd7cc4b9d1863c81503b584784f130fe466932e7"
259
+ "fileCount": 651,
260
+ "sha256": "02e75d8917cda9a4abc8833a33058700d7ee0baf9553b2efc54d894ff845023b"
261
261
  }
262
262
  ],
263
263
  "custodianComparisonRules": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piagent/platform",
3
- "version": "1.49.1",
3
+ "version": "1.51.0",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -72,6 +72,7 @@
72
72
  "bin": {
73
73
  "piagent": "scripts/piagent-cli.mjs",
74
74
  "piagent-dashboard": "scripts/piagent-cli.mjs",
75
+ "piagent-sessions": "scripts/piagent-cli.mjs",
75
76
  "piagent-setup": "scripts/piagent-cli.mjs",
76
77
  "piagent-install": "scripts/piagent-cli.mjs",
77
78
  "piagent-update": "scripts/piagent-cli.mjs",
@@ -31,7 +31,7 @@ export function fallbackBasePolicy(
31
31
  defaultRequiredContext: ["AGENTS.md", "README.md"],
32
32
  permissionProfiles: {
33
33
  defaultMode: "workspace-write",
34
- allowedModes: ["read-only", "workspace-write", "trusted-full-access", "bypass"]
34
+ allowedModes: ["read-only", "workspace-write", "trusted-full-access", "bypass", "always-bypass"]
35
35
  },
36
36
  execPolicy: {
37
37
  defaultMode: "enforce",
@@ -326,7 +326,10 @@ export type ResolvedOrchestrationPolicy = {
326
326
  // "bypass": personal sessions only; no Piagent gate asks or blocks the work. The
327
327
  // handoff (runtime/policy/handoff-policy.mjs) is still asked; output redaction
328
328
  // and turn checkpoints still run.
329
- export type PermissionProfileMode = "read-only" | "workspace-write" | "trusted-full-access" | "bypass";
329
+ // "always-bypass": only committing and pushing code and an rm on a critical path
330
+ // are asked (critical-removal.mjs);
331
+ // the project's autoDeny rules, output redaction and turn checkpoints remain.
332
+ export type PermissionProfileMode = "read-only" | "workspace-write" | "trusted-full-access" | "bypass" | "always-bypass";
330
333
 
331
334
  export type PermissionProfilesConfig = {
332
335
  defaultMode?: PermissionProfileMode;
@@ -7,7 +7,7 @@ import net from 'node:net';
7
7
  // the company Terminal's own reporter: the same socket requests (newline JSON,
8
8
  // pane.report_agent), with the command that reopens this conversation in
9
9
  // `piagent studio` instead of personal Pi.
10
- const SOURCE = 'custom:piagent-studio', AGENT = 'piagent';
10
+ const COMPANY_SOURCE = 'custom:piagent-studio', AGENT = 'piagent';
11
11
 
12
12
  // What a Herdr pane gives its processes, read before the environment is
13
13
  // cleared; null outside Herdr. Nothing else of it reaches the conversation.
@@ -21,7 +21,7 @@ export function herdrEnvironment(environment = process.env) {
21
21
  // control characters (its POSIX quoting), so such a path is not offered.
22
22
  export function herdrResumeArgv(cwd, sessionFile) {
23
23
  const argv = ['piagent', 'studio', '--project', cwd, ...(sessionFile ? ['--session', sessionFile] : [])];
24
- return argv.every(part => typeof part === 'string' && part && !part.includes("'") && !/\p{Cc}/u.test(part)) ? argv : null;
24
+ return safeArgv(argv);
25
25
  }
26
26
 
27
27
  // One request, delivered when Herdr answers; a second, longer try when the
@@ -42,12 +42,15 @@ export async function sendHerdrRequest(socketPath, request) {
42
42
  if (!await sendOnce(socketPath, request, 500)) await sendOnce(socketPath, request, 1500);
43
43
  }
44
44
 
45
+ // Herdr refuses a resume command with an apostrophe or control characters.
46
+ const safeArgv = argv => argv && argv.every(part => typeof part === 'string' && part && !part.includes("'") && !/\p{Cc}/u.test(part)) ? argv : null;
47
+
45
48
  // working while a turn runs, blocked while the conversation waits for the
46
- // member (Pi's `herdr:blocked` events), idle otherwise. Reports go out one at a
47
- // time, the newest state winning.
48
- export function companyHerdrExtension(herdr, { send = sendHerdrRequest } = {}) {
49
+ // member (Pi's blocking dialogs, or `herdr:blocked` events), idle otherwise.
50
+ // Reports go out one at a time, the newest state winning.
51
+ export function herdrReporterExtension(herdr, { source, resume, managed = null, send = sendHerdrRequest }) {
49
52
  return (pi) => {
50
- let seq = Date.now() * 1000, active = false, blocked = 0, label, last, resumeArgv, queued, sending = false;
53
+ let unsubscribe, seq = Date.now() * 1000, active = false, blocked = 0, label, last, resumeArgv, queued, sending = false;
51
54
  const desired = () => blocked > 0 ? { state: 'blocked', message: label } : { state: active ? 'working' : 'idle', message: undefined };
52
55
  const drain = async () => {
53
56
  if (sending) return;
@@ -55,8 +58,8 @@ export function companyHerdrExtension(herdr, { send = sendHerdrRequest } = {}) {
55
58
  try {
56
59
  while (queued) {
57
60
  const next = queued; queued = undefined;
58
- await send(herdr.socket, { id: `${SOURCE}:${next.seq}`, method: 'pane.report_agent',
59
- params: { pane_id: herdr.pane, source: SOURCE, agent: AGENT, state: next.state, message: next.message, seq: next.seq, ...(resumeArgv ? { resume_argv: resumeArgv } : {}) } });
61
+ await send(herdr.socket, { id: `${source}:${next.seq}`, method: 'pane.report_agent',
62
+ params: { pane_id: herdr.pane, source, agent: AGENT, state: next.state, message: next.message, seq: next.seq, ...(resumeArgv ? { resume_argv: resumeArgv } : {}) } });
60
63
  }
61
64
  } finally { sending = false; if (queued) void drain(); }
62
65
  };
@@ -68,18 +71,31 @@ export function companyHerdrExtension(herdr, { send = sendHerdrRequest } = {}) {
68
71
  const follow = ctx => {
69
72
  let file;
70
73
  try { file = ctx?.sessionManager?.getSessionFile?.(); } catch { file = undefined; }
71
- const argv = herdrResumeArgv(ctx?.cwd, typeof file === 'string' && file ? file : undefined);
74
+ const argv = safeArgv(resume(ctx?.cwd, typeof file === 'string' && file ? file : undefined));
72
75
  const changed = JSON.stringify(argv) !== JSON.stringify(resumeArgv);
73
76
  resumeArgv = argv ?? undefined;
74
77
  return changed;
75
78
  };
76
- pi.events?.on?.('herdr:blocked', data => {
79
+ const wait = data => {
77
80
  if (data?.active) { blocked += 1; label = data.label; } else { blocked = Math.max(0, blocked - 1); if (!blocked) label = undefined; }
78
81
  publish();
79
- });
82
+ };
83
+ pi.events?.on?.('herdr:blocked', wait);
84
+ // A long list as a title is not a label Herdr can show.
85
+ pi.on('ui_prompt_start', event => wait({ active: true, label: event?.title?.slice(0, 80) }));
86
+ pi.on('ui_prompt_end', () => wait({ active: false }));
80
87
  // /new, /resume and /fork start another session: Herdr follows it.
81
- pi.on('session_start', async (_event, ctx) => { follow(ctx); active = ctx?.isIdle?.() === false; publish(true); });
88
+ pi.on('session_start', async (_event, ctx) => {
89
+ follow(ctx); active = ctx?.isIdle?.() === false || !!managed?.()?.activePrompt; publish(true);
90
+ // One company message is many rounds: it is idle when the turn itself ends.
91
+ unsubscribe?.();
92
+ unsubscribe = managed?.()?.session?.subscribe?.(event => { if (event?.type === 'agent_settled' && !managed()?.activePrompt) { active = false; publish(); } });
93
+ });
82
94
  pi.on('agent_start', (_event, ctx) => { const changed = follow(ctx); active = true; publish(changed); });
83
- pi.on('agent_settled', (_event, ctx) => { if (ctx?.isIdle?.() !== true) return; active = false; publish(); });
95
+ pi.on('agent_settled', (_event, ctx) => { if (ctx?.isIdle?.() !== true || managed?.()?.activePrompt) return; active = false; publish(); });
84
96
  };
85
97
  }
98
+
99
+ export function companyHerdrExtension(herdr, { send, managed } = {}) {
100
+ return herdrReporterExtension(herdr, { source: COMPANY_SOURCE, resume: herdrResumeArgv, managed, ...(send ? { send } : {}) });
101
+ }
@@ -38,6 +38,7 @@ import {
38
38
  import { detectProfileName } from "./project-shape.js";
39
39
  import { evaluateUpdateCheck, isInstalledPlatform, readUpdateCache, startUpdateProbe } from "./update-check.js";
40
40
  import { dormantInPersonalPi, personalPiAgentDir } from "./agent-home.js";
41
+ import { registerTerminalSessionStatus } from "./session-status.js";
41
42
  import { collectServers } from "../mcp/mcp-config-layers.js";
42
43
  import { evaluateMcpApproval, mcpApprovalCache } from "../runtime/mcp-repository-gate.mjs";
43
44
  import { evaluateServerReadiness, readinessNotice } from "../mcp/mcp-auth-readiness.js";
@@ -88,7 +89,8 @@ import { ensurePrivateStateDirectory, resolveLocalStatePath } from "./local-stat
88
89
  import { hasDurableContextEvidence } from "./context-evidence.js";
89
90
  import { piApprovalBroker, type ApprovalActionDraft, type ApprovalChoice, type ApprovalUnavailableFallback } from "../runtime/inspection/approval-broker.ts";
90
91
  import { createSourceMutationGuardBindings } from "../runtime/policy/source-mutation-guard-binding.ts";
91
- import { FULL_ACCESS_RUNS, handoffReason, mcpWriteAction, treeExecFinding } from "../runtime/policy/handoff-policy.mjs";
92
+ import { REMOVAL_EXPIRED, REMOVAL_TTL_MS, criticalRemovalReason, noteRemovalExpired, removalsHeld } from "../runtime/policy/critical-removal.mjs";
93
+ import { FULL_ACCESS_RUNS, codeHandoffReason, handoffReason, mcpWriteAction, treeExecFinding } from "../runtime/policy/handoff-policy.mjs";
92
94
  import { createWorkspaceWriteAuthorityBindings } from "../runtime/policy/workspace-write-authority.ts";
93
95
  import { registerWorkspaceMemberEdits } from "../runtime/session/workspace-member-edits.mjs";
94
96
  import {
@@ -343,6 +345,8 @@ const PERMISSION_PROFILE_ALIASES: Record<string, PermissionProfileMode> = {
343
345
  "trusted_full_access": "trusted-full-access",
344
346
  "danger-full-access": "trusted-full-access",
345
347
  "danger_full_access": "trusted-full-access",
348
+ "always-bypass": "always-bypass",
349
+ "always_bypass": "always-bypass",
346
350
  bypass: "bypass",
347
351
  yolo: "bypass",
348
352
  "dangerously-bypass": "bypass",
@@ -1160,6 +1164,7 @@ function runtimeEquivalentForPermissionProfile(mode: PermissionProfileMode): str
1160
1164
  // checks are the boundary.
1161
1165
  if (mode === "read-only") return "like sandbox_mode=read-only, enforced by Piagent policy (no OS sandbox)";
1162
1166
  if (mode === "trusted-full-access") return "like sandbox_mode=danger-full-access; protected paths, destructive steps and the handoff (push, PR, publish, deploy, remote tools) are still asked";
1167
+ if (mode === "always-bypass") return "like sandbox_mode=danger-full-access + approval_policy=never except committing and pushing code and removing a critical path; the project's autoDeny rules, output redaction and turn checkpoints remain";
1163
1168
  if (mode === "bypass") return "like sandbox_mode=danger-full-access + approval_policy=never for the work; the handoff (push, PR, publish, deploy, remote tools, MCP writes) is still asked, and output redaction and turn checkpoints remain";
1164
1169
  return "like sandbox_mode=workspace-write + approval_policy=on-request, enforced by Piagent policy (no OS sandbox)";
1165
1170
  }
@@ -1239,7 +1244,7 @@ function isPiagentTool(toolName: string): boolean {
1239
1244
  }
1240
1245
 
1241
1246
  // Full access or more: the profile does not narrow reads or the tool registry.
1242
- const broadAccess = (mode: PermissionProfileMode) => mode === "trusted-full-access" || mode === "bypass";
1247
+ const broadAccess = (mode: PermissionProfileMode) => mode === "trusted-full-access" || mode === "bypass" || mode === "always-bypass";
1243
1248
 
1244
1249
  function evaluatePermissionProfileToolAccess(
1245
1250
  toolName: string,
@@ -3346,6 +3351,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
3346
3351
  // The member's own `pi` stays stock even when an older install or a project
3347
3352
  // still registers this package there; Piagent runs through `piagent`.
3348
3353
  if (dormantInPersonalPi()) return;
3354
+ registerTerminalSessionStatus(pi);
3349
3355
  const extensionDir = path.dirname(fileURLToPath(import.meta.url));
3350
3356
  const policy = loadPolicy(extensionDir);
3351
3357
  const bashResults = createBashResultLedger({ maxEntries: 300 });
@@ -3754,8 +3760,9 @@ export default function piagentGuard(pi: ExtensionAPI) {
3754
3760
  });
3755
3761
 
3756
3762
  // Bypass is for personal sessions only: a company session keeps Studio's rules.
3757
- const bypassActive = (ctx: ExtensionContext) => !isCompanySession(ctx) && ctx.model?.provider !== "agent_watch_managed"
3758
- && resolvePermissionProfile(loadProfileFromContext(ctx), policy, permissionOverrideFromContext(ctx)).mode === "bypass";
3763
+ const bypassMode = (ctx: ExtensionContext) => !isCompanySession(ctx) && ctx.model?.provider !== "agent_watch_managed"
3764
+ ? resolvePermissionProfile(loadProfileFromContext(ctx), policy, permissionOverrideFromContext(ctx)).mode : null;
3765
+ const bypassActive = (ctx: ExtensionContext) => ["bypass", "always-bypass"].includes(String(bypassMode(ctx)));
3759
3766
  // Bypass runs the work without asking and stops at the handoff: a push, a
3760
3767
  // PR or merge, a publish or deploy, a remote or cloud tool, an upload or an
3761
3768
  // MCP tool that writes outside is asked about, as in every other mode.
@@ -3770,8 +3777,11 @@ export default function piagentGuard(pi: ExtensionAPI) {
3770
3777
  const refused = evaluateExecPolicyCore(command, { policy: { execPolicy: { defaultMode: "enforce", bannedPrefixSuggestions: [], rules: projectRules } }, mode: "enforce" });
3771
3778
  if (refused.decision === "forbid") return execRefusal(refused);
3772
3779
  }
3773
- let reason = command ? await handoffReason(command) : null;
3774
- if (!reason && !command && prepared && classifyExternalAction(event.toolName, prepared.input, policy).decision === "confirm") {
3780
+ const always = bypassMode(ctx) === "always-bypass", modeName = always ? "Always bypass" : "Bypass";
3781
+ const removal = always && command ? criticalRemovalReason(command, { cwd: ctx.cwd, home: os.homedir() }) : null;
3782
+ let reason = !command ? null : always ? removal ?? codeHandoffReason(command) : await handoffReason(command);
3783
+ if (removal && removalsHeld(ctx.sessionManager.getSessionId(), ctx.sessionManager)) return { block: true, reason: `${removal}. ${REMOVAL_EXPIRED}` };
3784
+ if (!always && !reason && !command && prepared && classifyExternalAction(event.toolName, prepared.input, policy).decision === "confirm") {
3775
3785
  const action = await mcpWriteAction(prepared.proxyTool ?? event.toolName);
3776
3786
  if (action) reason = `${prepared.proxyToolName ?? event.toolName} writes outside this machine (${action})`;
3777
3787
  }
@@ -3780,10 +3790,11 @@ export default function piagentGuard(pi: ExtensionAPI) {
3780
3790
  const approval = await piApprovalBroker.request({ cwd: ctx.cwd, rawSessionId: ctx.sessionManager.getSessionId(), toolCallId: String(event.toolCallId), expectedTask: null,
3781
3791
  action: { kind: "external-provider-action", preconditionClass: "runtime-only", treePrecondition: null, toolName: event.toolName, rawAction: { toolName: event.toolName, command, input },
3782
3792
  commandPreview: command, parameterPreview: preview, targetPaths: [], targetSummaries: [reason], provider: command ? "shell-external" : String(prepared?.proxyToolName ?? event.toolName),
3783
- urlOrigin: null, requestedScope: "one-handoff", reason: `Bypass still asks before a handoff: ${reason}`, riskClass: "high",
3793
+ urlOrigin: null, requestedScope: "one-handoff", reason: `${modeName} still asks before a handoff: ${reason}`, riskClass: "high",
3784
3794
  allowConsequence: "Run this exact step once; the work leaves this machine.", denyConsequence: "The step does not run; the agent is told you declined." },
3785
- terminalConfirm: () => ctx.ui.confirm(`Bypass still asks before a handoff.\n\n${reason}\n\n${preview}\n\nAllow?`, "Piagent handoff confirmation"),
3786
- terminalChoose: terminalChooser(ctx, "Piagent handoff confirmation", `Bypass still asks before a handoff.\n\n${reason}\n\n${preview}`, false), unavailableFallback: approvalUnavailableFallback(ctx) });
3795
+ terminalConfirm: () => ctx.ui.confirm(`${modeName} still asks before a handoff.\n\n${reason}\n\n${preview}\n\nAllow?`, "Piagent handoff confirmation"),
3796
+ terminalChoose: terminalChooser(ctx, "Piagent handoff confirmation", `${modeName} still asks before a handoff.\n\n${reason}\n\n${preview}`, false), unavailableFallback: approvalUnavailableFallback(ctx), ...(removal ? { ttlMs: REMOVAL_TTL_MS } : {}) });
3797
+ if (removal && approval.receipt?.state === "expired") { noteRemovalExpired(ctx.sessionManager.getSessionId(), ctx.sessionManager); return { block: true, reason: `${removal}. ${REMOVAL_EXPIRED}` }; }
3787
3798
  if (!approval.allowed) return approval.choice === "stop" ? { block: true, terminate: true, reason: `User denied the handoff and stopped the turn: ${reason}. Do not retry; wait for the member.` } : { block: true, reason: `User denied the handoff: ${reason}` };
3788
3799
  if (!approval.consume()) return { block: true, reason: "Approval became stale before tool start; the action was blocked." };
3789
3800
  return undefined;
@@ -0,0 +1 @@
1
+ export function registerTerminalSessionStatus(pi: unknown, env?: NodeJS.ProcessEnv): void;