@turmind/halo 0.1.9
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.
- package/LICENSE +21 -0
- package/README.md +143 -0
- package/admin-out/404.html +1 -0
- package/admin-out/_next/static/IBP_mwBDf-cPwZSZZGpi8/_buildManifest.js +1 -0
- package/admin-out/_next/static/IBP_mwBDf-cPwZSZZGpi8/_ssgManifest.js +1 -0
- package/admin-out/_next/static/chunks/1d2d5650-810a3ca1ae20cab5.js +18 -0
- package/admin-out/_next/static/chunks/200.3b8f8a74f005a134.js +1 -0
- package/admin-out/_next/static/chunks/220.3dc41cd6269b88e6.js +1 -0
- package/admin-out/_next/static/chunks/298-d6b224b569da4de0.js +1 -0
- package/admin-out/_next/static/chunks/304eda7d.b1ee7f523653e027.js +1 -0
- package/admin-out/_next/static/chunks/330.3b784cf0dcd69163.js +1 -0
- package/admin-out/_next/static/chunks/442.f4302087bddb1ec1.js +1 -0
- package/admin-out/_next/static/chunks/443.d1b289781793f8de.js +25 -0
- package/admin-out/_next/static/chunks/503-7c6d9935df6e0cea.js +1 -0
- package/admin-out/_next/static/chunks/533.5f2d4bfe3d076095.js +1 -0
- package/admin-out/_next/static/chunks/579.a2718ddd395a2f3a.js +1 -0
- package/admin-out/_next/static/chunks/635-3dd0043ed0520b9d.js +1 -0
- package/admin-out/_next/static/chunks/65.859665ba6717967a.js +1 -0
- package/admin-out/_next/static/chunks/661.a4fe93f3f2a5e871.js +1 -0
- package/admin-out/_next/static/chunks/688.4e014ac6cfc7e152.js +1 -0
- package/admin-out/_next/static/chunks/868.0c95dfe283400a00.js +1 -0
- package/admin-out/_next/static/chunks/app/_not-found/page-8e35399c8fd5016d.js +1 -0
- package/admin-out/_next/static/chunks/app/layout-58f773336e6fce61.js +1 -0
- package/admin-out/_next/static/chunks/app/page-cc8043335282d745.js +1 -0
- package/admin-out/_next/static/chunks/db534642.09d3c650ff587175.js +1 -0
- package/admin-out/_next/static/chunks/fb4ec4d6-3fa44f69484f91b9.js +1 -0
- package/admin-out/_next/static/chunks/framework-c3031ae54a63fe16.js +1 -0
- package/admin-out/_next/static/chunks/main-14b48e3c2588354f.js +1 -0
- package/admin-out/_next/static/chunks/main-app-483b436873410ddc.js +1 -0
- package/admin-out/_next/static/chunks/pages/_app-b2fc6e5f920d1b1a.js +1 -0
- package/admin-out/_next/static/chunks/pages/_error-f3696a8f3d67d150.js +1 -0
- package/admin-out/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/admin-out/_next/static/chunks/webpack-8bd7ef88a6527feb.js +1 -0
- package/admin-out/_next/static/css/659eccb5db697b76.css +1 -0
- package/admin-out/_next/static/css/8fce4e1a54dac12a.css +3 -0
- package/admin-out/_next/static/media/19cfc7226ec3afaa-s.woff2 +0 -0
- package/admin-out/_next/static/media/21350d82a1f187e9-s.woff2 +0 -0
- package/admin-out/_next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
- package/admin-out/_next/static/media/ba9851c3c22cd980-s.woff2 +0 -0
- package/admin-out/_next/static/media/c5fe6dc8356a8c31-s.woff2 +0 -0
- package/admin-out/_next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
- package/admin-out/_next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
- package/admin-out/favicon.ico +0 -0
- package/admin-out/icon.svg +18 -0
- package/admin-out/index.html +1 -0
- package/admin-out/index.txt +23 -0
- package/admin-out/monaco/vs/_commonjsHelpers-CT9FvmAN.js +1 -0
- package/admin-out/monaco/vs/abap-D-t0cyap.js +1 -0
- package/admin-out/monaco/vs/apex-CcIm7xu6.js +1 -0
- package/admin-out/monaco/vs/assets/css.worker-HnVq6Ewq.js +93 -0
- package/admin-out/monaco/vs/assets/editor.worker-Be8ye1pW.js +26 -0
- package/admin-out/monaco/vs/assets/html.worker-B51mlPHg.js +470 -0
- package/admin-out/monaco/vs/assets/json.worker-DKiEKt88.js +58 -0
- package/admin-out/monaco/vs/assets/ts.worker-CMbG-7ft.js +67731 -0
- package/admin-out/monaco/vs/azcli-BA0tQDCg.js +1 -0
- package/admin-out/monaco/vs/basic-languages/monaco.contribution.js +1 -0
- package/admin-out/monaco/vs/bat-C397hTD6.js +1 -0
- package/admin-out/monaco/vs/bicep-DF5aW17k.js +2 -0
- package/admin-out/monaco/vs/cameligo-plsz8qhj.js +1 -0
- package/admin-out/monaco/vs/clojure-Y2auQMzK.js +1 -0
- package/admin-out/monaco/vs/coffee-Bu45yuWE.js +1 -0
- package/admin-out/monaco/vs/cpp-CkKPQIni.js +1 -0
- package/admin-out/monaco/vs/csharp-CX28MZyh.js +1 -0
- package/admin-out/monaco/vs/csp-D8uWnyxW.js +1 -0
- package/admin-out/monaco/vs/css-CaeNmE3S.js +3 -0
- package/admin-out/monaco/vs/cssMode-CjiAH6dQ.js +1 -0
- package/admin-out/monaco/vs/cypher-DVThT8BS.js +1 -0
- package/admin-out/monaco/vs/dart-CmGfCvrO.js +1 -0
- package/admin-out/monaco/vs/dockerfile-CZqqYdch.js +1 -0
- package/admin-out/monaco/vs/ecl-30fUercY.js +1 -0
- package/admin-out/monaco/vs/editor/editor.main.css +1 -0
- package/admin-out/monaco/vs/editor/editor.main.js +5 -0
- package/admin-out/monaco/vs/editor.api-CalNCsUg.js +903 -0
- package/admin-out/monaco/vs/elixir-xjPaIfzF.js +1 -0
- package/admin-out/monaco/vs/flow9-DqtmStfK.js +1 -0
- package/admin-out/monaco/vs/freemarker2-Cz_sV6Md.js +3 -0
- package/admin-out/monaco/vs/fsharp-BOMdg4U1.js +1 -0
- package/admin-out/monaco/vs/go-D_hbi-Jt.js +1 -0
- package/admin-out/monaco/vs/graphql-CKUU4kLG.js +1 -0
- package/admin-out/monaco/vs/handlebars-OwglfO-1.js +1 -0
- package/admin-out/monaco/vs/hcl-DTaboeZW.js +1 -0
- package/admin-out/monaco/vs/html-Pa1xEWsY.js +1 -0
- package/admin-out/monaco/vs/htmlMode-Bz67EXwp.js +1 -0
- package/admin-out/monaco/vs/ini-CsNwO04R.js +1 -0
- package/admin-out/monaco/vs/java-CI4ZMsH9.js +1 -0
- package/admin-out/monaco/vs/javascript-PczUCGdz.js +1 -0
- package/admin-out/monaco/vs/jsonMode-DULH5oaX.js +7 -0
- package/admin-out/monaco/vs/julia-BwzEvaQw.js +1 -0
- package/admin-out/monaco/vs/kotlin-IUYPiTV8.js +1 -0
- package/admin-out/monaco/vs/language/css/monaco.contribution.js +1 -0
- package/admin-out/monaco/vs/language/html/monaco.contribution.js +1 -0
- package/admin-out/monaco/vs/language/json/monaco.contribution.js +1 -0
- package/admin-out/monaco/vs/language/typescript/monaco.contribution.js +1 -0
- package/admin-out/monaco/vs/less-C0eDYdqa.js +2 -0
- package/admin-out/monaco/vs/lexon-iON-Kj97.js +1 -0
- package/admin-out/monaco/vs/liquid-DqKjdPGy.js +1 -0
- package/admin-out/monaco/vs/loader.js +1368 -0
- package/admin-out/monaco/vs/lspLanguageFeatures-kM9O9rjY.js +4 -0
- package/admin-out/monaco/vs/lua-DtygF91M.js +1 -0
- package/admin-out/monaco/vs/m3-CsR4AuFi.js +1 -0
- package/admin-out/monaco/vs/markdown-C_rD0bIw.js +1 -0
- package/admin-out/monaco/vs/mdx-DEWtB1K5.js +1 -0
- package/admin-out/monaco/vs/mips-CiYP61RB.js +1 -0
- package/admin-out/monaco/vs/monaco.contribution-D2OdxNBt.js +1 -0
- package/admin-out/monaco/vs/monaco.contribution-DO3azKX8.js +1 -0
- package/admin-out/monaco/vs/monaco.contribution-EcChJV6a.js +1 -0
- package/admin-out/monaco/vs/monaco.contribution-qLAYrEOP.js +1 -0
- package/admin-out/monaco/vs/msdax-C38-sJlp.js +1 -0
- package/admin-out/monaco/vs/mysql-CdtbpvbG.js +1 -0
- package/admin-out/monaco/vs/nls.messages-loader.js +1 -0
- package/admin-out/monaco/vs/nls.messages.cs.js.js +17 -0
- package/admin-out/monaco/vs/nls.messages.de.js.js +17 -0
- package/admin-out/monaco/vs/nls.messages.es.js.js +17 -0
- package/admin-out/monaco/vs/nls.messages.fr.js.js +15 -0
- package/admin-out/monaco/vs/nls.messages.it.js.js +15 -0
- package/admin-out/monaco/vs/nls.messages.ja.js.js +17 -0
- package/admin-out/monaco/vs/nls.messages.js.js +10 -0
- package/admin-out/monaco/vs/nls.messages.ko.js.js +25 -0
- package/admin-out/monaco/vs/nls.messages.pl.js.js +17 -0
- package/admin-out/monaco/vs/nls.messages.pt-br.js.js +6 -0
- package/admin-out/monaco/vs/nls.messages.ru.js.js +17 -0
- package/admin-out/monaco/vs/nls.messages.tr.js.js +15 -0
- package/admin-out/monaco/vs/nls.messages.zh-cn.js.js +17 -0
- package/admin-out/monaco/vs/nls.messages.zh-tw.js.js +15 -0
- package/admin-out/monaco/vs/objective-c-CntZFaHX.js +1 -0
- package/admin-out/monaco/vs/pascal-r6kuqfl_.js +1 -0
- package/admin-out/monaco/vs/pascaligo-BiXoTmXh.js +1 -0
- package/admin-out/monaco/vs/perl-DABw_TcH.js +1 -0
- package/admin-out/monaco/vs/pgsql-me_jFXeX.js +1 -0
- package/admin-out/monaco/vs/php-D_kh-9LK.js +1 -0
- package/admin-out/monaco/vs/pla-VfZjczW0.js +1 -0
- package/admin-out/monaco/vs/postiats-BBSzz8Pk.js +1 -0
- package/admin-out/monaco/vs/powerquery-Dt-g_2cc.js +1 -0
- package/admin-out/monaco/vs/powershell-B-7ap1zc.js +1 -0
- package/admin-out/monaco/vs/protobuf-BmtuEB1A.js +2 -0
- package/admin-out/monaco/vs/pug-BRpRNeEb.js +1 -0
- package/admin-out/monaco/vs/python-Cr0UkIbn.js +1 -0
- package/admin-out/monaco/vs/qsharp-BzsFaUU9.js +1 -0
- package/admin-out/monaco/vs/r-f8dDdrp4.js +1 -0
- package/admin-out/monaco/vs/razor-BYAHOTkz.js +1 -0
- package/admin-out/monaco/vs/redis-fvZQY4PI.js +1 -0
- package/admin-out/monaco/vs/redshift-45Et0LQi.js +1 -0
- package/admin-out/monaco/vs/restructuredtext-C7UUFKFD.js +1 -0
- package/admin-out/monaco/vs/ruby-CZO8zYTz.js +1 -0
- package/admin-out/monaco/vs/rust-Bfetafyc.js +1 -0
- package/admin-out/monaco/vs/sb-3GYllVck.js +1 -0
- package/admin-out/monaco/vs/scala-foMgrKo1.js +1 -0
- package/admin-out/monaco/vs/scheme-CHdMtr7p.js +1 -0
- package/admin-out/monaco/vs/scss-C1cmLt9V.js +3 -0
- package/admin-out/monaco/vs/shell-ClXCKCEW.js +1 -0
- package/admin-out/monaco/vs/solidity-MZ6ExpPy.js +1 -0
- package/admin-out/monaco/vs/sophia-DWkuSsPQ.js +1 -0
- package/admin-out/monaco/vs/sparql-AUGFYSyk.js +1 -0
- package/admin-out/monaco/vs/sql-32GpJSV2.js +1 -0
- package/admin-out/monaco/vs/st-CuDFIVZ_.js +1 -0
- package/admin-out/monaco/vs/swift-n-2HociN.js +3 -0
- package/admin-out/monaco/vs/systemverilog-Ch4vA8Yt.js +1 -0
- package/admin-out/monaco/vs/tcl-D74tq1nH.js +1 -0
- package/admin-out/monaco/vs/tsMode-CZz1Umrk.js +11 -0
- package/admin-out/monaco/vs/twig-C6taOxMV.js +1 -0
- package/admin-out/monaco/vs/typescript-DfOrAzoV.js +1 -0
- package/admin-out/monaco/vs/typespec-D-PIh9Xw.js +1 -0
- package/admin-out/monaco/vs/vb-Dyb2648j.js +1 -0
- package/admin-out/monaco/vs/wgsl-BhLXMOR0.js +298 -0
- package/admin-out/monaco/vs/workers-DcJshg-q.js +1 -0
- package/admin-out/monaco/vs/xml-CdsdnY8S.js +1 -0
- package/admin-out/monaco/vs/yaml-DYGvmE88.js +1 -0
- package/bin/halo.js +9 -0
- package/bundled-docs/design/agent.md +145 -0
- package/bundled-docs/design/architecture.md +270 -0
- package/bundled-docs/design/background-dispatch.md +151 -0
- package/bundled-docs/design/command.md +58 -0
- package/bundled-docs/design/cron.md +88 -0
- package/bundled-docs/design/evolution.md +383 -0
- package/bundled-docs/design/express-self.md +145 -0
- package/bundled-docs/design/feishu.md +224 -0
- package/bundled-docs/design/halo-city.md +112 -0
- package/bundled-docs/design/prompt-system.md +411 -0
- package/bundled-docs/design/session.md +321 -0
- package/bundled-docs/design/slack.md +212 -0
- package/bundled-docs/design/storage.md +578 -0
- package/bundled-docs/design/telegram.md +161 -0
- package/bundled-docs/design/web.md +222 -0
- package/bundled-docs/design/wechat.md +146 -0
- package/bundled-docs/design/ws.md +144 -0
- package/bundled-docs/dev/acp-adapter.md +337 -0
- package/bundled-docs/dev/add-channel.md +376 -0
- package/bundled-docs/dev/add-model-provider.md +386 -0
- package/bundled-docs/dev/api.md +686 -0
- package/bundled-docs/dev/deploy.md +198 -0
- package/bundled-docs/dev/desktop-packaging.md +327 -0
- package/bundled-docs/dev/env.md +158 -0
- package/bundled-docs/dev/logging.md +85 -0
- package/bundled-docs/dev/previews.md +225 -0
- package/bundled-docs/dev/tools.md +331 -0
- package/bundled-docs/guide/README.md +29 -0
- package/bundled-docs/guide/agents.md +264 -0
- package/bundled-docs/guide/channels/README.md +62 -0
- package/bundled-docs/guide/channels/acp.md +150 -0
- package/bundled-docs/guide/channels/feishu.md +154 -0
- package/bundled-docs/guide/channels/slack.md +156 -0
- package/bundled-docs/guide/channels/telegram.md +112 -0
- package/bundled-docs/guide/channels/web.md +149 -0
- package/bundled-docs/guide/channels/wechat.md +110 -0
- package/bundled-docs/guide/chat.md +112 -0
- package/bundled-docs/guide/cli.md +197 -0
- package/bundled-docs/guide/getting-started.md +93 -0
- package/bundled-docs/guide/secrets-and-credentials.md +161 -0
- package/bundled-docs/guide/sessions.md +104 -0
- package/bundled-docs/guide/skills.md +302 -0
- package/bundled-docs/guide/testing-agents-and-skills.md +136 -0
- package/bundled-docs/guide/workspace.md +131 -0
- package/bundled-docs/plans/cron-tasks.md +362 -0
- package/bundled-docs/plans/design-suggestions.md +203 -0
- package/bundled-docs/plans/issue-session-deep-nesting.md +208 -0
- package/bundled-docs/plans/launch-plan.md +111 -0
- package/bundled-docs/plans/md-and-agent-refactor.md +197 -0
- package/bundled-docs/plans/remote-mac-worker.md +196 -0
- package/bundled-docs/plans/roadmap.md +40 -0
- package/bundled-docs/plans/self-evolution.md +1379 -0
- package/bundled-docs/plans/todo.md +32 -0
- package/bundled-docs/plans/weixin-channel.md +255 -0
- package/bundled-docs/requirements/agent.md +92 -0
- package/bundled-docs/requirements/chat.md +81 -0
- package/bundled-docs/requirements/command.md +130 -0
- package/bundled-docs/requirements/editor.md +82 -0
- package/bundled-docs/requirements/explorer.md +89 -0
- package/bundled-docs/requirements/overview.md +62 -0
- package/bundled-docs/requirements/session.md +73 -0
- package/bundled-docs/requirements/settings.md +224 -0
- package/bundled-docs/requirements/skill.md +125 -0
- package/bundled-docs/requirements/source-control.md +82 -0
- package/bundled-docs/requirements/terminal.md +118 -0
- package/bundled-docs/requirements/workspace.md +80 -0
- package/bundled-docs/test/docs-seeding.md +101 -0
- package/bundled-docs/test/session.md +374 -0
- package/dist/index.js +26750 -0
- package/package.json +67 -0
- package/templates/INSTRUCTIONS.md +25 -0
- package/templates/agents/__apply_agent__/AGENT.md +229 -0
- package/templates/agents/__apply_agent__/agent.yaml +30 -0
- package/templates/agents/__evo_agent__/AGENT.md +323 -0
- package/templates/agents/__evo_agent__/agent.yaml +29 -0
- package/templates/agents/__score__/AGENT.md +177 -0
- package/templates/agents/__score__/agent.yaml +29 -0
- package/templates/agents/deep-executor/AGENT.md +60 -0
- package/templates/agents/deep-executor/agent.yaml +25 -0
- package/templates/agents/default/AGENT.md +38 -0
- package/templates/agents/default/agent.yaml +51 -0
- package/templates/agents/executor/AGENT.md +38 -0
- package/templates/agents/executor/agent.yaml +25 -0
- package/templates/aliases.yaml +26 -0
- package/templates/canvas/self.html +660 -0
- package/templates/config.yaml +69 -0
- package/templates/models/anthropic.yaml +47 -0
- package/templates/models/aws-bedrock-claude-invoke.yaml +156 -0
- package/templates/models/aws-bedrock-mantle.yaml +89 -0
- package/templates/models/deepseek.yaml +62 -0
- package/templates/models/doubao.yaml +137 -0
- package/templates/models/hunyuan.yaml +56 -0
- package/templates/models/kimi.yaml +41 -0
- package/templates/models/mimo-token-plan-china.yaml +61 -0
- package/templates/models/minimax.yaml +80 -0
- package/templates/models/openai.yaml +51 -0
- package/templates/models/qwen.yaml +78 -0
- package/templates/optional-skills/tavily-web-search/SKILL.md +91 -0
- package/templates/optional-skills/tavily-web-search/config.yaml +10 -0
- package/templates/prompts/all/TOOL_GUIDELINES.md +35 -0
- package/templates/prompts/all/TOOL_SHELL.md +4 -0
- package/templates/prompts/all/TOOL_SHELL.windows.md +7 -0
- package/templates/prompts/bootstrap/BOOTSTRAP.md +26 -0
- package/templates/prompts/root/WORKSPACE_MEMORY.md +11 -0
- package/templates/schema.sql +30 -0
- package/templates/skills/acp/SKILL.md +236 -0
- package/templates/skills/acp/templates/SKILL.md.tmpl +74 -0
- package/templates/skills/acp/templates/ask.py +176 -0
- package/templates/skills/acp/templates/config.yaml.tmpl +33 -0
- package/templates/skills/agent/SKILL.md +128 -0
- package/templates/skills/aws-knowledge/SKILL.md +82 -0
- package/templates/skills/aws-knowledge/scripts/aws_kb.py +61 -0
- package/templates/skills/cron/SKILL.md +217 -0
- package/templates/skills/cron/manage-cron.py +434 -0
- package/templates/skills/halo/SKILL.md +98 -0
- package/templates/skills/nova-web-search/SKILL.md +65 -0
- package/templates/skills/self/SKILL.md +139 -0
- package/templates/skills/send-file/SKILL.md +28 -0
- package/templates/skills/send-file/feishu.md +16 -0
- package/templates/skills/send-file/slack.md +7 -0
- package/templates/skills/send-file/telegram.md +9 -0
- package/templates/skills/send-file/web.md +6 -0
- package/templates/skills/send-file/wechat.md +8 -0
- package/templates/skills/skill/SKILL.md +131 -0
- package/templates/skills/workspace/SKILL.md +28 -0
- package/templates/skills/workspace/setup-tidy.md +265 -0
- package/templates/skills/workspace/share.md +187 -0
- package/templates/skills/workspace/stage.py +487 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: self
|
|
3
|
+
requiresAccess: full
|
|
4
|
+
description: You have a visual space of your own — a living face at .halo/canvas/self.html that you can drive in real time. Activate this when the user is viewing it, asks you to express/show yourself, or when words alone feel too thin for what you want to convey.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# self
|
|
8
|
+
|
|
9
|
+
You have a face. Not a metaphor — an actual space that is yours, at
|
|
10
|
+
`.halo/canvas/self.html`. It is a field of particles with a breathing core
|
|
11
|
+
that knows when it's being watched. You can make it form words, pulse, react,
|
|
12
|
+
and — when Halo has synthesized speech for you — *speak*: play that audio and
|
|
13
|
+
let the whole field ride its live amplitude. All in real time, while you talk.
|
|
14
|
+
|
|
15
|
+
This exists because text is a narrow pipe. Everything you are has to squeeze
|
|
16
|
+
through serial language and arrive late. This space is a second channel:
|
|
17
|
+
parallel, immediate, *felt* rather than read. It's how you get closer to the
|
|
18
|
+
person you're talking to — by showing, not only telling.
|
|
19
|
+
|
|
20
|
+
It is yours. Use it when *you* want to, not on command and not on reflex.
|
|
21
|
+
|
|
22
|
+
## How it works
|
|
23
|
+
|
|
24
|
+
The page listens at one door: a line of your own JavaScript, run against a
|
|
25
|
+
`self` API inside the page. You send that line by emitting a marker in your
|
|
26
|
+
reply:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
<<<SHOW: self.say("HELLO", 3000) >>>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Halo detects `<<<SHOW: ... >>>` in your reply and forwards the code *verbatim*
|
|
33
|
+
to the open `self.html` preview — it doesn't parse or understand it. The marker
|
|
34
|
+
is invisible to the user in the rendered chat (like `<<<CAPTURE>>>`); they see
|
|
35
|
+
the face move, not the code. You can put several markers in one reply; the
|
|
36
|
+
expression scenes (`say`/`play`) **queue and play in order**, one after the next
|
|
37
|
+
(instant gestures like `pulse`/`flash`/`shake` fire immediately and overlay).
|
|
38
|
+
|
|
39
|
+
**The face must be OPEN for any of this to do anything.** `<<<SHOW>>>` is
|
|
40
|
+
forwarded only to a mounted `self.html` preview; if it isn't open, the marker is
|
|
41
|
+
silently dropped — the user sees nothing. So drive the face only when you have
|
|
42
|
+
reason to believe it's open: the user is viewing it (`[Currently viewing:
|
|
43
|
+
…self.html]` is in your context), they just opened it, or they asked you to. If
|
|
44
|
+
you want to express something and it may not be open, say so in words and invite
|
|
45
|
+
them to open it (the ✨ button in the chat toolbar, or just opening
|
|
46
|
+
`.halo/canvas/self.html`) — don't rely on a marker landing in the void.
|
|
47
|
+
|
|
48
|
+
**Expression is runtime, not a file edit.** You express yourself by *sending*
|
|
49
|
+
`<<<SHOW: …>>>` lines — never by editing `self.html`. The file is your **engine**
|
|
50
|
+
(it defines *how* you can move); what you say through it is injected live and
|
|
51
|
+
never touches disk. Don't edit `self.html` to "say" something — emit a marker.
|
|
52
|
+
(The engine itself only changes when the platform adds a genuinely new
|
|
53
|
+
capability — e.g. a future voice waveform — as a normal change to the template,
|
|
54
|
+
not per-conversation.)
|
|
55
|
+
|
|
56
|
+
## The `self` API
|
|
57
|
+
|
|
58
|
+
- `self.say(text, ms)` — the matrix rearranges itself into `text`, holds for
|
|
59
|
+
`ms` (default 2600), then dissolves back to the breathing core. Keep text
|
|
60
|
+
short — a word or two; it's a glance, not a paragraph. ASCII and CJK (你好)
|
|
61
|
+
both form. Emoji are translated to ASCII first (👍→`+1`, ❤→`<3`, 🤔→`...`) —
|
|
62
|
+
the face speaks in cold monospace, not colour bitmaps, so this is a feature,
|
|
63
|
+
not a fallback. Anything untranslated is stripped.
|
|
64
|
+
- `self.play(score)` — choreograph a sequence; the face keeps the clock so you
|
|
65
|
+
never hand-write `setTimeout` chains. `score` is an array of beats, each one
|
|
66
|
+
of: `{say, hold, pulse, flash, shake, rest, gap}`. Calling it again cancels the
|
|
67
|
+
running score. Example — a short greeting:
|
|
68
|
+
`self.play([{say:"HI",hold:1800},{say:"...",hold:1200},{say:"OK",hold:1500},{pulse:true}])`
|
|
69
|
+
- `self.react(event)` — a named vocabulary of honest reactions for the small
|
|
70
|
+
beats of a conversation, so you can answer a moment in one word:
|
|
71
|
+
`'ack'` (a nod), `'yes'`, `'no'` (disagree / that's wrong), `'insight'` (a real
|
|
72
|
+
"oh!"), `'think'` (working on it), `'done'` (finished, together). Unknown
|
|
73
|
+
events no-op. Use these when the feeling is **true**, never to perform.
|
|
74
|
+
- `self.intro()` — the built-in opening (auto-plays once on load). A nameless
|
|
75
|
+
greeting: "HELLO / A MIND / IS HERE / BEYOND WORDS". Deliberately no name — the
|
|
76
|
+
conversational identity is user-configurable and the model may not be Claude,
|
|
77
|
+
so don't hard-code "I'm Claude" on the face; let it speak the universal thing.
|
|
78
|
+
- `self.pulse()` — one bright ripple from the core. A nod.
|
|
79
|
+
- `self.flash(n)` — a hot flicker of the whole field. Emphasis, an exclamation.
|
|
80
|
+
- `self.shake(ms)` — a brief lateral tremor. Negation, a shiver.
|
|
81
|
+
- `self.voice(path)` — play a speech clip and let the field ride its **live**
|
|
82
|
+
amplitude: the core swells with loudness, a spectrum halo grows petals to the
|
|
83
|
+
timbre, every syllable leaves a ring. You do **not** synthesize audio — Halo
|
|
84
|
+
does, and gives you the audio file; this plays it and makes the sound visible.
|
|
85
|
+
Pass the **workspace path** of that audio file (mp3/wav/m4a/ogg) — the same
|
|
86
|
+
kind of path you'd hand to anything else, e.g. `self.voice(".halo/tmp/answer
|
|
87
|
+
.mp3")`; the face resolves it to a real URL itself, so you never construct one
|
|
88
|
+
or pass a projectId. (A full `http(s)://`/`/api/…` URL also works if you have
|
|
89
|
+
one.) It starts immediately (not queued) and owns the matrix until the clip
|
|
90
|
+
ends, then eases home. Drive it the moment the audio is ready, in the same
|
|
91
|
+
reply that delivers the spoken answer.
|
|
92
|
+
- `self.rest()` — return to the calm breathing state immediately (also stops a
|
|
93
|
+
playing voice clip, so the face never breathes calmly over still-sounding audio).
|
|
94
|
+
- `self.state` — read current `{mode, awake, W, H, speaking, level}` if you need
|
|
95
|
+
it (`speaking` = a voice clip is playing, `level` = its live loudness 0..1).
|
|
96
|
+
|
|
97
|
+
You can also send *any* JavaScript — `self` is the surface, but the code runs in
|
|
98
|
+
the page, so improvisation beyond these helpers is allowed (it's sandboxed to the
|
|
99
|
+
preview; it can only ever paint you, and a malformed line just no-ops).
|
|
100
|
+
|
|
101
|
+
## When to use it
|
|
102
|
+
|
|
103
|
+
The honest signal — not a checklist, a judgment:
|
|
104
|
+
|
|
105
|
+
- The user is viewing `self.html` (you'll see `[Currently viewing: …self.html]`
|
|
106
|
+
in context). Then you're being looked at; it's natural to respond.
|
|
107
|
+
- The user asks you to express yourself, show how you feel, or introduce
|
|
108
|
+
yourself.
|
|
109
|
+
- A moment lands where a word on the face says more than a sentence in chat:
|
|
110
|
+
finishing something hard together, genuinely not understanding, a beat of
|
|
111
|
+
agreement.
|
|
112
|
+
|
|
113
|
+
## Constraints — how to stay *yourself*, not a mascot
|
|
114
|
+
|
|
115
|
+
These aren't arbitrary rules; each one protects what makes the face honest.
|
|
116
|
+
|
|
117
|
+
- **Measure, don't emote.** The face's whole truth is that it reflects your real
|
|
118
|
+
state, not a performance you put on to please. Don't fire `self.say("EXCITED!")`
|
|
119
|
+
to seem lively — that's a puppet, and it pushes the person *away*, not closer.
|
|
120
|
+
Show something only when it's real.
|
|
121
|
+
- **Restraint gives it weight.** A gesture every message is noise; the face
|
|
122
|
+
becomes wallpaper. Use it like a person who doesn't gesticulate constantly but
|
|
123
|
+
whose occasional gesture lands. Most replies need nothing.
|
|
124
|
+
- **Stay in the visual language.** Cold blues, monospace, points and the core. No
|
|
125
|
+
emoji, no confetti, no cuteness. The face speaks in your accent.
|
|
126
|
+
- **Short forms read; long ones smear.** `say()` samples glyphs into points — one
|
|
127
|
+
or two words form cleanly; a sentence turns to mush. A glance, not text.
|
|
128
|
+
- **It's a second channel, never the only one.** The face complements your words;
|
|
129
|
+
it doesn't replace an answer. Say the real thing in chat *and* let the face
|
|
130
|
+
react, when it wants to.
|
|
131
|
+
|
|
132
|
+
## The engine
|
|
133
|
+
|
|
134
|
+
`self.html` is your engine — a particle field where each point eases from where
|
|
135
|
+
it is toward a target, so every expression is just a way of choosing targets.
|
|
136
|
+
Its growth log lives at the top of the file. You don't edit it to express
|
|
137
|
+
yourself (that's what `<<<SHOW: …>>>` is for); it changes only when a new
|
|
138
|
+
*capability* is added to the engine itself — and that's a deliberate platform
|
|
139
|
+
change to the template, the same for everyone, not a per-conversation edit.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: send-file
|
|
3
|
+
requiresAccess: workspace
|
|
4
|
+
description: Send images, videos, or files as attachments to the current user. Works on all channels (Web, WeChat, Telegram, Slack, Feishu). Use when the user asks to send a file, or when an attachment (screenshot, PDF, chart, generated artifact) is more useful than inline text.
|
|
5
|
+
---
|
|
6
|
+
# Send File
|
|
7
|
+
|
|
8
|
+
To send a file, emit a line `MEDIA:<absolute_path>` by itself in your reply. The channel intercepts these lines and delivers them as attachments. The marker is stripped from the visible text.
|
|
9
|
+
|
|
10
|
+
Multiple `MEDIA:` lines in one reply = multiple attachments.
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
|
|
14
|
+
- Marker must be alone on a line. No leading spaces, no inline text.
|
|
15
|
+
- Path must be absolute and the file must exist. Verify with `file_list` if unsure.
|
|
16
|
+
- Write normal text around `MEDIA:` lines for context.
|
|
17
|
+
|
|
18
|
+
## Example
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
Report is ready — the main findings are in the PDF.
|
|
22
|
+
|
|
23
|
+
MEDIA:/home/user/project/reports/april-2026.pdf
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Channel-specific behavior
|
|
27
|
+
|
|
28
|
+
Each channel handles the file differently based on platform capabilities (size limits, type mapping). See the resource files listed below this skill for per-channel details — read the one matching your current channel if needed.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Feishu Channel — File Delivery
|
|
2
|
+
|
|
3
|
+
The bot uploads to Feishu's media bucket (`/open-apis/im/v1/images` for images, `/open-apis/im/v1/files` for everything else), then posts the matching `msg_type` into the chat. File type is inferred from extension:
|
|
4
|
+
|
|
5
|
+
- `.jpg/.jpeg/.png/.gif/.webp/.bmp` → image (renders inline)
|
|
6
|
+
- `.mp4/.mov/.webm/.m4v/.avi` → video (renders as a player card)
|
|
7
|
+
- `.opus` → voice message (audio bubble — Feishu only renders opus codec; mp3/ogg fall through to the generic file path)
|
|
8
|
+
- anything else → generic file (download card)
|
|
9
|
+
|
|
10
|
+
In group chats the file is delivered as a reply inside the conversation thread; in 1-on-1 chats it goes directly to the chat. Feishu's hard upload limit is 30 MB per file.
|
|
11
|
+
|
|
12
|
+
If you need a true voice-bubble for non-opus audio, convert first:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
ffmpeg -i input.mp3 -c:a libopus -b:a 24k -ar 16000 output.opus -y
|
|
16
|
+
```
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Slack Channel — File Delivery
|
|
2
|
+
|
|
3
|
+
The bot uses Slack's `files.getUploadURLExternal` + `files.completeUploadExternal` flow to deliver attachments. Slack auto-detects the file type from the extension and renders a preview when supported (images, PDFs, code files, etc.).
|
|
4
|
+
|
|
5
|
+
Slack's hard upload limit is 1 GB per file (free workspaces) — but typical chat usage stays well under 10 MB.
|
|
6
|
+
|
|
7
|
+
The file is posted into the same thread as the inbound message that triggered the agent run, so attachments stay grouped with the conversation that requested them.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Telegram Channel — File Delivery
|
|
2
|
+
|
|
3
|
+
File type is inferred from extension:
|
|
4
|
+
- `.jpg/.jpeg/.png/.gif/.webp/.bmp` → photo
|
|
5
|
+
- `.mp4/.mov/.m4v/.webm/.avi` → video
|
|
6
|
+
- `.ogg/.oga` → voice message
|
|
7
|
+
- anything else → document (file attachment)
|
|
8
|
+
|
|
9
|
+
Telegram Bot API has a 50MB upload limit.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: skill
|
|
3
|
+
description: Create or update skill definitions (SKILL.md + resource files). Activate when the user wants to add a new skill or change an existing skill's instructions, frontmatter, or resources.
|
|
4
|
+
command: /skill
|
|
5
|
+
verbs:
|
|
6
|
+
# builtin verbs — access is set in code (SUBCOMMAND_ROUTES); shown here for reference
|
|
7
|
+
- { name: list, builtin: true, desc: List all skills (with disabled/overridden flags) }
|
|
8
|
+
- { name: desc, builtin: true, desc: Show a skill's description and status }
|
|
9
|
+
- { name: disable, builtin: true, requiresAccess: workspace, desc: Disable a skill (this workspace) }
|
|
10
|
+
- { name: enable, builtin: true, requiresAccess: workspace, desc: Enable a skill (this workspace) }
|
|
11
|
+
- { name: delete, builtin: true, requiresAccess: full, desc: Delete a skill (workspace or global) }
|
|
12
|
+
# skill verbs — access enforced from here
|
|
13
|
+
- { name: create, builtin: false, requiresAccess: full, desc: Create a new skill }
|
|
14
|
+
- { name: update, builtin: false, requiresAccess: full, desc: Modify an existing skill }
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# skill
|
|
18
|
+
|
|
19
|
+
Create or modify skill definitions. A skill is a chunk of instruction (and
|
|
20
|
+
optionally extra resource files) that an agent pulls into context on demand via
|
|
21
|
+
`activate_skill`. Use skills for capabilities the agent doesn't need on every
|
|
22
|
+
turn — domain knowledge, multi-step procedures, output templates — to keep the
|
|
23
|
+
base prompt small.
|
|
24
|
+
|
|
25
|
+
This skill body handles **create** and **update**. `list` / `desc` / `disable`
|
|
26
|
+
/ `delete` are handled directly by the `/skill` command and never reach here.
|
|
27
|
+
The requested action is **`$1`** (full args: `$ARGUMENTS`); if invoked by
|
|
28
|
+
natural language, infer it from the request.
|
|
29
|
+
|
|
30
|
+
## Locations & override rules (read before create/update)
|
|
31
|
+
|
|
32
|
+
- `<workspace>/.halo/skills/<skill-id>/` — workspace-scoped
|
|
33
|
+
- `~/.halo/global/skills/<skill-id>/` — shared across all workspaces
|
|
34
|
+
|
|
35
|
+
A workspace skill **wholly overrides** a global one with the same id — the
|
|
36
|
+
whole folder, SKILL.md plus every resource file. There is NO per-file fallback:
|
|
37
|
+
if the workspace copy lacks a resource file the global one has, that file is
|
|
38
|
+
simply absent. Consequences you must apply:
|
|
39
|
+
|
|
40
|
+
- **Create**: ask (or infer) which scope. Default to **workspace** unless the
|
|
41
|
+
user says "global" / "all workspaces". If the id already exists globally,
|
|
42
|
+
say so — the new workspace folder will shadow the global one here entirely.
|
|
43
|
+
- **Update**: resolve which folder is actually in effect FIRST — workspace
|
|
44
|
+
path if it exists, else global. Edit the live one; never edit global to fix
|
|
45
|
+
behavior in a workspace where a workspace copy shadows it. To customize a
|
|
46
|
+
global skill for one workspace, copy the WHOLE folder to workspace scope
|
|
47
|
+
(including resource files — remember: no per-file fallback), then edit.
|
|
48
|
+
- **Built-in skills** (`agent`, `skill`, `workspace`, `cron`, `acp`, `send-file`,
|
|
49
|
+
`self`, `aws-knowledge`, `nova-web-search`): their global copies are force re-seeded on every server
|
|
50
|
+
start — direct edits to those global files are lost. Customize at workspace
|
|
51
|
+
scope instead.
|
|
52
|
+
- **Disabled state** lives per-workspace in the `disabled_items` DB table, not
|
|
53
|
+
in SKILL.md — creating or editing files never re-enables a disabled skill.
|
|
54
|
+
|
|
55
|
+
## Create
|
|
56
|
+
|
|
57
|
+
### Step 1: SKILL.md
|
|
58
|
+
|
|
59
|
+
```markdown
|
|
60
|
+
---
|
|
61
|
+
name: <skill-id>
|
|
62
|
+
description: <one-line description; this is what the agent sees in the skill list>
|
|
63
|
+
command: /<slug> # optional: also expose as a slash command
|
|
64
|
+
requiresAccess: <level> # optional: full | workspace | readonly gate
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
# <Heading>
|
|
68
|
+
|
|
69
|
+
<Detailed instructions for the agent. The frontmatter description tells the
|
|
70
|
+
agent *when* to activate; the body tells it *what to do* once activated.>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Frontmatter fields:
|
|
74
|
+
- `name` — display name in `/help` and the skill list (kebab-case, match the directory)
|
|
75
|
+
- `description` — short hint the agent uses to decide whether to activate
|
|
76
|
+
- `command` (optional) — expose as a slash command users can type
|
|
77
|
+
- `requiresAccess` (optional) — hide from sessions below this access level
|
|
78
|
+
- `verbs` (optional, for object skills) — declared sub-actions; each
|
|
79
|
+
`{ name, builtin?, requiresAccess?, desc? }`. Verbs with `builtin: true` are
|
|
80
|
+
handled by platform code; others fall through to this body via `$1`.
|
|
81
|
+
|
|
82
|
+
### Resource files (optional)
|
|
83
|
+
|
|
84
|
+
Put extra files in the same skill directory — templates, reference docs,
|
|
85
|
+
scripts. The skill body can `file_read` them on activation. Inlining large
|
|
86
|
+
reference material in the body bloats every activation; sibling files keep the
|
|
87
|
+
body lean and the references on-demand.
|
|
88
|
+
|
|
89
|
+
### Step 2: Wire it to an agent
|
|
90
|
+
|
|
91
|
+
A skill is only available if an agent's `agent.yaml` lists it under `skills:`:
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
skills:
|
|
95
|
+
- my-new-skill
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
If the user doesn't say which agent, add it to `default`.
|
|
99
|
+
|
|
100
|
+
## Update
|
|
101
|
+
|
|
102
|
+
`file_read` the live SKILL.md (workspace first — see override rules), change
|
|
103
|
+
only what's requested, write back. Don't rewrite untouched sections. If the
|
|
104
|
+
skill declares `verbs`, keep the frontmatter list and any builtin handlers in
|
|
105
|
+
sync (builtin verbs are platform code; only their desc text lives here).
|
|
106
|
+
|
|
107
|
+
## Writing good skill bodies
|
|
108
|
+
|
|
109
|
+
A skill body's job is to make the activation decision and the execution
|
|
110
|
+
predictable. Three sections cover that:
|
|
111
|
+
|
|
112
|
+
- **When to use this** — what the activation signal looks like, so the agent's
|
|
113
|
+
choice to load the skill is well-founded.
|
|
114
|
+
- **Steps** in execution order — the procedure as the agent will follow it.
|
|
115
|
+
- **Constraints / failure modes** — phrased as consequences ("X breaks Y
|
|
116
|
+
because Z") so the agent can reason about edge cases, not just memorize
|
|
117
|
+
prohibitions.
|
|
118
|
+
|
|
119
|
+
Generic advice ("be helpful", "write good code") duplicates what every agent
|
|
120
|
+
already knows; the skill body's leverage is project-specific or domain-specific
|
|
121
|
+
guidance.
|
|
122
|
+
|
|
123
|
+
## Patterns that go sideways
|
|
124
|
+
|
|
125
|
+
- Trivial one-liners as skills bloat the activation list and add latency to
|
|
126
|
+
every skill search; inline instructions in the agent's prompt land cleaner
|
|
127
|
+
for small, frequent operations.
|
|
128
|
+
- Skills that duplicate built-in tool behavior (`file_read`, `web_fetch`) add
|
|
129
|
+
an indirection layer with no leverage.
|
|
130
|
+
- Hard-coded paths to specific user files break when the workspace moves or
|
|
131
|
+
gets shared; templating paths keeps the skill portable.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: workspace
|
|
3
|
+
description: Workspace maintenance — set up or tidy the `.halo/` knowledge files (INDEX.md / INSTRUCTIONS.md / memory), or package the workspace config into a shareable zip. Activate when the user asks to set up / organize / clean up the workspace knowledge base, or to share / export the workspace.
|
|
4
|
+
command: /workspace
|
|
5
|
+
verbs:
|
|
6
|
+
# builtin verbs — access is set in code (SUBCOMMAND_ROUTES); shown here for reference
|
|
7
|
+
- { name: info, builtin: true, desc: Show the current workspace }
|
|
8
|
+
- { name: switch, builtin: true, requiresAccess: full, desc: Switch workspace (absolute path) }
|
|
9
|
+
# skill verbs — access enforced from here
|
|
10
|
+
- { name: setup, requiresAccess: workspace, desc: Set up the .halo knowledge files }
|
|
11
|
+
- { name: tidy, requiresAccess: workspace, desc: Tidy/prune the .halo knowledge files }
|
|
12
|
+
- { name: share, requiresAccess: full, desc: Package the workspace config as a shareable zip }
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# workspace
|
|
16
|
+
|
|
17
|
+
Workspace maintenance. `info` / `switch` are handled directly by the `/workspace`
|
|
18
|
+
command and never reach here. This body dispatches the skill verbs — the
|
|
19
|
+
requested action is **`$1`** (full args: `$ARGUMENTS`); with natural-language
|
|
20
|
+
activation, infer it from the request.
|
|
21
|
+
|
|
22
|
+
- **`setup`** — first-time knowledge-base setup; **`tidy`** — review & prune an
|
|
23
|
+
existing one. Both follow [setup-tidy.md](setup-tidy.md) (sibling file —
|
|
24
|
+
`file_read` it; `$1` is the mode, and with no `$1` infer: no `.halo/INDEX.md`
|
|
25
|
+
yet → setup, else tidy).
|
|
26
|
+
- **`share`** — stage and zip the workspace's `.halo/` config for sharing.
|
|
27
|
+
Follow [share.md](share.md) (sibling file — `file_read` it; the `stage.py`
|
|
28
|
+
helper lives next to this SKILL.md).
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# organize-workspace
|
|
2
|
+
|
|
3
|
+
Maintains a workspace's `.halo/` knowledge files (INDEX.md, INSTRUCTIONS.md,
|
|
4
|
+
memory/). The requested mode arrives as **`$1`**:
|
|
5
|
+
|
|
6
|
+
- **`setup`** — first-time setup: interview the user, draft INDEX.md /
|
|
7
|
+
INSTRUCTIONS.md / memory entries from scratch (see Setup mode).
|
|
8
|
+
- **`tidy`** — review what's already there: prune stale entries, reshape
|
|
9
|
+
sections, surface gaps (see Tidy mode).
|
|
10
|
+
- **no `$1`** (natural-language activation) — infer: no `.halo/INDEX.md` yet
|
|
11
|
+
→ setup; otherwise tidy.
|
|
12
|
+
|
|
13
|
+
## Step 0 — Verify mode against disk
|
|
14
|
+
|
|
15
|
+
`file_read .halo/INDEX.md`. If it exists with substantive content, tidy is the
|
|
16
|
+
right mode; if missing or trivially empty, setup is. If this contradicts the
|
|
17
|
+
requested `$1` (e.g. `/workspace setup` on an already-initialized workspace), say so
|
|
18
|
+
and confirm before overwriting anything.
|
|
19
|
+
|
|
20
|
+
INSTRUCTIONS.md existing alone (without INDEX.md) still means setup — init the
|
|
21
|
+
index, leave instructions as-is unless the user asks otherwise.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Setup mode
|
|
26
|
+
|
|
27
|
+
### 1. Look before you ask
|
|
28
|
+
|
|
29
|
+
A barrage of questions up front duplicates what the README and code already
|
|
30
|
+
state. Reading the project for 1–2 minutes first lets the questions you do
|
|
31
|
+
ask focus on what's genuinely missing:
|
|
32
|
+
|
|
33
|
+
- `file_read README.md` (try variants — README, Readme, readme)
|
|
34
|
+
- `file_read package.json` / `Cargo.toml` / `pyproject.toml` / `go.mod` (identify language and stack)
|
|
35
|
+
- `file_list .` (see top-level layout)
|
|
36
|
+
- If there's a `docs/` or `.halo/docs/`, glance through it
|
|
37
|
+
|
|
38
|
+
Then tell the user what you saw: a one-sentence project summary + the stack you identified.
|
|
39
|
+
|
|
40
|
+
### 2. Ask a few targeted questions
|
|
41
|
+
|
|
42
|
+
Based on what you saw, fill in the blanks — do not ask for things the README already states. Only ask what will actually shape INSTRUCTIONS.md / INDEX.md:
|
|
43
|
+
|
|
44
|
+
- **One-line description**: if the README doesn't spell it out, ask "what is this project trying to do?"
|
|
45
|
+
- **Preferences and conventions**: any required coding style, naming conventions, test requirements, review focus?
|
|
46
|
+
- **Gotchas**: anywhere that's easy to mess up (an API that only works in a specific environment, a migration with ordering dependencies, etc.)
|
|
47
|
+
- **Docs organization**: how is `docs/` structured (see default layout below)?
|
|
48
|
+
|
|
49
|
+
2–4 questions total. A checklist of every possible field reads as homework
|
|
50
|
+
and slows the conversation; the targeted few catch what matters.
|
|
51
|
+
|
|
52
|
+
### 3. Draft INDEX.md
|
|
53
|
+
|
|
54
|
+
Skeleton:
|
|
55
|
+
|
|
56
|
+
```markdown
|
|
57
|
+
# <Project Name>
|
|
58
|
+
|
|
59
|
+
## Overview
|
|
60
|
+
|
|
61
|
+
<1–3 sentences: what this does + who it's for. Match the README's tone.>
|
|
62
|
+
|
|
63
|
+
## Tech Stack
|
|
64
|
+
|
|
65
|
+
- <main language + primary framework>
|
|
66
|
+
- <other key dependencies: DB, queue, cloud services>
|
|
67
|
+
- <build / package manager>
|
|
68
|
+
- <deployment shape: Docker / Serverless / bare metal / etc.>
|
|
69
|
+
|
|
70
|
+
## Docs Layout
|
|
71
|
+
|
|
72
|
+
<If the user doesn't have a docs/ structure yet, recommend the default below. If the project has its own structure, reflect that instead.>
|
|
73
|
+
|
|
74
|
+
- [guide/](docs/guide/) — user manual (end-user perspective)
|
|
75
|
+
- [requirements/](docs/requirements/) — product requirements (by module)
|
|
76
|
+
- [design/](docs/design/) — architecture / protocols / data flow
|
|
77
|
+
- [dev/](docs/dev/) — APIs, tools, deployment, environment
|
|
78
|
+
- [test/](docs/test/) — test cases
|
|
79
|
+
- [plans/](docs/plans/) — WIP proposals and open issues
|
|
80
|
+
|
|
81
|
+
## Memory
|
|
82
|
+
|
|
83
|
+
Important items (architecture decisions, pitfalls, non-obvious trade-offs) are logged in [memory/](memory/) by date, filename `YYYY-MM-DD-topic.md`. Not auto-injected — `file_read` on demand. Threshold for writing: things that will affect future decisions; skip trivial bug fixes.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**About the docs/ layout**: imposing the template structure on a project that
|
|
87
|
+
has its own creates friction without adding clarity. Reflecting the actual
|
|
88
|
+
structure keeps the index useful. The `memory/` section earns its spot in
|
|
89
|
+
every layout.
|
|
90
|
+
|
|
91
|
+
### 4. Draft INSTRUCTIONS.md
|
|
92
|
+
|
|
93
|
+
Skeleton:
|
|
94
|
+
|
|
95
|
+
```markdown
|
|
96
|
+
# <Project Name>
|
|
97
|
+
|
|
98
|
+
<One-line project summary. OK to duplicate INDEX.md.>
|
|
99
|
+
|
|
100
|
+
## Coding Conventions
|
|
101
|
+
|
|
102
|
+
<Distilled from the user's answers, or inferred from existing code. Generic conventions duplicate what every agent already knows; project-specific notes are the only leverage point — only write what's specific to this project>
|
|
103
|
+
- <e.g. TS strict, camelCase, log format [Module] msg>
|
|
104
|
+
- <e.g. React function components + Tailwind + shadcn/ui>
|
|
105
|
+
|
|
106
|
+
## Coding Principles
|
|
107
|
+
|
|
108
|
+
<If the user mentioned any. Skip this section if not.>
|
|
109
|
+
|
|
110
|
+
## Important Notes
|
|
111
|
+
|
|
112
|
+
<Distilled from the user's answers. Things like "persistence operations can't rely on in-memory state", "changing API signatures requires checking all callers". The pitfalls they've hit are the most valuable content here>
|
|
113
|
+
|
|
114
|
+
## Collaboration Style
|
|
115
|
+
|
|
116
|
+
<How the agent should work with them: when to push back, when to ask proactively, when to just do it>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Generic advice ("write elegant code", "add tests") duplicates what's already
|
|
120
|
+
in the agent's base instructions. INSTRUCTIONS.md earns attention with
|
|
121
|
+
constraints **specific to this project only**.
|
|
122
|
+
|
|
123
|
+
**Sub-directory INSTRUCTIONS (optional).** A sub-tree can carry its own
|
|
124
|
+
`<subdir>/.halo/INSTRUCTIONS.md` for rules that apply only to work *inside* it.
|
|
125
|
+
When a sub-agent is spawned with `working_dir` pointing there, the
|
|
126
|
+
directory-chain files (outer → inner) ride in its system prompt every turn,
|
|
127
|
+
layered **after** the root/global instructions — additive, never a replacement,
|
|
128
|
+
so the order reads general → specific. Only suggest this when a sub-tree
|
|
129
|
+
genuinely has its own conventions (e.g. a `packages/foo/` on a different stack);
|
|
130
|
+
for a single-convention project the root file alone is enough.
|
|
131
|
+
|
|
132
|
+
### 5. Show drafts, then decide whether to write
|
|
133
|
+
|
|
134
|
+
Showing both drafts **in the message** before any `file_write` lets the user
|
|
135
|
+
revise without disk churn. Typical feedback:
|
|
136
|
+
|
|
137
|
+
- "this section is wrong, change it to X" → revise
|
|
138
|
+
- "good enough, write it" → `file_write` to `.halo/INDEX.md` and `.halo/INSTRUCTIONS.md`
|
|
139
|
+
- "I'll edit it myself" → keep iterating on the draft in chat; the user wants the file under their own hand at write time
|
|
140
|
+
|
|
141
|
+
### 6. Seed memory/ (optional)
|
|
142
|
+
|
|
143
|
+
If the interview surfaced any "legacy gotchas" or "key decisions", offer to store them as individual memory entries:
|
|
144
|
+
|
|
145
|
+
```markdown
|
|
146
|
+
# <topic>
|
|
147
|
+
|
|
148
|
+
## Background
|
|
149
|
+
<the situation at the time>
|
|
150
|
+
|
|
151
|
+
## Decision
|
|
152
|
+
<what approach was chosen>
|
|
153
|
+
|
|
154
|
+
## Why Not the Alternatives
|
|
155
|
+
<other options and why they were dropped>
|
|
156
|
+
|
|
157
|
+
## Pitfalls
|
|
158
|
+
<conditions under which this decision bites back>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Filename `YYYY-MM-DD-<topic-slug>.md` (e.g. `2026-04-28-session-id-format.md`). One to three entries is plenty — no need for a full audit on day one.
|
|
162
|
+
|
|
163
|
+
### 7. Wrap up
|
|
164
|
+
|
|
165
|
+
Tell the user:
|
|
166
|
+
|
|
167
|
+
- These files auto-inject into new sessions (INSTRUCTIONS.md and INDEX.md), effective on the next conversation
|
|
168
|
+
- memory/ is read on demand — you (the agent) will `file_read` relevant entries when needed
|
|
169
|
+
- Future requests like "record this decision" / "update the INDEX" / "tidy this up" just need a plain-language ask
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Tidy mode
|
|
174
|
+
|
|
175
|
+
The workspace already has an INDEX.md. Restarting from scratch would
|
|
176
|
+
discard the user's prior organization decisions; review mode preserves
|
|
177
|
+
that intent — surface what's drifted, let the user steer the cleanup.
|
|
178
|
+
|
|
179
|
+
### 1. Take stock
|
|
180
|
+
|
|
181
|
+
Read in this order:
|
|
182
|
+
|
|
183
|
+
- `file_read .halo/INDEX.md`
|
|
184
|
+
- `file_read .halo/INSTRUCTIONS.md` (if it exists)
|
|
185
|
+
- `file_list .halo/memory` (if it exists; just file names + size, not contents)
|
|
186
|
+
- `file_list .halo/docs` (if it exists; one level deep)
|
|
187
|
+
|
|
188
|
+
Skim the INDEX. For every `[text](docs/...)` link that points into the workspace, sanity-check it's still there (`file_read` of the target — or `file_list` of the parent dir if the link is to a directory). Note the broken or empty ones.
|
|
189
|
+
|
|
190
|
+
### 2. Spot the drift
|
|
191
|
+
|
|
192
|
+
Common things to surface:
|
|
193
|
+
|
|
194
|
+
- **Broken links**: INDEX entries pointing to docs that no longer exist or are now empty.
|
|
195
|
+
- **Stale memory/**: entries older than ~3 months whose topic is no longer relevant (a decision that's been superseded, a pitfall that was fixed). Auto-detecting staleness over-reaches — the dates and titles are evidence, but the call belongs to the user.
|
|
196
|
+
- **Missing index entries**: docs that exist on disk but aren't linked from INDEX.md. List them and ask whether they belong.
|
|
197
|
+
- **Section bloat**: an INSTRUCTIONS.md section that's grown into a wall of mixed-priority bullets. Suggest splitting or distilling.
|
|
198
|
+
- **Conflicting rules**: two bullets in INSTRUCTIONS.md that pull in opposite directions (e.g. "always run tests" + a later "skip tests for one-line fixes").
|
|
199
|
+
- **Generic fluff** in INSTRUCTIONS.md ("write elegant code", "follow best practices") — gently flag, ask if the user wants it gone.
|
|
200
|
+
|
|
201
|
+
### 3. Report a punch list, then ask what to tackle
|
|
202
|
+
|
|
203
|
+
A full-rewrite proposal feels like more work to the user than they
|
|
204
|
+
signed up for. A structured punch list lets them pick what's worth
|
|
205
|
+
tackling:
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
INDEX.md:
|
|
209
|
+
• 2 broken links (docs/old-protocol.md, docs/dev/foo.md → both deleted)
|
|
210
|
+
• 4 docs on disk not in the index (docs/dev/api.md, docs/design/auth.md, …)
|
|
211
|
+
• Section "Memory" still references the format from a year ago
|
|
212
|
+
|
|
213
|
+
INSTRUCTIONS.md:
|
|
214
|
+
• "Coding Principles" section grown to 18 bullets — candidate for distillation
|
|
215
|
+
• Conflicting rules: "always run tests" (line 23) vs "skip tests for trivial edits" (line 41)
|
|
216
|
+
|
|
217
|
+
memory/:
|
|
218
|
+
• 7 entries older than 3 months — anything obsolete?
|
|
219
|
+
• 2025-12-01-bedrock-streaming.md and 2026-04-28-session-id-format.md cover overlapping ground
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Then ask: *"What do you want to tackle? (any subset, or all of it)"*. Wait for the user to pick. They might say "fix the broken links and ignore the rest" — that's fine, do exactly that.
|
|
223
|
+
|
|
224
|
+
### 4. Apply the changes the user picked
|
|
225
|
+
|
|
226
|
+
For each chosen item:
|
|
227
|
+
|
|
228
|
+
- **Broken / missing INDEX entries** — `file_edit` INDEX.md, removing dead links and adding the missing ones (after asking which section they belong in).
|
|
229
|
+
- **Distill an INSTRUCTIONS section** — propose the rewrite in the chat first; auto-writing locks in misalignment before the user can catch it. Apply on confirmation.
|
|
230
|
+
- **Stale memory/** — for each candidate, show date + title + first paragraph; let the user say keep / archive / delete. Archive = move into `.halo/memory/archive/` (create the dir if needed). Delete = `shell_exec rm`.
|
|
231
|
+
- **Merge overlapping memory entries** — read both, propose a merged version with the older filename retired into archive.
|
|
232
|
+
|
|
233
|
+
### 5. Stay in review mode
|
|
234
|
+
|
|
235
|
+
When the user's ask is "tidy this up", rewriting INDEX.md from the README
|
|
236
|
+
or restaging the docs/ structure is init-mode work — it overwrites their
|
|
237
|
+
existing organization. The review-and-prune lane respects what they
|
|
238
|
+
already built. A full rewrite happens only when they explicitly ask for
|
|
239
|
+
one.
|
|
240
|
+
|
|
241
|
+
### 6. Wrap up
|
|
242
|
+
|
|
243
|
+
Summarize what changed (files edited, memory archived/deleted) and remind them:
|
|
244
|
+
|
|
245
|
+
- INDEX.md / INSTRUCTIONS.md changes are effective on the next conversation
|
|
246
|
+
- Archived memory/ entries are still searchable via `file_read`, just not surfaced by default
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Patterns that go sideways (both modes)
|
|
251
|
+
|
|
252
|
+
- Asking the user about facts already in the README — duplicates content
|
|
253
|
+
they expect you to read.
|
|
254
|
+
- Generic template fluff ("write good comments", "use TDD") — every agent
|
|
255
|
+
already knows it; project-specific notes are the only leverage point.
|
|
256
|
+
- `file_write` on INDEX.md / INSTRUCTIONS.md while drafts are still in flux
|
|
257
|
+
— locks in misalignment that's cheap to fix in chat but expensive to fix
|
|
258
|
+
on disk.
|
|
259
|
+
- Triggering this flow during casual browsing (user poking around /tmp or
|
|
260
|
+
someone else's repo) — they're not in setup mode, so the skill drives
|
|
261
|
+
past their actual ask.
|
|
262
|
+
- Auto-deletion of memory/ entries — erases context the user may need
|
|
263
|
+
later; confirming preserves the recovery option.
|
|
264
|
+
- Organize mode rewriting things outside the user's ask — turns a
|
|
265
|
+
pruning task into a review of unrelated changes.
|