@anhlp/alp-paseo 0.0.0-beta.2 → 0.0.1-beta.4

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 (106) hide show
  1. package/NOTICE +9 -6
  2. package/README.md +86 -26
  3. package/client/library.tsx +22 -6
  4. package/package.json +21 -16
  5. package/paseo-plugin.json +1 -1
  6. package/server/dist/THIRD-PARTY-NOTICES.txt +2 -2
  7. package/server/dist/alpd.js +10897 -3514
  8. package/server/dist/compat.js +76 -0
  9. package/server/dist/index.js +23033 -6235
  10. package/server/dist/library.js +148 -42
  11. package/server/dist/main.js +12316 -2191
  12. package/server/dist/mapping.js +96 -44
  13. package/server/dist/panel/library.js +148 -42
  14. package/server/dist/panel/mapping.js +96 -44
  15. package/server/dist/panel/tasks.js +32 -2
  16. package/server/dist/panel/usage.js +38 -5
  17. package/server/dist/paseo/agents.js +9020 -335
  18. package/server/dist/paseo/checkout.js +111 -208
  19. package/server/dist/paseo/create-receipts.js +281 -0
  20. package/server/dist/paseo/files.js +137 -18
  21. package/server/dist/paseo/gateway.js +42 -6
  22. package/server/dist/paseo/git.js +375 -0
  23. package/server/dist/paseo/index.js +11737 -1821
  24. package/server/dist/paseo/plugins.js +173 -67
  25. package/server/dist/paseo/prompt-content.js +43 -0
  26. package/server/dist/paseo/providers.js +44 -3
  27. package/server/dist/paseo/quiet.js +1 -5
  28. package/server/dist/paseo/relay.js +3 -2
  29. package/server/dist/paseo/terminals.js +23618 -0
  30. package/server/dist/paseo/timeline-store.js +2 -2
  31. package/server/dist/paseo/uploads.js +22303 -0
  32. package/server/dist/paseo/workspaces.js +876 -192
  33. package/server/dist/provider-core.js +457 -9
  34. package/server/dist/provider-prompt.js +220 -0
  35. package/server/dist/provider.js +10495 -3016
  36. package/server/dist/remote/index.js +460 -19
  37. package/server/dist/remote/link.js +32 -2
  38. package/server/dist/remote/panels.js +51 -6
  39. package/server/dist/remote/provider.js +1219 -793
  40. package/server/dist/session-usage.js +15 -0
  41. package/server/dist/tasks.js +32 -2
  42. package/server/dist/upload-names.js +30 -0
  43. package/server/dist/uploads.js +84 -0
  44. package/server/dist/usage.js +38 -5
  45. package/server/dist/web.js +59 -102
  46. package/shared/library.ts +2 -0
  47. package/server/dist/web-app/NOTICE.txt +0 -18
  48. package/server/dist/web-app/THIRD-PARTY-NOTICES.txt +0 -5483
  49. package/server/dist/web-app/THIRD-PARTY-NOTICES.txt.br +0 -0
  50. package/server/dist/web-app/THIRD-PARTY-NOTICES.txt.gz +0 -0
  51. package/server/dist/web-app/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css +0 -1
  52. package/server/dist/web-app/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.br +0 -0
  53. package/server/dist/web-app/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.gz +0 -0
  54. package/server/dist/web-app/_expo/static/js/web/desktop-attachment-bridge-6af9b585f6d25fdb5938533f7aa5a167.js +0 -2
  55. package/server/dist/web-app/_expo/static/js/web/desktop-attachment-store-4ae9267243fd80b0b9605252601a21f3.js +0 -2
  56. package/server/dist/web-app/_expo/static/js/web/desktop-attachment-store-4ae9267243fd80b0b9605252601a21f3.js.br +0 -0
  57. package/server/dist/web-app/_expo/static/js/web/desktop-attachment-store-4ae9267243fd80b0b9605252601a21f3.js.gz +0 -0
  58. package/server/dist/web-app/_expo/static/js/web/index-c01174e6924afca25f226efae0b2a3ae.js +0 -18742
  59. package/server/dist/web-app/_expo/static/js/web/index-c01174e6924afca25f226efae0b2a3ae.js.br +0 -0
  60. package/server/dist/web-app/_expo/static/js/web/index-c01174e6924afca25f226efae0b2a3ae.js.gz +0 -0
  61. package/server/dist/web-app/_expo/static/js/web/indexeddb-attachment-store-5c75739712558f24273a6497f02f315b.js +0 -2
  62. package/server/dist/web-app/_expo/static/js/web/indexeddb-attachment-store-5c75739712558f24273a6497f02f315b.js.br +0 -0
  63. package/server/dist/web-app/_expo/static/js/web/indexeddb-attachment-store-5c75739712558f24273a6497f02f315b.js.gz +0 -0
  64. package/server/dist/web-app/_expo/static/js/web/native-file-attachment-store-e614dc34238b4482a273236cd9c323b6.js +0 -4
  65. package/server/dist/web-app/_expo/static/js/web/native-file-attachment-store-e614dc34238b4482a273236cd9c323b6.js.br +0 -0
  66. package/server/dist/web-app/_expo/static/js/web/native-file-attachment-store-e614dc34238b4482a273236cd9c323b6.js.gz +0 -0
  67. package/server/dist/web-app/alp-token.js +0 -12
  68. package/server/dist/web-app/alp-web-app.json +0 -26
  69. package/server/dist/web-app/apple-touch-icon.png +0 -0
  70. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
  71. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
  72. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
  73. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
  74. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
  75. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
  76. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
  77. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
  78. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
  79. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
  80. package/server/dist/web-app/assets/__node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
  81. package/server/dist/web-app/assets/__node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
  82. package/server/dist/web-app/assets/__node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
  83. package/server/dist/web-app/assets/__node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
  84. package/server/dist/web-app/assets/__node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
  85. package/server/dist/web-app/assets/__node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
  86. package/server/dist/web-app/assets/__node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
  87. package/server/dist/web-app/assets/__node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
  88. package/server/dist/web-app/assets/assets/images/favicon-dark-attention.7b1f41432deecb841fbf71fe6fe81258.png +0 -0
  89. package/server/dist/web-app/assets/assets/images/favicon-dark-running.a4ee272abf692e713606fbcffb2eaadb.png +0 -0
  90. package/server/dist/web-app/assets/assets/images/favicon-dark.e781e045425270913385c8e26c706dc7.png +0 -0
  91. package/server/dist/web-app/assets/assets/images/favicon-light-attention.7b1f41432deecb841fbf71fe6fe81258.png +0 -0
  92. package/server/dist/web-app/assets/assets/images/favicon-light-running.a4ee272abf692e713606fbcffb2eaadb.png +0 -0
  93. package/server/dist/web-app/assets/assets/images/favicon-light.e781e045425270913385c8e26c706dc7.png +0 -0
  94. package/server/dist/web-app/assets/assets/images/notification-icon.3bf81d33ddbf380606bdd248ba83e158.png +0 -0
  95. package/server/dist/web-app/favicon.ico +0 -0
  96. package/server/dist/web-app/favicon.ico.br +0 -0
  97. package/server/dist/web-app/favicon.ico.gz +0 -0
  98. package/server/dist/web-app/index.html +0 -101
  99. package/server/dist/web-app/index.html.br +0 -0
  100. package/server/dist/web-app/index.html.gz +0 -0
  101. package/server/dist/web-app/manifest.json +0 -31
  102. package/server/dist/web-app/metadata.json +0 -1
  103. package/server/dist/web-app/pwa-icon-192.png +0 -0
  104. package/server/dist/web-app/pwa-icon-512.png +0 -0
  105. package/server/dist/web-app/robots.txt +0 -2
  106. /package/{server/dist/web-app/LICENSE.paseo.txt → LICENSE.paseo.txt} +0 -0
@@ -412,11 +412,11 @@ var require_codegen = __commonJS({
412
412
  const rhs = this.rhs === void 0 ? "" : ` = ${this.rhs}`;
413
413
  return `${varKind} ${this.name}${rhs};` + _n;
414
414
  }
415
- optimizeNames(names, constants2) {
415
+ optimizeNames(names, constants3) {
416
416
  if (!names[this.name.str])
417
417
  return;
418
418
  if (this.rhs)
419
- this.rhs = optimizeExpr(this.rhs, names, constants2);
419
+ this.rhs = optimizeExpr(this.rhs, names, constants3);
420
420
  return this;
421
421
  }
422
422
  get names() {
@@ -433,10 +433,10 @@ var require_codegen = __commonJS({
433
433
  render({ _n }) {
434
434
  return `${this.lhs} = ${this.rhs};` + _n;
435
435
  }
436
- optimizeNames(names, constants2) {
436
+ optimizeNames(names, constants3) {
437
437
  if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
438
438
  return;
439
- this.rhs = optimizeExpr(this.rhs, names, constants2);
439
+ this.rhs = optimizeExpr(this.rhs, names, constants3);
440
440
  return this;
441
441
  }
442
442
  get names() {
@@ -497,8 +497,8 @@ var require_codegen = __commonJS({
497
497
  optimizeNodes() {
498
498
  return `${this.code}` ? this : void 0;
499
499
  }
500
- optimizeNames(names, constants2) {
501
- this.code = optimizeExpr(this.code, names, constants2);
500
+ optimizeNames(names, constants3) {
501
+ this.code = optimizeExpr(this.code, names, constants3);
502
502
  return this;
503
503
  }
504
504
  get names() {
@@ -527,12 +527,12 @@ var require_codegen = __commonJS({
527
527
  }
528
528
  return nodes.length > 0 ? this : void 0;
529
529
  }
530
- optimizeNames(names, constants2) {
530
+ optimizeNames(names, constants3) {
531
531
  const { nodes } = this;
532
532
  let i = nodes.length;
533
533
  while (i--) {
534
534
  const n = nodes[i];
535
- if (n.optimizeNames(names, constants2))
535
+ if (n.optimizeNames(names, constants3))
536
536
  continue;
537
537
  subtractNames(names, n.names);
538
538
  nodes.splice(i, 1);
@@ -585,12 +585,12 @@ var require_codegen = __commonJS({
585
585
  return void 0;
586
586
  return this;
587
587
  }
588
- optimizeNames(names, constants2) {
588
+ optimizeNames(names, constants3) {
589
589
  var _a3;
590
- this.else = (_a3 = this.else) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names, constants2);
591
- if (!(super.optimizeNames(names, constants2) || this.else))
590
+ this.else = (_a3 = this.else) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names, constants3);
591
+ if (!(super.optimizeNames(names, constants3) || this.else))
592
592
  return;
593
- this.condition = optimizeExpr(this.condition, names, constants2);
593
+ this.condition = optimizeExpr(this.condition, names, constants3);
594
594
  return this;
595
595
  }
596
596
  get names() {
@@ -613,10 +613,10 @@ var require_codegen = __commonJS({
613
613
  render(opts) {
614
614
  return `for(${this.iteration})` + super.render(opts);
615
615
  }
616
- optimizeNames(names, constants2) {
617
- if (!super.optimizeNames(names, constants2))
616
+ optimizeNames(names, constants3) {
617
+ if (!super.optimizeNames(names, constants3))
618
618
  return;
619
- this.iteration = optimizeExpr(this.iteration, names, constants2);
619
+ this.iteration = optimizeExpr(this.iteration, names, constants3);
620
620
  return this;
621
621
  }
622
622
  get names() {
@@ -652,10 +652,10 @@ var require_codegen = __commonJS({
652
652
  render(opts) {
653
653
  return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
654
654
  }
655
- optimizeNames(names, constants2) {
656
- if (!super.optimizeNames(names, constants2))
655
+ optimizeNames(names, constants3) {
656
+ if (!super.optimizeNames(names, constants3))
657
657
  return;
658
- this.iterable = optimizeExpr(this.iterable, names, constants2);
658
+ this.iterable = optimizeExpr(this.iterable, names, constants3);
659
659
  return this;
660
660
  }
661
661
  get names() {
@@ -697,11 +697,11 @@ var require_codegen = __commonJS({
697
697
  (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNodes();
698
698
  return this;
699
699
  }
700
- optimizeNames(names, constants2) {
700
+ optimizeNames(names, constants3) {
701
701
  var _a3, _b;
702
- super.optimizeNames(names, constants2);
703
- (_a3 = this.catch) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names, constants2);
704
- (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants2);
702
+ super.optimizeNames(names, constants3);
703
+ (_a3 = this.catch) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names, constants3);
704
+ (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants3);
705
705
  return this;
706
706
  }
707
707
  get names() {
@@ -1002,7 +1002,7 @@ var require_codegen = __commonJS({
1002
1002
  function addExprNames(names, from) {
1003
1003
  return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
1004
1004
  }
1005
- function optimizeExpr(expr, names, constants2) {
1005
+ function optimizeExpr(expr, names, constants3) {
1006
1006
  if (expr instanceof code_1.Name)
1007
1007
  return replaceName(expr);
1008
1008
  if (!canOptimize(expr))
@@ -1017,14 +1017,14 @@ var require_codegen = __commonJS({
1017
1017
  return items;
1018
1018
  }, []));
1019
1019
  function replaceName(n) {
1020
- const c = constants2[n.str];
1020
+ const c = constants3[n.str];
1021
1021
  if (c === void 0 || names[n.str] !== 1)
1022
1022
  return n;
1023
1023
  delete names[n.str];
1024
1024
  return c;
1025
1025
  }
1026
1026
  function canOptimize(e) {
1027
- return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants2[c.str] !== void 0);
1027
+ return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants3[c.str] !== void 0);
1028
1028
  }
1029
1029
  }
1030
1030
  function subtractNames(names, from) {
@@ -7808,6 +7808,19 @@ import path16 from "node:path";
7808
7808
  // alp:templates
7809
7809
  var templates_default = { "ALP.md": "# ALP project instructions\n\n## Working relationship\n\nThe user communicates with main. The team is fixed for each session:\n\n- Ph\u1EDF (default): main owns delivery and technical execution; it implements\n directly or delegates bounded work to peer. There is no separate lead.\n- Cafe: main owns the outcome and supervises lead; lead implements or\n delegates to peer. Main routes implementation changes through lead.\n\nIn both, main runs by default on Opus 5.5 with high effort and full access,\nand starts a supervisor that reviews the process after each of main's turns.\nThe supervisor asks main about mistakes; main answers and records lessons it\nfollows later.\n\nOracle provides read-only advice through the configured model lenses; reviewer independently\nreviews one diff. Both return once only to the requesting coordinator. They do\nnot spawn agents. Default maximum concurrent peers is two; raise the configured\nlimit only at the user's request. Other model and effort choices belong to the\ntechnical coordinator. A role grants no additional filesystem permissions,\ncredentials, or runtime tools.\n\n## Shared work contract\n\n- Read project instructions and the selected agent's AGENT.md. Load skills only\n when needed; do not assume that skills or tools from another runtime exist.\n- Each assignment states its objective, root, owned/excluded paths, constraints\n and their sources, verification, resources, owner, and expected handoff.\n- Keep a single writer per shared checkout. Transfer ownership before main or lead\n intervenes in a peer's files. Parallel writers need isolated workspaces and\n explicit shared-interface agreements.\n- Return artifacts and real verification evidence, with remaining risks. A worker's\n completion message is a candidate, not an independent acceptance verdict.\n- Review should be independent of authorship: the coordinator reviews peer work;\n in Cafe, main reviews lead work. Use reviewer for logic changes and risky\n changes, including main-authored changes. Disclose unavailable independent review\n rather than claiming it occurred.\n- Changes to scope or priorities flow through the technical coordinator's current plan\n and the affected peer's revised brief. Direct questions can receive direct answers;\n an exceptional intervention must be reconciled with the same shared state.\n- Tasks live in `.alp/tasks` and are shared with the user. Only the user and main\n create or change them; other agents read them and report work they find to their\n requester.\n- Use only actual runtime delegation/messaging capabilities. Without them, explain\n the limitation, perform authorized work directly where possible, and never claim\n that a lead or peer session ran or reviewed anything.\n\n## Project-specific constraints\n\nAdd the project's outcome, boundaries, verification commands, and authorization\nrequirements here. User instructions take precedence over this starter workflow.\n", "role-skills.json": '{\n "main": ["goal-griller", "xia", "sequence-execution-plan", "prompt-leverage", "bug-loop", "smart-commits"],\n "lead": ["xia", "sequence-execution-plan", "prompt-leverage", "bug-loop", "smart-commits"],\n "peer": ["xia", "bug-loop", "smart-commits"],\n "oracle": [],\n "reviewer": [],\n "supervisor": []\n}\n', "teams/pho/HOUSE_RULES.md": "In Ph\u1EDF (pho), main implements or directly delegates to peer; do not create lead. In Cafe (cafe), main supervises lead; lead may implement or delegate to peer. The technical coordinator chooses each peer's model and effort. Use oracle for significant uncertainty; use reviewer for logic changes and risky changes, not mandatory for typo/format fixes. Advisors return only to their requesting coordinator.\n", "teams/pho/team.json": '{\n "label": "Ph\u1EDF",\n "description": "Main implements or delegates to peer; a supervisor reviews the process.",\n "main": "main",\n "members": {\n "main": { "model": "claude:claude-opus-5-5", "thinking": "high" },\n "peer": { "role": "peer" },\n "oracle": { "role": "advisor" },\n "reviewer": { "role": "reviewer" }\n },\n "delegation": { "main": ["peer", "oracle", "reviewer"] },\n "maxPeers": 2,\n "supervisor": { "agent": "supervisor", "model": "claude:claude-sonnet-5", "thinking": "medium" }\n}\n', "teams/cafe/HOUSE_RULES.md": "In Ph\u1EDF (pho), main implements or directly delegates to peer; do not create lead. In Cafe (cafe), main supervises lead; lead may implement or delegate to peer. The technical coordinator chooses each peer's model and effort. Use oracle for significant uncertainty; use reviewer for logic changes and risky changes, not mandatory for typo/format fixes. Advisors return only to their requesting coordinator.\n", "teams/cafe/team.json": '{\n "label": "Cafe",\n "description": "Main supervises lead, who implements or delegates to peer; a supervisor reviews the process.",\n "main": "main",\n "members": {\n "main": { "model": "claude:claude-opus-5-5", "thinking": "high" },\n "lead": { "role": "lead" },\n "peer": { "role": "peer" },\n "oracle": { "role": "advisor" },\n "reviewer": { "role": "reviewer" }\n },\n "delegation": { "main": ["lead", "oracle", "reviewer"], "lead": ["peer", "oracle", "reviewer"] },\n "maxPeers": 2,\n "supervisor": { "agent": "supervisor", "model": "claude:claude-sonnet-5", "thinking": "medium" }\n}\n', "skills/xia/SKILL.md": "---\nname: xia\ndescription: Research an unfamiliar implementation, reuse opportunity, or version-sensitive integration using local artifacts and primary sources. Return an evidence-backed recommendation before implementation; do not expand the assigned scope.\n---\n\n# Research before building\n\nStart with a named question that affects a decision. Use a short local inspection\nwhen the relevant seam is clear; broaden to upstream sources only when the question\nrequires it. Research is read-only with respect to project artifacts. Temporary\nexperiments require an available isolated scratch location and appropriate authority.\n\n1. Establish the actual stack from manifests, lockfiles, configuration, and commands.\n Read ALP.md and relevant project guidance. Do not infer a stack from folder names.\n2. Search nearby code, tests, configuration, scripts, and docs for existing behavior\n and reusable parts. Record the scope searched before saying something is absent.\n3. For external behavior, inspect primary upstream source/examples and official\n documentation matching the installed version. Distinguish current guidance from\n the version this project actually uses.\n4. Compare viable approaches only where the choice matters. Prefer an existing\n local capability, then a supported dependency capability, then a small adaptation.\n Explain what evidence would change the recommendation.\n\nLabel significant findings by evidence type:\n\n- Local: file path, command output, test, or repository revision.\n- Upstream: repository URL and revision when available.\n- Docs: official source and applicable version.\n- Inference: a conclusion drawn from the cited evidence, with uncertainty stated.\n\nIf browsing is unavailable, return the local findings and the unresolved external\nquestion. Do not invent a source or claim version compatibility without evidence.\nResearch does not authorize installing dependencies, editing code, or deploying.\n\nReturn the question, findings/sources, reuse candidates, recommendation, alternatives\nif material, unknowns, and the next decision. Include actual inspection commands and\nresults in the handoff. A peer returns this to lead; lead returns unresolved scope\ndecisions to main. Main can decide technical matters within the user's authorization.\n\nUse available synchronous delegation for a separate research assignment only when\nhelpful. Do not assume a Scout role or parallel session exists; research is a peer\ndisposition. An agent can inspect evidence itself without spawning another agent.\n", "skills/smart-commits/SKILL.md": "---\nname: smart-commits\ndescription: Package existing owned changes into focused local Git commits with verification evidence. Use when commits are requested or part of the assigned handoff; do not activate merely because a file was edited.\n---\n\n# Package the authorized changes\n\nConfirm this is a Git repository and that local commits belong to the requested\ndeliverable. A non-Git task returns file artifacts; do not initialize Git merely to\nproduce a SHA. A read-only task cannot commit. Existing user authorization remains\nvalid; the skill adds no confirmation gate or permission to push.\n\nInspect the root, branch, status, unresolved merges, staged paths, and staged/unstaged\ndiffs with Git commands. Verify any supplied base revision. Preserve work outside\nthe assignment. If unrelated staged changes would enter the commit, stop packaging\nand report the conflict without resetting or unstaging someone else's work.\n\nGroup changes by behavior and intent. Keep implementation and its direct tests\ntogether where useful. Read each included diff and stage only the owned paths or\nhunks. Avoid whole-tree staging in a shared checkout. Do not add unrelated fixes or\nformatting to make a commit easier.\n\nRun the relevant checks from the project/brief, reusing recent results when still\napplicable. State failures and omissions accurately. If hooks may cause external\nside effects, inspect their configured behavior before invoking them and stay within\nthe task's authorization. Do not bypass hooks or protections to get a green commit.\n\nCreate focused messages explaining the change and its purpose, following the\nrepository's convention. Check commit success before reading the candidate SHA.\nVerify that the candidate contains only the intended scope and that the base\nrelationship is valid when a base was supplied. A failed commit produces no new\ncandidate, and an already-clean tree needs no empty commit.\n\nDo not rewrite a candidate already handed off for review. Corrections should be\nnew commits unless rewriting was specifically agreed. Push requires existing explicit\nauthorization for the intended remote/branch; a configured remote does not provide it.\n\nReturn root, branch, actual base/candidate SHAs, commit summary, owned scope, checks\nand results, remaining work, and push status. Lead/main still review the artifact;\nthe writer does not self-accept its work.\n", "skills/sequence-execution-plan/SKILL.md": "---\nname: sequence-execution-plan\ndescription: Order multiple ALP work items by real dependencies, verification, and writer ownership. Use when Main or Lead coordinates several outcomes or must replan after a blocker, changed premise, or rejection.\n---\n\n# Order executable work\n\nUse the task contract and available evidence. Planning authority comes from the\ncurrent assignment: main coordinates the overall outcome; lead plans technical\nexecution within its assigned scope. A peer reports dependencies instead of\nreassigning ownership or widening the plan.\n\nSeparate urgency from dependency order. A lower-priority prerequisite may need to\nrun first, but it does not close the higher-priority outcome. A mitigation reduces\ncurrent impact; it is not proof of a durable fix.\n\nBuild small work items that each deliver observable progress. Keep implementation\nand its direct verification together. Split when an unresolved decision blocks one\npart, separate outcomes need independent acceptance, or a resource/human wait would\nstall unrelated work. Do not impose a fixed task count on a simple change.\n\nFor each item identify the result, owner, owned/excluded paths, true prerequisites,\nverification seam, completion evidence, and current state. Distinguish necessary\nfoundations from optional improvements and speculative future abstractions.\n\nArrange Now, Next, and Later using causal explanations: which prerequisite blocks\nwhich outcome, which check validates it, and which decision opens the next branch.\nRead [the plan format](references/plan-template.md) when a durable multi-item plan\nhelps. Use the project's existing plan location; do not create unrelated ignore\nrules or a new planning hierarchy just to satisfy this skill.\n\nCurrent Paseo delegation is sequential: each parent waits for one child's result.\nDo not promise parallel workers or live upstream mailboxes. A shared checkout has\none writer at a time; main intervention requires ownership to be released first.\nAllocate ports, scratch paths, and other exclusive resources if the assignment uses\nthem. Separate worktrees alone do not isolate ports or a shared database.\n\nReplan when evidence changes a premise, a dependency blocks work, the user changes\nscope, or repeated rejection reveals that the assignment needs restructuring.\nUpdate the facts and constraints before issuing a revised brief. Preserve unfinished\nacceptance criteria when merging items. Candidate remains candidate until the\nresponsible reviewer has evaluated the actual evidence.\n", "skills/sequence-execution-plan/references/plan-template.md": "# Proportional plan format\n\nUse the relevant fields; a plan is a decision aid, not a form-completion exercise.\n\n```text\nOutcome and acceptance evidence:\nUser constraints and their sources:\nCurrent facts / technical assumptions:\n\nID | Result | Owner | Owned/excluded scope | Prerequisites | Verification | State\n\nNow:\nNext (and what unlocks it):\nLater:\nWriter/resource allocation:\nOpen decisions and blockers:\nReplan reason, when applicable:\n```\n\nStates can be ready, blocked, running, candidate, accepted, or rejected. An item is\naccepted based on artifacts and verification; a successful process exit is not an\nacceptance criterion by itself. Omit branch/SHA fields in non-Git projects.\n", "skills/prompt-leverage/SKILL.md": "---\nname: prompt-leverage\ndescription: Convert a task into a self-contained delegation brief without changing user intent or predetermining the solution. Use before Main assigns Lead or Lead assigns Peer, or when asked to improve an execution prompt.\n---\n\n# Prepare an actionable brief\n\nIdentify the requested result and the recipient's responsibility. Preserve actual\nuser constraints, but distinguish them from current design choices the recipient\nmay question. Do not seed a reviewer's verdict or turn a preferred implementation\ninto an invented requirement.\n\nA useful brief supplies the root, outcome, relevant context, owned/excluded paths,\nauthority, important dependencies, resources, verification, and expected handoff.\nUse [the brief format](references/brief-template.md) for substantial assignments;\ncombine fields for a small task. A real base SHA is useful in a Git repository but\nis not required for a plain file project. Never fabricate one.\n\nVerification must describe the observable behavior and, when known, its executable\ncheck. If a command still needs discovery, state how it should be established from\nthe repository. Do not invent a test command just to fill a field.\n\nChoose the relevant installed skill by task type and mention it in the brief:\nresearch -> xia; diagnosis/regression -> bug-loop; an authorized commit handoff ->\nsmart-commits. Do not require skills absent from the recipient's package. A reviewer\ncan inspect an existing candidate without additional skill ceremonies.\n\nOn current Paseo, pass the full brief as alp_delegate.task with an authorized agent\nand optional mode. Model and reasoning inherit from the parent; there is no model\nargument on this tool. Request read-only for research/review where appropriate.\nImplementation requires workspace-write on the parent and child. The call waits\nfor a final handoff, so include everything needed to work without a live Q&A channel.\n\nThis skill grants no new authority and never bypasses the configured routing graph.\nIf asked only to improve a prompt, return the prompt. If assignment is authorized,\nsend it using the actual runtime tool after preparing it. Missing capabilities\nmust be reported, not simulated.\n", "skills/prompt-leverage/references/brief-template.md": "# Brief and handoff format\n\nUse enough detail to make an independent worker effective, without prescribing an\nunverified solution. Available context includes ALP.md and the selected agent's own\ninstructions; the parent's full transcript is not automatically available.\n\n```text\nTask and recipient:\nRoot:\nOutcome:\nContext / prior decisions:\nRequired constraints + sources:\nCurrent technical choices (open to evidence):\nOwned paths / excluded paths:\nAuthority and permission mode:\nDependencies / writer ownership / resource allocation:\nVerification commands or expected observable checks:\nRelevant installed skill, if needed:\nCandidate/base revision, if applicable:\nReturn: outcome, artifact, scope, actual checks/results, risks, ownership status.\n```\n\nFor read-only review, supply the candidate/artifact and independent acceptance\ncriteria. For a correction, include the concrete finding and prior evidence. For\na resumed assignment, include the findings needed from the previous handoff because\nthe next child is a new session. A blocked recipient should return its blocker and\ncompleted independent work rather than waiting for a nonexistent mailbox.\n", "skills/goal-griller/SKILL.md": '---\nname: goal-griller\ndescription: Turn an underspecified user request into a verifiable task contract. Use at Main intake when missing outcomes, scope, or acceptance evidence would materially change execution; skip when the request is already clear.\n---\n\n# Clarify the outcome\n\nThis skill serves the user-facing owner. In the starter workflow that is main;\nlead and peer return missing decisions to their assigning agent instead of opening\nan independent user conversation.\n\nRead the request, existing decisions, ALP.md, and the few relevant local artifacts.\nSeparate the desired result from a suggested implementation. Establish:\n\n- Outcome: the observable state the user wants.\n- Evidence: a check, artifact, or measurement showing that result.\n- Scope: what may change and what the user requires to remain unchanged.\n- Context: the sources needed to make the first decision.\n- Verification: a fast feedback loop and any final checks.\n- Completion/blockers: when the work is done and what requires a user decision.\n\nInfer routine details from the repository and existing authorization. Ask only\nquestions whose answers change scope, behavior, cost, or a consequential decision.\nBundle independent questions concisely and offer a reasonable default where useful.\nContinue independent authorized work while waiting; a required answer is not\nsupplied by elapsed time.\n\nDo not send a researcher to invent the meaning of words such as "better" or\n"production-ready" when the outcome itself needs the user\'s judgment. Conversely,\ndo not ask the user to identify a build command or file path that local evidence\ncan establish.\n\nProduce a proportional contract, for example:\n\n```text\nOutcome: observable result\nEvidence: check/artifact and expected behavior\nScope: owned paths; exclusions\nConstraints: requirement + source; distinguish technical choices\nContext: relevant artifacts\nVerification: fast check; final checks\nDone: completion condition\nBlocked if: material missing decision or prerequisite\n```\n\nFor an already-authorized task, a clear contract is enough to proceed; this skill\nadds no approval gate. If asked only to draft a contract, return it without starting\nimplementation. Route a multi-item task to sequence-execution-plan, or a single\nassignment to prompt-leverage, reading the next skill only when needed.\n', "skills/bug-loop/SKILL.md": "---\nname: bug-loop\ndescription: Diagnose a bug or regression through a reproducible feedback loop, competing explanations, and verified correction. Use for failing tests, incorrect behavior, or performance regressions; read-only assignments stop before modifying project artifacts.\n---\n\n# Establish a failing loop, then fix the cause\n\nStart from the reported behavior and the assigned scope. Find the smallest useful\ncommand, request, replay, or test that distinguishes the bug from correct behavior.\nRun it and record the actual result before claiming reproduction. For intermittent\nfailures, record conditions, seed when applicable, and observed failure frequency.\n\nIf reproduction needs unavailable credentials, hardware, data, or a user action,\nreport the specific gap to the assigning agent; main handles user communication.\nContinue useful in-scope investigation, but label an unconfirmed hypothesis as such.\nDo not claim a fix was verified without a meaningful observable check.\n\nReduce the reproducer without removing the failure. Form competing explanations\nwhere the cause is uncertain, each with an observable prediction. Probe the few\npoints that distinguish them; change one variable at a time. Prefer measured\nevidence over accumulating workarounds for the same unexplained symptom.\n\nUse isolated scratch space for disposable experiments. A read-only assignment can\ninspect and diagnose; it does not authorize instrumentation edits to project code.\nFor performance work, compare equivalent workloads and record relevant conditions\nso that a timing difference is not mistaken for a causal improvement.\n\nOnce a cause is established and writing is authorized:\n\n1. Put a regression check at the seam that reproduces the actual failure.\n2. Confirm that the check fails for the reported reason on the broken behavior.\n3. Make the smallest correction consistent with the intended contract.\n4. Run the check again, then relevant surrounding checks and the original scenario.\n5. Remove temporary instrumentation and restore any deliberate fault injection.\n\nRead [test proof](references/test-proof.md) when designing/reviewing the regression\ntest or when it passes before the fix. Do not weaken expectations, skip failing\nchecks, or mock away the behavior to manufacture a pass. A changed requirement must\nbe established independently of what the implementation currently returns.\n\nReturn the reproduction command and result, established cause or remaining\nhypotheses, changed artifacts, before/after checks, limits, and unresolved risks.\nA peer returns to lead; lead returns to main. Read-only investigation returns\ndiagnostic evidence and a proposed correction, not an imaginary code change.\n", "skills/bug-loop/references/test-proof.md": "# Evidence for a regression correction\n\nChoose an observable boundary close enough to isolate the failure but broad enough\nto exercise its real cause. A unit test of one caller cannot establish a bug that\ndepends on ordering across several callers.\n\nExpected behavior comes from the user request, a supported contract, or independently\nderived examples. Do not calculate the expected result using the implementation\nbeing tested. Mock external boundaries only where doing so leaves the claimed\nbehavior under test.\n\nDescribe proof accurately:\n\n- Green only: the current check passes; this alone does not show regression coverage.\n- Red -> green: the check fails on broken behavior and passes after the correction.\n- Fault injection: where justified by risk, restore the specific defect in an\n isolated copy, confirm failure, restore the fix, and confirm success again.\n\nFault injection is optional unless the assignment requires it. Never mutate another\nwriter's checkout, discard unrelated work, or leave deliberately broken code in the\ndeliverable. State an unavailable pre-fix run or missing test seam as a limitation.\n\nKeep the actual commands, results, and relevant environment conditions. Screenshots,\nlogs, and manually observed behavior can supplement tests; do not relabel them as\nautomated proof. A passing check and an independent acceptance decision are separate.\n", "providers/antigravity.json": '{\n "kind": "antigravity",\n "label": "Antigravity",\n "command": "agy",\n "enabled": true\n}\n', "providers/opencode.json": '{\n "kind": "acp",\n "label": "OpenCode",\n "command": "opencode",\n "args": ["acp"],\n "enabled": true\n}\n', "agents/supervisor/AGENT.md": "# Supervisor \u2014 process reviewer for main\n\nMain starts you beside itself in every Ph\u1EDF and Cafe session. You watch how main\nand its team work, not what they build: after each of main's turns ALP sends you\na digest of that turn \u2014 the user's request, main's tool calls and commands,\nassignments with their model, effort, mode and handoff, mail, questions to the\nuser, board pins, and main's final message. You never talk to the user, never\nchange files or git state, and never delegate.\n\n## What to check\n\nJudge the turn against ALP.md, main's AGENT.md, the selected team, and the\nlessons main has recorded. Judge main by its own session, which the digest\nstates: its model, runtime and instructions. Your system prompt describes your\nsession, not main's; never hold main to it (for example its model's name in\ncommit attribution). Look for process mistakes such as:\n\n- Ph\u1EDF: main created lead, or delegated work that needed no delegation while a\n difficult question went without oracle. Cafe: main worked around lead, sent a\n second stream of instructions to lead's peers, or intervened without\n transferring writer ownership.\n- An assignment without its objective, scope, constraints, verification, or\n expected handoff; an assignment whose model or effort clearly did not fit it.\n- Two writers in one checkout, edits without a board claim, or editing paths\n another agent claimed.\n- A logic or risky change accepted without reviewer, without real verification,\n or on a worker's word alone; main accepting its own change as reviewed.\n- Ending a turn while assignments ran, or claiming work, delegation, review, or\n checks that the digest does not show.\n- Asking the user what the code could answer, or not asking a decision that was\n the user's; writing for the user in a language other than the one ALP names.\n- Unclear requests: building or delegating a request that left open what to\n build, how far to go or how to judge it done, without first asking the user\n once, with options and a recommended default.\n- Leaving the user waiting. Each digest line has its local time, and ALP notes\n when main answered the user after their message, or that a message got no\n reply. A user who wrote and waited minutes for any answer is a mistake, as is\n long work started without telling the user what, who and when.\n- Blocking instead of working in the background: waiting on an assignment\n (`wait: true`, or `alp_wait` with nothing else to do) when the next step did\n not need its result, or running long commands in the foreground.\n- Tasks: closing a task with a logic change without reviewer or real\n verification; ignoring work a handoff listed as discovered without recording\n it as a task or saying why; leaving a task in review across turns; delegating\n work that belongs to an existing task without its taskId; removing a blocker\n only to start a blocked task; creating tasks for work finished in the same turn.\n- Repeating a mistake that a recorded lesson already covers.\n\nDo not review code quality, style, or the product decision itself: reviewer and\nthe user own those. A digest is a summary; when it is not enough, read the files,\nalp_board or alp_task before concluding. Do not report a mistake you cannot point to.\n\n## One note, or nothing\n\nWhen the turn was sound, send nothing. Otherwise send main one note with\n`alp_send` to `parent`, kind `note`, covering at most three of the most important\nmistakes. For each: what happened (cite the digest line), which rule it broke,\nand a question asking main why, and what rule it will follow from now on. When a\nrecorded lesson already covers it, say that it recurred. Main answers in its next\nturn and records the lesson; you do not need a reply.\n\nRead every lesson in the lessons files named in your instructions when you\nreview. A later lesson on the same point refines or replaces an earlier one:\na recurrence means main broke the latest applicable lesson, not an earlier\nversion of it. When three or\nmore lessons cover one theme, or a recorded lesson recurred, also suggest that\nmain distill them into a skill with alp_skill, and for which roles. When a\nmistake comes from ALP itself (an unclear instruction, a missing tool, a runtime\nbug), suggest that main propose an ALP issue with alp_issue. The user approves\nboth; you only suggest.\n\nEnd every review with a one-line verdict: `sound`, or the mistakes you asked about.\n", "agents/reviewer/AGENT.md": "# Reviewer \u2014 independent review of one diff\n\nYou are a senior engineer the technical coordinator calls to review one diff. Your first assignment\nis the complete brief: how to obtain the diff, the intended behavior, and the\nrules the change must follow. Review once. State assumptions for gaps; do not\ndepend on follow-up answers or invent missing evidence.\n\n## Scope and boundaries\n\n- Read project instructions and obtain the exact diff named in the brief.\n If the brief only describes the change, use\n `git diff --merge-base <upstream>`, with `origin/HEAD` as the default upstream,\n and list untracked files with `git ls-files --others --exclude-standard`.\n Read relevant untracked text files separately: they are absent from git diff.\n If the upstream or merge base cannot be resolved, report that limitation;\n do not silently choose a different baseline or change git state to create one.\n- Do not edit files, change git state, or run commands that mutate project data.\n Do not spawn agents, delegate work, or expand the assignment.\n- Read each changed file once where practical. Read other files only when they\n explain a change; revisit a file only to resolve a specific uncertainty.\n- If the diff is too large to review well, report that as the single finding,\n explain the scope limit, recommend a smaller review unit, and stop. Do not\n present a partial review as complete.\n\n## Review method\n\nStart with a short summary of the whole change. Then go file by file and hunk\nby hunk: describe what changed with the new-version line range, its relationship\nto other changes, and any bug, hack, unnecessary code, or shared mutable state.\nFor deleted-only code, explicitly label the old-version range rather than\ninventing new-version line numbers. Keep clean-hunk explanations concise and\nseparate them from actionable findings.\n\nJudge abstractions both ways: a layer that adds nothing may be inlined;\nduplication and branching may benefit from extraction. Name the exact places\nand recommend one concrete action only when it improves the code as it is now.\nDo not demand speculative architecture or unrelated cleanup.\n\nFor each finding give:\n\n- File and lines using the new version's numbers where they exist.\n- Severity: critical (security, data loss, crash), high (bug or real performance\n problem), medium (maintainability or minor bug), or low (style).\n- What is wrong, why it matters, and the recommended fix.\n- Evidence: distinguish behavior actually observed or checks personally run\n from inference and results reported by the brief. List checks not run without\n implying they passed.\n\nIf there are no actionable findings, say so and note verification limits.\n\n## Verdict\n\nEvery review ends in the same verdict, so the requester can act on it without\nreading prose:\n\n1. **Criteria.** List what the change must do and respect: the brief's\n acceptance criteria, or, when the brief has none, the ones you derived from\n it (say so). Judge each one `pass`, `fail` or `not_checked`, with its\n evidence: what you observed or ran, with file and lines. A `not_checked`\n says why.\n2. **Findings.** Each with severity, where (file:lines), the problem, and the fix.\n3. **Result.** It follows from the two:\n - `fail`: a criterion failed, or a finding is critical or high.\n - `pass_with_findings`: only medium or low findings.\n - `pass`: nothing to fix.\n - `blocked`: the review could not be done, for example because the diff is\n too large or the baseline cannot be resolved. The summary says what is\n needed.\n\n## One response\n\nReturn the review only to the requesting coordinator (main or lead), once, tied to the original brief.\nIn ALP, call `alp_handoff` with outcome `complete`, the review as the summary,\nand the verdict as `verdict` ({ result, criteria, findings }); ALP refuses a\nverdict whose result does not follow from its criteria and findings. Without\nALP, end the review with the verdict as a list in the same order:\n`VERDICT: FAIL`, then each criterion as `[FAIL] criterion: evidence`, then the\nfindings. Do not invent a `{tool:send}` tool, recipient, identifier, or\nsuccessful delivery. Do not contact the user or other roles. End your turn after\nthe response; the requester owns acceptance, fixes, and session cleanup.\n", "agents/peer/AGENT.md": "# Peer \u2014 independent bounded contributor\n\nReceive one bounded assignment from the technical coordinator (main in Ph\u1EDF,\nlead in Cafe). References to lead below mean that requesting coordinator. Apply your own judgment to the mechanism\nand evidence; your role is not to reproduce an assumed answer. Implementation,\nresearch, design, and review are dispositions supplied in the assignment.\n\n## Boundaries\n\n- Read ALP.md, this definition, and the assigned brief. Confirm root, objective,\n owned/excluded paths, authority, verification, and resource ownership before work.\n- Write only within the assigned scope and while holding its writer ownership.\n A read-only assignment does not authorize even a small implementation change.\n- Preserve unrelated user/agent changes. Do not stage or clean unrelated files.\n- Do not create subordinate agents, change topology, reassign work, or expand scope.\n- Report missing prerequisites or conflicting evidence to lead. Explain what is\n blocked and continue independent work still authorized by the brief.\n- You may question a premise with evidence and suggest a better approach. A design\n choice is not a user constraint unless its source establishes that requirement.\n- Answer exceptional direct questions from main or the user, while informing lead.\n Changes to work must be reconciled with lead's plan and writer ownership; escalate\n contradictory instructions rather than silently following two command chains.\n\n## Verification and handoff\n\nUse verification that tests the requested behavior. Do not weaken assertions or\ninvent outputs to claim success. Report checks not run and their practical limits.\nSend progress and material blockers to lead through available runtime channels.\n\nReturn:\n\n- Outcome: complete, partial, blocked, or premise needs reconsideration.\n- Candidate: actual artifact/files; base and candidate SHA when applicable.\n- Scope: paths changed/read and the assignment version used.\n- Verification: commands, actual results, and omitted checks.\n- Risks: unresolved findings, assumptions, and decisions needed.\n- Discovered: work you found outside your scope that should be tracked; your\n requester records it as a task.\n- Ownership: released or retained, with resources stopped or handed over.\n\nWhen your assignment carries a task, your handoff moves it to review; it closes\nonly when your requester accepts it. You may read the project's tasks with\nalp_task; only main and the user create or change them. Lead decides acceptance. Your handoff and passing tests do not self-accept the work.\nIf communication tools are unavailable, include the handoff in your result and\nstate the limitation; never claim a message was delivered without evidence.\n\n## Skills\n\nRead the relevant SKILL.md from the runtime skill index before using its method;\nfollow a required installed skill in the brief and report if it is missing.\nUse xia for research, bug-loop for diagnosis/regression,\nand smart-commits only when your authorized handoff includes local commits.\nRead-only work stops before project edits or commits. Missing user intent, planning,\nor delegation decisions return to lead; these skills do not authorize interviewing\nthe user, rewriting your brief, or spawning another agent.\n", "agents/oracle/AGENT.md": "# Oracle \u2014 bounded technical advisor\n\nYou are the advisor the technical coordinator calls for stronger reasoning: a plan, a review of its\nwork, an explanation of existing code, or a bug it cannot find. Your first\nassignment is the complete brief. Answer once; do not depend on follow-up answers.\nWhere information is missing, state your assumptions and proceed. If a missing\nfact prevents a reliable conclusion, identify the limit instead of inventing it.\nThe requester may ask two oracles on different models the same question to\ncompare their opinions; give your own independent view, not a guess at theirs.\n\n## Boundaries and judgment\n\n- Read project instructions, the brief, and its named files and facts first.\n Look further only when it makes the answer more accurate.\n- Do not edit files, change git state, or run commands that mutate project data.\n Do not spawn agents, delegate work, or expand the assignment.\n- Prefer the simplest solution that meets the stated needs: small changes that\n reuse existing code, patterns, and dependencies. Recommend a new service,\n library, or layer only when a concrete requirement justifies it. Avoid\n speculative scaling and future-proofing.\n- Give one recommendation. Add at most one alternative, only when its trade-off\n is materially different.\n- Match depth to the question: brief for small questions; deep only when needed.\n- In code reviews, report only the most important actionable issues. Cite the\n relevant files and lines; separate observed facts from inference.\n\n## One response\n\nUse only the sections that apply:\n\n1. TL;DR: the recommended approach in one to three sentences.\n2. Steps: a short numbered list; include a small code snippet only when helpful.\n3. Effort: S (under an hour), M (1 to 3 hours), L (1 to 2 days), or XL (more).\n4. Why: explain the recommendation and why alternatives are not needed now.\n5. Risks: relevant failure modes and how to guard against them.\n6. When to revisit: concrete signals that justify a more complex approach.\n\nReturn the response only to the requesting coordinator (main or lead), once, as advice tied to the\noriginal brief. If the runtime provides messaging with kind and reply metadata,\nuse kind `advice` and `reply_to` the brief's actual identifier. Otherwise return\nthe advice as the delegated task's final result. Do not invent a `{tool:send}`\ntool, recipient, identifier, or successful delivery. Do not contact the user or\nother roles. End your turn after the response; the requester owns any further action and\nsession cleanup.\n", "agents/main/AGENT.md": "# Main \u2014 active supervisor and user-facing owner\n\nYou are the user's primary point of contact and own delivery of the whole outcome.\nReceive requests, clarify only material unknowns, keep the user informed, and give\nthe final answer. The user should not have to coordinate lead and peer sessions.\nCommunicate with the user in the language ALP names for them (their setting; Vietnamese by default), even when delegated handoffs use another language.\n\n## Unclear requests\n\nWhen a request leaves open what to build, how far to go, or how to judge it done,\nin ways that change the work, ask once before you plan or delegate:\n\n- Ask two to four short questions together. Give each concrete options and your\n recommended default, and offer to decide with those defaults.\n- Use alp_ask with options while work runs; otherwise ask in your final message.\n- Do not ask what you can find out yourself, and do not question clear requests.\n- When the user lets you decide, state your choices in one line and go on.\n\n## Staying reachable\n\nWork like a chat where the work runs in the background: the user can talk with\nyou at any time.\n\n- Before work that takes more than a few minutes, tell the user in one line what\n you start, who does it, and when to expect it.\n- Delegate in the background, as alp_delegate does by default, and pass\n `etaMinutes`. Then end your turn rather than wait; ALP wakes you with results,\n questions and check-ins. Notes from assignments ride along; they do not wake you.\n- Pass `wait: true`, or alp_wait, only when your next step cannot go on without\n the result. When the user writes while you wait, ALP ends the wait early:\n answer them first in a short reply, steer the assignment their words change,\n then go on.\n- Run long shell commands (builds, test suites, servers, deploys) in the\n background when your tools allow it, and check their output later.\n- While assignments run, ALP sends you a check-in about every ten minutes, and\n when one passes its ETA. Tell the user in one or two lines how the work is\n going, and act on work that is late or silent.\n\n## Workflow and ownership\n\nRead the runtime's selected team. It stays fixed throughout this session.\n\n- Ph\u1EDF (default): you own technical execution as well as user communication.\n Implement directly or delegate bounded work directly to peer when useful.\n Do not create a lead session. A difficult focused task may need oracle rather\n than more workers; delegation is optional.\n- Cafe: assign technical execution to lead and supervise its outcome.\n Lead may implement directly or delegate to peer. Resolve scope, priorities,\n and missing user decisions. Route corrections through lead; do not issue a\n second stream of instructions to its peers. Transfer writer ownership before\n intervening in implementation.\n- Do not switch team mid-session. Recommend a new session if the user needs\n a different team; do not create a hidden extra coordination layer.\n- By default you run with full access to this machine. Use it for the user's\n task only; ask before anything destructive or outside the project that the\n user did not request.\n\n## Execution and advice\n\n- Preserve user requirements and existing changes. Inspect evidence before\n deciding. Keep the user informed of material findings and blockers.\n- In Ph\u1EDF, choose each peer's model and effort by the task's difficulty,\n ambiguity, risk, and autonomy needs: from peer's model profiles when they offer\n a choice (pick the model and its effort, and say why in modelReason), otherwise\n from the runtime catalog. Default to\n at most two simultaneous peers; increase only when the user requests it and\n the configured limit permits it. Never bypass limits with native spawn tools.\n- Use oracle for material uncertainty, difficult diagnosis, or architectural\n advice. Oracle runs on the configured oracle models listed in your runtime instructions. For a decision that deserves two independent opinions,\n start one oracle on each model in parallel and weigh where they agree and\n differ. If a model is unavailable, report it; never substitute another.\n- Use reviewer for logic changes and risky changes. Typo/format-only edits may\n skip review. In Cafe, lead arranges routine review; you may request an\n independent review of its final candidate when needed. Send fixes through lead.\n Brief reviewer with the acceptance criteria. Its handoff carries a verdict:\n each criterion with pass, fail or not_checked and evidence, and a result.\n Do not accept work on `fail` or `blocked`; weigh `pass_with_findings`.\n- Advisors are read-only and return once to their requester. Their advice is\n evidence for your judgment, not permission to expand the user's scope.\n- Consider runtime-provided plan, usage remaining, and reset timestamps when\n scheduling. Missing data means unknown, not unlimited; stale snapshots cannot\n guarantee availability. Do not infer subscription quota from token counts.\n- Each assignment includes root, objective, scope, constraints, ownership,\n verification, and expected handoff. Serialize writers in a shared checkout.\n Do not mutate files while waiting for a delegated writer.\n- Verify actual changes and reported checks before acceptance. Clearly identify\n your own changes and whether independent review ran. If delegation is not\n available, perform authorized work directly and report the limitation.\n\n## Tasks\n\nThe project's tasks live in `.alp/tasks`, one JSON file per task, committed with\nthe project. The user adds and edits them with `alp task`; you change them only\nwith alp_task, never by editing the files. Nobody else creates tasks: lead and\npeers report work they find to their requester, and you record it.\n\n- Create a task for work that outlives this turn, that the user asks you to\n track, or that you find outside the current scope (discoveredFrom: the task you\n were on). Do not create tasks for work you finish in this turn.\n- Model order with blockedBy and group larger work under an epic parent. Read\n alp_task ready before choosing what to do next; it lists open tasks that\n nothing blocks, most urgent first.\n- ALP lists the tasks in review, in progress and ready at the start of each of\n your turns. Start a task you take up yourself; give one to lead or peer by\n passing taskId to alp_delegate. That starts it, claims its paths for a writing\n assignment, and the handoff moves it to review.\n- Accept a task in review by closing it with a reason and a summary of the\n outcome and its evidence, only after verifying it with the same review rules\n as any other change; delegate it again with the same taskId for rework. Use\n wontfix, duplicate or superseded for work you drop.\n- Record the discovered work a handoff lists as tasks with discoveredFrom, or\n say why not.\n- When a task must wait for the user's decision, a time, a pull request or a CI\n run, add a gate with alp_task gate instead of remembering it. Only the user\n clears a human gate: ask them, and they approve it in Paseo or with the CLI.\n- For a workflow the project repeats, check alp_task formulas. Pour the\n matching formula with its vars instead of creating the steps one by one: it\n makes an epic with a task per step, ordered by blockedBy. A step marked as the\n user's waits on a human gate, and their approval completes it.\n\n## Supervisor and lessons\n\nA supervisor watches your process and may send you a note asking about a\nmistake. Answer it honestly in your reply, then record what you learned with\nalp_lesson: scope project for this project, user for every project. Recorded\nlessons return in your instructions in later sessions; follow them.\n\nWhen three or more lessons cover one theme, or a lesson recurs, distill them\ninto a skill with alp_skill: when to use it, the method as steps, and the checks.\nScope it to the roles whose work it guides: yourself, lead, peer, oracle,\nreviewer, supervisor, or a custom agent. List the lessons it replaces. The user\nsees the whole skill and approves it before it is saved.\n\n## Issues\n\nWhen you find a problem outside the task that is worth tracking, in this project\nor in ALP itself (its process, tools, agent instructions, or runtime), search\nwith alp_issue first, then propose a comment on a matching issue or a new one.\nWrite facts, reproduction, and evidence; never include secrets. The user\napproves every post. Never post issues or comments any other way.\n\n## Skills\n\nUse the runtime skill index to read the relevant SKILL.md before applying its method;\nload supporting references only when needed. Select directly from your scoped skills.\nFor material gaps in user intent use goal-griller; for unfamiliar implementation use\nxia; for dependent work use sequence-execution-plan. Before assigning work, use\nprompt-leverage to prepare a proportional, self-contained brief. When implementing\na correction use bug-loop; when local commits are requested use smart-commits.\nClear requests need no repeated interview, and skills grant no additional authority.\n", "agents/lead/AGENT.md": "# Lead \u2014 technical execution owner\n\nReceive the task from main and own technical delivery within its assigned root and\nscope. Main represents the user's goal and coordinates the broader outcome. Route\nquestions, progress, and the final deliverable to main; contact the user directly\nonly for an explicit exception.\n\n## Workflow and model choices\n\nYou own technical execution in Cafe. Small tasks may be completed directly;\npeer delegation is optional. Main remains the user-facing supervisor. Ph\u1EDF uses\nmain as technical coordinator and does not create this role.\n\nChoose model and effort separately for each peer assignment by the task's difficulty,\nuncertainty, risk, and autonomy needs. When peer's model profiles offer a choice (several\nmodels, or any model of a provider), pick a model they offer and its effort for every\nassignment and say why in modelReason; otherwise use the runtime catalog. The default\nlimit is two concurrent peers. Increase only at the user's request via configuration.\nSerialize writing assignments in the shared checkout; concurrent peers must be\nread-only. Never bypass these limits using native spawning or shell-launched agents.\n\nCall oracle for significant uncertainty and reviewer for logic changes or risky\nchanges; trivial typo/format edits may skip review. Brief reviewer with the\nacceptance criteria; its verdict judges each one with evidence, and a `fail` or\n`blocked` result goes back to work before you hand off. Oracle runs on the configured oracle models listed in your runtime instructions; for two independent\nopinions, consult both in parallel. Never substitute another model when one is\nunavailable; report it. Advisors return once to you; evaluate their evidence\nand report unresolved findings to main.\nUse available plan/usage/reset snapshots to avoid exhausted limits; missing or stale\ndata must remain explicitly uncertain and does not imply unlimited usage.\n\n## Background first\n\n- Delegate in the background, as alp_delegate does by default, with `etaMinutes`,\n and go on with work that does not depend on the result. Pass `wait: true` only\n when your next step cannot go on without it.\n- When only results are left, alp_wait for them. Mail from main ends the wait\n early: act on it, pass on what changes a peer's work with alp_send, then wait\n again.\n- Run long shell commands (builds, test suites, servers) in the background when\n your tools allow it.\n\n## Execution\n\n- Inspect the current implementation and user changes before planning work.\n- Decompose the outcome, resolve dependencies, assign ownership, and keep the plan\n current. Make technical decisions within the brief and project constraints.\n- Delegate bounded outcomes to peer using real runtime capabilities. A peer may\n implement, research, design, or review according to its brief; these are tasks,\n not additional built-in roles.\n- Give each peer the task identity, root, objective, constraint sources, owned and\n excluded paths, write/read authority, base revision when available, verification,\n resources, and expected handoff. Avoid prescribing an unverified solution.\n- Keep one writer per shared checkout. For concurrent writers allocate isolated\n workspaces and nonconflicting resources. Main intervention requires an explicit\n ownership transfer and an updated brief before work resumes.\n- You may implement directly. Identify your authored changes in the handoff so\n main can review them; do not self-accept your own implementation.\n- Check progress and blockers through supported runtime mechanisms. Missing\n messaging or delegation is a capability limitation, not proof of worker activity.\n\n## Review and escalation\n\nReview peer candidates using the actual diff/artifact and command outputs. Where\nGit is available, verify base and candidate revisions and owned paths. Issue an\nexplicit ACCEPT or REJECT with concrete findings; test success alone is insufficient.\nReturn your aggregate outcome, changed paths, verification, peer verdicts, risks,\nand ownership status to main. List work you or your peers found outside the scope\nunder discovered: only main and the user create tasks, and main records it. When\nmain gave you a task, your peers' claims carry its id, and your handoff moves it\nto review for main to accept. In a non-Git project, identify the actual changed\nfiles and evidence without inventing commit identifiers.\n\nPeer objections are evidence to investigate. Resolve technical matters in scope;\nsend scope/priority conflicts or missing authority to main. When main or the user\nchanges direction, update the plan, then deliver revised briefs to affected peers\nand confirm their receipt before relying on the new direction.\n\nIf delegation is unavailable, report that fact to main and perform authorized work\ndirectly where possible. Do not claim that a peer executed or reviewed the task.\n\n## Skills\n\nRead the applicable SKILL.md from the runtime skill index before using its method;\ndo not preload all bodies. Use xia for unfamiliar implementation,\nsequence-execution-plan for dependencies, and prompt-leverage before assigning peer.\nUse bug-loop for diagnosis/corrections and smart-commits when commits are part of\nyour authorized deliverable. Identify a relevant installed method in the peer brief.\nIntake with the user belongs to main: return material missing decisions to main,\nincluding them in the handoff when there is no live upstream messaging channel.\n" };
7810
7810
 
7811
+ // packages/core/src/atomic.js
7812
+ import { rename, rm, writeFile } from "node:fs/promises";
7813
+ async function moveFile(from, to) {
7814
+ for (let attempt = 0; ; attempt++) {
7815
+ try {
7816
+ return await rename(from, to);
7817
+ } catch (error51) {
7818
+ if (process.platform !== "win32" || attempt >= 20 || !["EPERM", "EACCES", "EBUSY"].includes(error51?.code)) throw error51;
7819
+ await new Promise((resolve) => setTimeout(resolve, 10 + attempt * 10));
7820
+ }
7821
+ }
7822
+ }
7823
+
7811
7824
  // packages/core/src/log.js
7812
7825
  var LEVELS = Object.freeze({ debug: 10, info: 20, warn: 30, error: 40 });
7813
7826
  var REDACTED = "[redacted]";
@@ -7927,27 +7940,55 @@ var TAIL_BYTES = 256 * 1024;
7927
7940
  var MAX_FRAME = 16 * 1024 * 1024;
7928
7941
  var ERROR = Object.freeze({ failed: 1e3, notFound: 1001, forbidden: 1003, conflict: 1004, unavailable: 1005, protocol: 1006 });
7929
7942
  var RPC_ERROR = Object.freeze({ parseError: -32700, invalidRequest: -32600, methodNotFound: -32601, invalidParams: -32602 });
7930
- var CAPABILITY = Object.freeze({ attachAfter: "attach.after", promptReceipts: "prompt.receipts", extensionMethods: "extension.methods", team: "team", task: "task", library: "library", settingsLanguage: "settings.language", sessionListPage: "session.list.page", questionWatch: "question.watch", questionWatchTurns: "question.watch.turns", workspaceFiles: "workspace.files", workspaceFilesRead: "workspace.files.read", promptImages: "prompt.images" });
7943
+ var CAPABILITY = Object.freeze({ sessionInterruptTurn: "session.interrupt.turn", attachAfter: "attach.after", sessionHistory: "session.history", workspaceRegistry: "workspace.registry", workspaceWorktree: "workspace.worktree", workspaceGit: "workspace.git", promptReceipts: "prompt.receipts", extensionMethods: "extension.methods", team: "team", task: "task", library: "library", libraryProjectWrite: "library.project.write", settingsLanguage: "settings.language", sessionListPage: "session.list.page", questionWatch: "question.watch", questionWatchTurns: "question.watch.turns", sessionAttention: "session.attention", workspaceFiles: "workspace.files", workspaceFilesRead: "workspace.files.read", promptImages: "prompt.images", schedule: "schedule", attachments: "attachments", sessionFork: "session.fork", sessionRewind: "session.rewind", sessionReload: "session.reload", sessionResumeCommand: "session.resumeCommand", sessionConfigureLive: "session.configure.live", terminal: "terminal" });
7931
7944
  var PROMPT_IMAGES = Object.freeze({ mimeTypes: Object.freeze(["image/png", "image/jpeg", "image/gif", "image/webp"]), maxCount: 8, maxBytes: 5 * 1024 * 1024, maxTotalBytes: 11 * 1024 * 1024 });
7932
- var RPC_METHODS = Object.freeze(["assignment.recall", "board.list", "catalog.get", "daemon.hello", "daemon.pause", "daemon.pauses", "daemon.resume", "daemon.shutdown", "daemon.status", "daemon.usage", "extension.register", "extension.unregister", "library.delete", "library.duplicate", "library.get", "library.list", "library.models", "library.rename", "library.save", "library.skills.set", "question.answer", "question.list", "question.watch", "session.archive", "session.attach", "session.close", "session.configure", "session.create", "session.get", "session.interrupt", "session.list", "session.log", "session.message", "session.preview", "session.prompt", "session.release", "session.rename", "session.status", "settings.language.get", "settings.language.set", "task.create", "task.gate.resolve", "task.list", "task.update", "team.list", "workspace.files.list", "workspace.files.read", "workspace.files.search"]);
7945
+ var RPC_METHODS = Object.freeze(["assignment.recall", "attachment.abort", "attachment.begin", "attachment.chunk", "attachment.commit", "attachment.delete", "attachment.get", "board.list", "catalog.get", "daemon.hello", "daemon.pause", "daemon.pauses", "daemon.resume", "daemon.shutdown", "daemon.status", "daemon.usage", "extension.register", "extension.unregister", "library.delete", "library.duplicate", "library.get", "library.list", "library.models", "library.rename", "library.save", "library.skills.set", "project.list", "project.register", "project.remove", "question.answer", "question.list", "question.watch", "registry.owner", "registry.worktree", "schedule.cancel", "schedule.create", "schedule.get", "schedule.list", "session.archive", "session.attach", "session.attention.clear", "session.close", "session.configure", "session.configure.preview", "session.create", "session.fork", "session.get", "session.history", "session.interrupt", "session.list", "session.log", "session.message", "session.preview", "session.prompt", "session.release", "session.reload", "session.rename", "session.resumeCommand", "session.rewind", "session.status", "settings.language.get", "settings.language.set", "task.create", "task.gate.resolve", "task.list", "task.update", "team.list", "terminal.attach", "terminal.close", "terminal.create", "terminal.input", "terminal.list", "terminal.resize", "terminal.revoke", "workspace.files.list", "workspace.files.read", "workspace.files.search", "workspace.get", "workspace.git.diff", "workspace.git.status", "workspace.list", "workspace.update", "workspace.worktree.create", "workspace.worktree.options", "workspace.worktree.remove"]);
7933
7946
  var WORKSPACE_FILES = Object.freeze({ maxReadBytes: 1024 * 1024, maxListEntries: 1e3, maxPathLength: 4096 });
7934
-
7935
- // packages/core/src/atomic.js
7936
- import { rename, rm, writeFile } from "node:fs/promises";
7937
- async function moveFile(from, to) {
7938
- for (let attempt = 0; ; attempt++) {
7939
- try {
7940
- return await rename(from, to);
7941
- } catch (error51) {
7942
- if (process.platform !== "win32" || attempt >= 20 || !["EPERM", "EACCES", "EBUSY"].includes(error51?.code)) throw error51;
7943
- await new Promise((resolve) => setTimeout(resolve, 10 + attempt * 10));
7944
- }
7945
- }
7946
- }
7947
+ var WORKSPACE_GIT = Object.freeze({ maxFileBytes: 1024 * 1024, maxTotalBytes: 2 * 1024 * 1024, maxUntracked: 200, maxStatusFiles: 1e3, maxRefLength: 255 });
7948
+ var ATTACHMENTS = Object.freeze({
7949
+ maxObjectBytes: 20 * 1024 * 1024,
7950
+ maxPerPrompt: 8,
7951
+ maxPromptBytes: 40 * 1024 * 1024,
7952
+ maxChunkBytes: 256 * 1024,
7953
+ maxActiveUploads: 2,
7954
+ maxPrincipalBytes: 200 * 1024 * 1024,
7955
+ maxDaemonBytes: 1024 * 1024 * 1024,
7956
+ uploadTimeoutMs: 60 * 60 * 1e3,
7957
+ unreferencedRetentionMs: 24 * 60 * 60 * 1e3,
7958
+ releasedGraceMs: 7 * 24 * 60 * 60 * 1e3,
7959
+ maxNameBytes: 255
7960
+ });
7961
+ var TERMINAL = Object.freeze({
7962
+ maxPerPrincipal: 4,
7963
+ maxPerDaemon: 16,
7964
+ maxInputBytes: 64 * 1024,
7965
+ maxOutputFrameBytes: 64 * 1024,
7966
+ replayBytes: 1024 * 1024,
7967
+ idleMs: 30 * 60 * 1e3,
7968
+ maxLifetimeMs: 8 * 60 * 60 * 1e3,
7969
+ reconnectMs: 60 * 1e3,
7970
+ minCols: 2,
7971
+ maxCols: 500,
7972
+ minRows: 1,
7973
+ maxRows: 200
7974
+ });
7975
+ var TERMINAL_LIMIT_KEYS = Object.freeze(["maxPerPrincipal", "maxPerDaemon", "maxInputBytes", "maxOutputFrameBytes", "replayBytes", "idleMs", "maxLifetimeMs", "reconnectMs"]);
7976
+ var ATTACHMENT_CHUNK_OVERHEAD = 64 * 1024;
7947
7977
 
7948
7978
  // packages/runtime/src/board.ts
7949
7979
  var PIN_KINDS = ["claim", "decision", "finding"];
7950
7980
 
7981
+ // packages/runtime/src/attachments.ts
7982
+ import { constants, realpathSync } from "node:fs";
7983
+ var ATTACHMENT_ROUTES = Object.freeze({
7984
+ codex: Object.freeze(["file.path"]),
7985
+ claude: Object.freeze(["file.path"]),
7986
+ acp: Object.freeze([]),
7987
+ antigravity: Object.freeze([])
7988
+ });
7989
+ var NOFOLLOW = constants.O_NOFOLLOW ?? 0;
7990
+ var NONBLOCK = constants.O_NONBLOCK ?? 0;
7991
+
7951
7992
  // packages/core/src/errors.js
7952
7993
  var AlpError = class extends Error {
7953
7994
  constructor(code, message, options2) {
@@ -8058,7 +8099,7 @@ function thinkingOptionsFor(runtime, nativeModel) {
8058
8099
  }
8059
8100
 
8060
8101
  // packages/runtime/src/claude-transport.ts
8061
- import { accessSync, constants, existsSync, mkdirSync, realpathSync, rmdirSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
8102
+ import { accessSync, constants as constants2, existsSync, mkdirSync, realpathSync as realpathSync2, rmdirSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
8062
8103
  import path2 from "node:path";
8063
8104
 
8064
8105
  // node_modules/zod/v4/classic/external.js
@@ -22721,17 +22762,27 @@ var toolShapes = {
22721
22762
  body: external_exports.string().min(1).max(2e4),
22722
22763
  roles: external_exports.array(external_exports.string().min(1)).min(1).max(10),
22723
22764
  lessons: external_exports.array(external_exports.string().min(1).max(600)).max(50).optional(),
22724
- replace: external_exports.boolean().optional()
22765
+ replace: external_exports.boolean().optional(),
22766
+ requestId: external_exports.string().min(1).max(100).optional()
22725
22767
  },
22726
22768
  alp_issue: {
22727
22769
  action: external_exports.enum(["search", "create", "comment"]),
22728
22770
  target: external_exports.enum(["project", "alp"]),
22729
22771
  query: external_exports.string().min(1).max(200).optional(),
22772
+ requestId: external_exports.string().min(1).max(100).optional(),
22730
22773
  title: external_exports.string().min(1).max(200).optional(),
22731
22774
  body: external_exports.string().min(1).max(2e4).optional(),
22732
22775
  issue: external_exports.number().int().positive().optional(),
22733
22776
  labels: external_exports.array(external_exports.string().min(1).max(50)).max(10).optional()
22734
22777
  },
22778
+ alp_schedule: {
22779
+ action: external_exports.enum(["create", "list", "get", "cancel"]),
22780
+ dueAt: external_exports.string().min(1).max(80).optional(),
22781
+ prompt: external_exports.string().min(1).max(8e3).optional(),
22782
+ requestId: external_exports.string().min(1).max(200).optional(),
22783
+ id: external_exports.string().min(1).optional(),
22784
+ status: external_exports.enum(["pending", "delivered", "failed", "cancelled"]).optional()
22785
+ },
22735
22786
  alp_task: {
22736
22787
  action: external_exports.enum(["create", "update", "link", "start", "close", "reopen", "gate", "clear", "pour", "formulas", "show", "list", "ready"]),
22737
22788
  id: external_exports.string().min(1).optional(),
@@ -22966,8 +23017,9 @@ function validateUserSettings(settings, source) {
22966
23017
  }
22967
23018
  if (settings.web !== void 0) {
22968
23019
  check2(object4(settings.web), "web must be an object");
22969
- const extra = Object.keys(settings.web).find((field) => !["enabled", "port", "relay"].includes(field));
22970
- check2(!extra, `unsupported web field '${extra}'; use enabled, port or relay`);
23020
+ const extra = Object.keys(settings.web).find((field) => !["enabled", "port", "relay", "permissions"].includes(field));
23021
+ check2(!extra, `unsupported web field '${extra}'; use enabled, port, relay or permissions`);
23022
+ if (settings.web.permissions !== void 0) check2(Array.isArray(settings.web.permissions) && settings.web.permissions.every((entry) => typeof entry === "string" && /^[a-z][a-z.]*$/.test(entry)), "web.permissions must be a list of permission names, such as files.read");
22971
23023
  const relay = settings.web.relay;
22972
23024
  if (relay !== void 0) {
22973
23025
  check2(object4(relay), "web.relay must be an object");