@piagent/platform 1.50.0 → 1.51.1

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 (116) hide show
  1. package/CHANGELOG.md +31 -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 +54 -30
  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 +72 -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 +54 -30
  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/check-questions.mjs +24 -14
  68. package/packages/piagent-core/managed/command-tools.mjs +46 -7
  69. package/packages/piagent-core/managed/dist/workspace/assets/packages/piagent-core/policies/base-policy.json +2 -1
  70. package/packages/piagent-core/managed/dist/workspace/manifest.json +1 -1
  71. package/packages/piagent-core/managed/fetch-guard.mjs +2 -1
  72. package/packages/piagent-core/managed/helper-run.mjs +4 -2
  73. package/packages/piagent-core/managed/host-command.mjs +8 -4
  74. package/packages/piagent-core/managed/member-mcp.mjs +2 -0
  75. package/packages/piagent-core/managed/permission.mjs +11 -3
  76. package/packages/piagent-core/managed/session.mjs +5 -5
  77. package/packages/piagent-core/managed/tool-boundary.mjs +4 -4
  78. package/packages/piagent-core/package.json +1 -1
  79. package/packages/piagent-core/policies/base-policy.json +2 -1
  80. package/packages/piagent-core/runtime/hooks/session-start-hook.ts +3 -0
  81. package/packages/piagent-core/runtime/policy/critical-removal.mjs +122 -0
  82. package/packages/piagent-core/runtime/policy/handoff-policy.mjs +23 -4
  83. package/packages/piagent-core/runtime/registration/permission-commands.ts +14 -6
  84. package/packages/piagent-core/runtime/registration/task-evidence-tools.ts +1 -1
  85. package/packages/piagent-webui/dist/client/assets/{ActivityPanel-CmjxPmNT.js → ActivityPanel-DeeJLOYx.js} +1 -1
  86. package/packages/piagent-webui/dist/client/assets/App-C9tlGPMb.js +5 -0
  87. package/packages/piagent-webui/dist/client/assets/{GatewayApp-BmkqeXih.js → GatewayApp-Dvo96qoX.js} +17 -17
  88. package/packages/piagent-webui/dist/client/assets/{InspectionApp-9jBsgkVJ.js → InspectionApp-CGgHsOyC.js} +1 -1
  89. package/packages/piagent-webui/dist/client/assets/{SessionAgentWorkspace-RQ0N65d9.js → SessionAgentWorkspace-n8UMMcrP.js} +1 -1
  90. package/packages/piagent-webui/dist/client/assets/{SessionInspectorDrawer-BWyEN4bf.js → SessionInspectorDrawer-B62kkr8J.js} +2 -2
  91. package/packages/piagent-webui/dist/client/assets/SettingsNavigation-BZijmuPt.js +3 -0
  92. package/packages/piagent-webui/dist/client/assets/SettingsPage-DKg0SfZQ.js +1 -0
  93. package/packages/piagent-webui/dist/client/assets/{TerminalPanel-DzHdSjpN.js → TerminalPanel-BPTVsNjP.js} +1 -1
  94. package/packages/piagent-webui/dist/client/assets/{WorkspaceCodeEditor-CEuPTTBd.js → WorkspaceCodeEditor-BHGFFBc2.js} +1 -1
  95. package/packages/piagent-webui/dist/client/assets/{WorkspaceExplorer-B_NwYf4S.js → WorkspaceExplorer-nd4kghwK.js} +3 -3
  96. package/packages/piagent-webui/dist/client/assets/{index-fUpioGMZ.js → index-BiLVX8S-.js} +2 -2
  97. package/packages/piagent-webui/dist/client/assets/{transcript-view-model-acWtHGyE.js → transcript-view-model-BB1niiXd.js} +1 -1
  98. package/packages/piagent-webui/dist/client/assets/{view-model-CWNiS4JN.js → view-model-BrdSO09E.js} +1 -1
  99. package/packages/piagent-webui/dist/client/index.html +1 -1
  100. package/packages/piagent-webui/gateway/managed-projection.ts +1 -1
  101. package/packages/piagent-webui/gateway/runtime-session-controls.ts +1 -1
  102. package/packages/piagent-webui/gateway/session-command-controller.ts +4 -4
  103. package/packages/piagent-webui/gateway/session-inspection-registry.ts +1 -1
  104. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +1 -1
  105. package/schemas/piagent-webui/session-catalog-v1.schema.json +1 -1
  106. package/schemas/piagent-webui/session-command-v1.schema.json +1 -1
  107. package/schemas/piagent-webui/snapshot-v1.schema.json +2 -1
  108. package/schemas/project-profile.schema.json +2 -1
  109. package/scripts/company-terminal.mjs +8 -7
  110. package/scripts/pi-auto.sh +5 -1
  111. package/scripts/piagent-cli.mjs +3 -1
  112. package/scripts/piagent-sessions.mjs +97 -0
  113. package/scripts/piagent-studio.mjs +5 -3
  114. package/packages/piagent-webui/dist/client/assets/App-JrRb7jgn.js +0 -5
  115. package/packages/piagent-webui/dist/client/assets/SettingsNavigation-Wx-q5QQk.js +0 -3
  116. package/packages/piagent-webui/dist/client/assets/SettingsPage-xAt6kSyZ.js +0 -1
@@ -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.50.0" title="v1.50.0 docs · VI"><span class="dot"></span>v1.50.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.1" title="v1.51.1 docs · VI"><span class="dot"></span>v1.51.1</a>
41
41
  <nav class="top-nav" aria-label="Tài liệu">
42
42
  <a href="/quickstart" aria-current="page">Tài liệu</a>
43
43
  <a href="/whats-new">Changelog</a>
@@ -1,4 +1,76 @@
1
1
  [
2
+ {
3
+ "version": "1.51.1",
4
+ "date": "2026-11-03",
5
+ "status": "stable",
6
+ "title": {
7
+ "en": "A task left running overnight no longer waits for an answer until morning",
8
+ "vi": "Task để chạy qua đêm không còn đứng chờ câu trả lời tới sáng"
9
+ },
10
+ "summary": {
11
+ "en": "In company mode the harness asked how much to test, or whether to push, and waited for you with no limit. A question nobody answers now goes away after ten minutes and the cheap answer goes on.",
12
+ "vi": "Ở chế độ công ty, harness hỏi chạy test phần nào hay có push không, rồi chờ bạn mãi. Giờ câu hỏi không ai trả lời trong mười phút sẽ tự rút và lựa chọn an toàn được dùng."
13
+ },
14
+ "requires": null,
15
+ "items": [
16
+ {
17
+ "kind": "fixed",
18
+ "en": "A test or push question left unanswered for ten minutes is taken back: only the tests that cover the change run, and nothing is pushed. A task no longer stands still overnight.",
19
+ "vi": "Câu hỏi về test hay push không ai trả lời trong mười phút sẽ tự rút: chỉ chạy test liên quan tới thay đổi, không push gì. Task không còn đứng yên cả đêm."
20
+ }
21
+ ]
22
+ },
23
+ {
24
+ "version": "1.51.0",
25
+ "date": "2026-11-02",
26
+ "status": "stable",
27
+ "title": {
28
+ "en": "Follow every session from outside it, and a new Always bypass access",
29
+ "vi": "Theo dõi mọi session từ bên ngoài, thêm quyền Always bypass"
30
+ },
31
+ "summary": {
32
+ "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.",
33
+ "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."
34
+ },
35
+ "requires": null,
36
+ "items": [
37
+ {
38
+ "kind": "new",
39
+ "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.",
40
+ "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."
41
+ },
42
+ {
43
+ "kind": "new",
44
+ "en": "piagent sessions lists every open session as processing, paused, failed, done or idle, company conversations included. Add --watch to keep it refreshed.",
45
+ "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."
46
+ },
47
+ {
48
+ "kind": "new",
49
+ "en": "piagent sessions --setup-herdr shows the state on each space and agent of the Herdr sidebar.",
50
+ "vi": "piagent sessions --setup-herdr hiện trạng thái ngay trên từng space và agent ở sidebar Herdr."
51
+ },
52
+ {
53
+ "kind": "fixed",
54
+ "en": "Herdr sees piagent again: since Piagent moved to its own home, every pane read as unknown and the agents list stayed empty.",
55
+ "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."
56
+ },
57
+ {
58
+ "kind": "fixed",
59
+ "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.",
60
+ "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."
61
+ },
62
+ {
63
+ "kind": "security",
64
+ "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.",
65
+ "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 đó."
66
+ },
67
+ {
68
+ "kind": "improved",
69
+ "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.",
70
+ "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."
71
+ }
72
+ ]
73
+ },
2
74
  {
3
75
  "version": "1.50.0",
4
76
  "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.50.0" title="v1.50.0 docs · VI"><span class="dot"></span>v1.50.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.1" title="v1.51.1 docs · VI"><span class="dot"></span>v1.51.1</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.50.0" title="v1.50.0 docs · VI"><span class="dot"></span>v1.50.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.1" title="v1.51.1 docs · VI"><span class="dot"></span>v1.51.1</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.50.0" title="v1.50.0 docs · VI"><span class="dot"></span>v1.50.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.1" title="v1.51.1 docs · VI"><span class="dot"></span>v1.51.1</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.50.0" title="v1.50.0 docs · VI"><span class="dot"></span>v1.50.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.1" title="v1.51.1 docs · VI"><span class="dot"></span>v1.51.1</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.50.0" title="v1.50.0 docs · VI"><span class="dot"></span>v1.50.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.1" title="v1.51.1 docs · VI"><span class="dot"></span>v1.51.1</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.50.0&#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.1&#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.50.0
158
+ npm install -g --ignore-scripts @piagent/platform@1.51.1
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.50.0" title="v1.50.0 docs · VI"><span class="dot"></span>v1.50.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.1" title="v1.51.1 docs · VI"><span class="dot"></span>v1.51.1</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,33 @@
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-50-0" data-release>
111
+ <article class="release latest" id="v1-51-1" data-release>
112
+ <div class="release-meta"><a class="release-version" href="#v1-51-1">v1.51.1</a><time class="release-date" datetime="2026-11-03">03/11/2026</time></div>
113
+ <div class="release-body">
114
+ <h3 data-toc-skip id="v1-51-1-title">Task để chạy qua đêm không còn đứng chờ câu trả lời tới sáng</h3>
115
+ <p>Ở chế độ công ty, harness hỏi chạy test phần nào hay có push không, rồi chờ bạn mãi. Giờ câu hỏi không ai trả lời trong mười phút sẽ tự rút và lựa chọn an toàn được dùng.</p>
116
+ <ul class="release-items">
117
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Câu hỏi về test hay push không ai trả lời trong mười phút sẽ tự rút: chỉ chạy test liên quan tới thay đổi, không push gì. Task không còn đứng yên cả đêm.</span></li>
118
+ </ul>
119
+ </div>
120
+ </article>
121
+ <article class="release" id="v1-51-0" data-release>
122
+ <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>
123
+ <div class="release-body">
124
+ <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>
125
+ <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>
126
+ <ul class="release-items">
127
+ <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>
128
+ <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>
129
+ <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>
130
+ <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>
131
+ <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>
132
+ <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>
133
+ <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>
134
+ </ul>
135
+ </div>
136
+ </article>
137
+ <article class="release" id="v1-50-0" data-release>
112
138
  <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>
113
139
  <div class="release-body">
114
140
  <h3 data-toc-skip id="v1-50-0-title">Push được xét theo từng repo và review trước</h3>
@@ -399,39 +425,37 @@
399
425
  </ul>
400
426
  </div>
401
427
  </article>
402
- <article class="release" id="v1-43-8" data-release>
403
- <div class="release-meta"><a class="release-version" href="#v1-43-8">v1.43.8</a><time class="release-date" datetime="2026-10-27">27/10/2026</time></div>
404
- <div class="release-body">
405
- <h3 data-toc-skip id="v1-43-8-title">Đủ skill đã cài, và mở file agent gửi lại <span class="tag">không phát hành</span></h3>
406
- <p>Đã tag nhưng chưa publish: test mới chỉ chạy trên Linux đọc sai trường trên CI. Thay bằng 1.43.9.</p>
407
- <ul class="release-items">
408
- <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>
409
- <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>
410
- <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>
411
- <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Lượt chỉ sửa tài liệu hay file Spec Kit không bị harness bắt chạy check của repo, và approval cho check đã bị từ chối thì không bị hỏi lại.</span></li>
412
- <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Câu trả lời agent lặp lại sau mỗi lần harness trả về chỉ hiện một lần, không lặp theo từng vòng.</span></li>
413
- <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Trên Linux và Windows (WSL2), check tìm được JDK ngoài PATH: SDKMAN, /usr/lib/jvm hoặc ~/.jdks.</span></li>
414
- </ul>
415
- </div>
416
- </article>
417
- <article class="release" id="v1-43-7" data-release>
418
- <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>
419
- <div class="release-body">
420
- <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>
421
- <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>
422
- <ul class="release-items">
423
- <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>
424
- <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>
425
- <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>
426
- </ul>
427
- </div>
428
- </article>
429
428
  </section>
430
429
  <section class="section archive">
431
430
  <h2 id="archive">Các bản trước</h2>
432
431
  <p class="section-lead">Bản cũ hơn, gom theo tháng. Mở một tháng để xem từng thay đổi.</p>
433
432
  <details class="release-archive">
434
- <summary><span>Tháng 10/2026</span><span class="archive-count">71</span></summary>
433
+ <summary><span>Tháng 10/2026</span><span class="archive-count">73</span></summary>
434
+ <div class="archive-row" id="v1-43-8">
435
+ <div class="archive-head"><a class="release-version" href="#v1-43-8">v1.43.8</a> <span class="release-date">27/10/2026</span></div>
436
+ <div class="archive-body">
437
+ <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: test mới chỉ chạy trên Linux đọc sai trường trên CI. Thay bằng 1.43.9.</p>
438
+ <ul class="release-items">
439
+ <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>
440
+ <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>
441
+ <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>
442
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Lượt chỉ sửa tài liệu hay file Spec Kit không bị harness bắt chạy check của repo, và approval cho check đã bị từ chối thì không bị hỏi lại.</span></li>
443
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Câu trả lời agent lặp lại sau mỗi lần harness trả về chỉ hiện một lần, không lặp theo từng vòng.</span></li>
444
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Trên Linux và Windows (WSL2), check tìm được JDK ngoài PATH: SDKMAN, /usr/lib/jvm hoặc ~/.jdks.</span></li>
445
+ </ul>
446
+ </div>
447
+ </div>
448
+ <div class="archive-row" id="v1-43-7">
449
+ <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>
450
+ <div class="archive-body">
451
+ <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>
452
+ <ul class="release-items">
453
+ <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>
454
+ <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>
455
+ <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>
456
+ </ul>
457
+ </div>
458
+ </div>
435
459
  <div class="archive-row" id="v1-43-6">
436
460
  <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>
437
461
  <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.50.0" title="v1.50.0 docs · VI"><span class="dot"></span>v1.50.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.1" title="v1.51.1 docs · VI"><span class="dot"></span>v1.51.1</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.50.0" title="v1.50.0 docs · VI"><span class="dot"></span>v1.50.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.51.1" title="v1.51.1 docs · VI"><span class="dot"></span>v1.51.1</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": "35ef07c0ab53282fccd92472562e92fa1e505305c4a47f7c527391eecf1cafec"
259
+ "fileCount": 651,
260
+ "sha256": "3e29d3643596a6ed8d960833b13df079ee337aaa431e059e81af1b662311bcb8"
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.50.0",
3
+ "version": "1.51.1",
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;