alp-code 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +770 -0
- package/LICENSE +21 -0
- package/README.md +295 -0
- package/alp.config.yaml +5 -0
- package/dist/src/agents/agent-definition.js +28 -0
- package/dist/src/agents/capability-catalog.js +33 -0
- package/dist/src/agents/compaction.js +36 -0
- package/dist/src/agents/errors.js +12 -0
- package/dist/src/agents/librarian.js +38 -0
- package/dist/src/agents/main.js +37 -0
- package/dist/src/agents/memory-grant.js +29 -0
- package/dist/src/agents/model-context.js +70 -0
- package/dist/src/agents/modes.js +134 -0
- package/dist/src/agents/oracle.js +36 -0
- package/dist/src/agents/read-thread.js +38 -0
- package/dist/src/agents/registry.js +238 -0
- package/dist/src/agents/render-identity.js +38 -0
- package/dist/src/agents/review.js +37 -0
- package/dist/src/agents/search.js +37 -0
- package/dist/src/agents/shared/house-rules.js +33 -0
- package/dist/src/agents/shared/principal.js +18 -0
- package/dist/src/agents/shared/voice.js +29 -0
- package/dist/src/agents/titling.js +32 -0
- package/dist/src/agents/types.js +15 -0
- package/dist/src/backend/execution-backend.js +2 -0
- package/dist/src/backend/local-execution-store.js +144 -0
- package/dist/src/backend/local-process-backend.js +533 -0
- package/dist/src/backend/local-supervisor.js +104 -0
- package/dist/src/cli/alp.js +380 -0
- package/dist/src/cli/commands/context.js +203 -0
- package/dist/src/cli/commands/delegate.js +136 -0
- package/dist/src/cli/commands/identity-sync.js +31 -0
- package/dist/src/cli/commands/init.js +184 -0
- package/dist/src/cli/commands/mode.js +22 -0
- package/dist/src/cli/commands/principal.js +114 -0
- package/dist/src/cli/commands/run-main.js +90 -0
- package/dist/src/cli/commands/runtime.js +21 -0
- package/dist/src/cli/mode-preference-store.js +62 -0
- package/dist/src/cli/mode-selector.js +178 -0
- package/dist/src/cli/update-check.js +77 -0
- package/dist/src/context/checkpoint.js +134 -0
- package/dist/src/context/compact-journal.js +153 -0
- package/dist/src/context/compact-payload.js +121 -0
- package/dist/src/context/continuity.js +70 -0
- package/dist/src/context/types.js +2 -0
- package/dist/src/delegation/backend-registry.js +40 -0
- package/dist/src/delegation/delegation-service.js +300 -0
- package/dist/src/delegation/types.js +12 -0
- package/dist/src/execution/execution-policy.js +96 -0
- package/dist/src/execution/execution-service.js +115 -0
- package/dist/src/execution/execution-store.js +78 -0
- package/dist/src/execution/identity-capsule.js +65 -0
- package/dist/src/execution/types.js +12 -0
- package/dist/src/hooks/execution-bridge.js +84 -0
- package/dist/src/index.js +4 -0
- package/dist/src/memory/adapters/markdown-file-store.js +257 -0
- package/dist/src/memory/adapters/memory-api-client.js +2 -0
- package/dist/src/memory/adapters/memory-path-mapper.js +76 -0
- package/dist/src/memory/adapters/remote-api-store.js +25 -0
- package/dist/src/memory/context-ranker.js +21 -0
- package/dist/src/memory/errors.js +58 -0
- package/dist/src/memory/memory-service.js +149 -0
- package/dist/src/memory/memory-store.js +2 -0
- package/dist/src/memory/types.js +2 -0
- package/dist/src/policy/capability-policy.js +29 -0
- package/dist/src/policy/delegation-policy.js +25 -0
- package/dist/src/policy/errors.js +10 -0
- package/dist/src/policy/invariants.js +31 -0
- package/dist/src/policy/memory-policy.js +22 -0
- package/dist/src/policy/policy-engine.js +85 -0
- package/dist/src/policy/types.js +8 -0
- package/dist/src/policy/workspace-policy.js +77 -0
- package/dist/src/principal/principal-profile-store.js +89 -0
- package/dist/src/runtime/adapter-files.js +147 -0
- package/dist/src/runtime/claude-adapter.js +177 -0
- package/dist/src/runtime/codex-adapter.js +169 -0
- package/dist/src/runtime/permission-rules.js +156 -0
- package/dist/src/runtime/render-session-context.js +124 -0
- package/dist/src/runtime/render-task-input.js +33 -0
- package/dist/src/runtime/runtime-adapter.js +2 -0
- package/dist/src/runtime/runtime-preference-store.js +66 -0
- package/dist/src/runtime/runtime-selector.js +178 -0
- package/dist/src/runtime/types.js +2 -0
- package/dist/src/runtime/windows-shim.js +57 -0
- package/dist/src/state-paths.js +49 -0
- package/dist/src/workflow/output-validator.js +27 -0
- package/dist/src/workflow/repair-policy.js +8 -0
- package/dist/src/workflow/types.js +22 -0
- package/dist/src/workflow/workflow-runner.js +81 -0
- package/hooks/compact-record.cjs +109 -0
- package/hooks/session-boot.cjs +112 -0
- package/hooks/session-end.cjs +34 -0
- package/package.json +48 -0
- package/scaffold/memory/INDEX.md +27 -0
- package/scaffold/memory/README.md +76 -0
- package/scaffold/memory/projects/INDEX.md +22 -0
- package/scaffold/memory/projects/PROTOCOL.md +128 -0
- package/scaffold/memory/projects/_template/PROJECT.md +45 -0
- package/scripts/alp.cjs +126 -0
- package/scripts/alp.ps1 +4 -0
- package/scripts/alp.sh +3 -0
- package/scripts/bootstrap.cjs +144 -0
- package/scripts/checkout-release.cjs +30 -0
- package/scripts/delegate.cjs +19 -0
- package/scripts/doctor.cjs +158 -0
- package/scripts/doctor.sh +3 -0
- package/scripts/ensure-state.cjs +22 -0
- package/scripts/lib/cli-link.cjs +375 -0
- package/scripts/lib/codex-role.cjs +18 -0
- package/scripts/lib/delegation/command-runner.cjs +108 -0
- package/scripts/lib/delegation/config.cjs +81 -0
- package/scripts/lib/install-paths.cjs +154 -0
- package/scripts/lib/release-manifest.cjs +42 -0
- package/scripts/lib/semver-lite.cjs +20 -0
- package/scripts/lib/state.cjs +274 -0
- package/scripts/lib/uninstall.cjs +252 -0
- package/scripts/lib/update-check-worker.cjs +21 -0
- package/scripts/lib/update.cjs +395 -0
- package/scripts/run-role.cjs +42 -0
- package/scripts/run-role.ps1 +4 -0
- package/scripts/run-role.sh +3 -0
- package/scripts/sync-project-index.sh +167 -0
- package/skills/agent-memory/SKILL.md +109 -0
- package/skills/alp-debug/SKILL.md +90 -0
- package/skills/alp-debug/references/defense-in-depth.md +118 -0
- package/skills/alp-debug/references/investigation-methodology.md +106 -0
- package/skills/alp-debug/references/log-and-ci-analysis.md +96 -0
- package/skills/alp-debug/references/performance-diagnostics.md +112 -0
- package/skills/alp-debug/references/reporting-standards.md +120 -0
- package/skills/alp-debug/references/root-cause-tracing.md +134 -0
- package/skills/alp-debug/references/systematic-debugging.md +93 -0
- package/skills/alp-debug/references/verification.md +86 -0
- package/skills/alp-debug/scripts/find-polluter.sh +63 -0
- package/skills/alp-debug/scripts/find-polluter.test.md +102 -0
- package/skills/alp-plan/SKILL.md +128 -0
- package/skills/alp-plan/references/archive-workflow.md +77 -0
- package/skills/alp-plan/references/codebase-understanding.md +55 -0
- package/skills/alp-plan/references/output-standards.md +96 -0
- package/skills/alp-plan/references/plan-organization.md +129 -0
- package/skills/alp-plan/references/red-team-personas.md +76 -0
- package/skills/alp-plan/references/red-team-workflow.md +81 -0
- package/skills/alp-plan/references/research-phase.md +57 -0
- package/skills/alp-plan/references/scope-challenge.md +82 -0
- package/skills/alp-plan/references/solution-design.md +76 -0
- package/skills/alp-plan/references/validate-question-framework.md +89 -0
- package/skills/alp-plan/references/validate-workflow.md +83 -0
- package/skills/alp-predict/SKILL.md +98 -0
- package/skills/alp-scenario/SKILL.md +86 -0
- package/skills/code-review/SKILL.md +111 -0
- package/skills/code-review/references/code-review-reception.md +114 -0
- package/skills/code-review/references/edge-case-scouting.md +78 -0
- package/skills/code-review/references/verification-before-completion.md +117 -0
- package/skills/delegation/SKILL.md +46 -0
- package/skills/docs-seeker/.env.example +15 -0
- package/skills/docs-seeker/SKILL.md +87 -0
- package/skills/docs-seeker/package.json +25 -0
- package/skills/docs-seeker/references/advanced.md +82 -0
- package/skills/docs-seeker/references/context7-patterns.md +68 -0
- package/skills/docs-seeker/references/errors.md +72 -0
- package/skills/docs-seeker/scripts/analyze-llms-txt.js +211 -0
- package/skills/docs-seeker/scripts/detect-topic.js +172 -0
- package/skills/docs-seeker/scripts/fetch-docs.js +213 -0
- package/skills/docs-seeker/scripts/tests/run-tests.js +72 -0
- package/skills/docs-seeker/scripts/tests/test-analyze-llms.js +119 -0
- package/skills/docs-seeker/scripts/tests/test-detect-topic.js +112 -0
- package/skills/docs-seeker/scripts/tests/test-fetch-docs.js +84 -0
- package/skills/docs-seeker/scripts/utils/env-loader.js +94 -0
- package/skills/docs-seeker/workflows/library-search.md +73 -0
- package/skills/docs-seeker/workflows/repo-analysis.md +90 -0
- package/skills/docs-seeker/workflows/topic-search.md +69 -0
- package/skills/git/SKILL.md +121 -0
- package/skills/git/references/branch-management.md +90 -0
- package/skills/git/references/commit-standards.md +82 -0
- package/skills/git/references/gh-cli-guide.md +132 -0
- package/skills/git/references/safety-protocols.md +86 -0
- package/skills/git/references/workflow-commit.md +89 -0
- package/skills/git/references/workflow-merge.md +63 -0
- package/skills/git/references/workflow-pr.md +70 -0
- package/skills/git/references/workflow-push.md +62 -0
- package/skills/gkg/SKILL.md +87 -0
- package/skills/gkg/references/cli-commands.md +92 -0
- package/skills/gkg/references/http-api.md +99 -0
- package/skills/gkg/references/language-support.md +54 -0
- package/skills/problem-solving/SKILL.md +86 -0
- package/skills/problem-solving/references/attribution.md +48 -0
- package/skills/problem-solving/references/collision-zone-thinking.md +71 -0
- package/skills/problem-solving/references/inversion-exercise.md +88 -0
- package/skills/problem-solving/references/meta-pattern-recognition.md +80 -0
- package/skills/problem-solving/references/scale-game.md +82 -0
- package/skills/problem-solving/references/simplification-cascades.md +83 -0
- package/skills/problem-solving/references/when-stuck.md +76 -0
- package/skills/repomix/SKILL.md +94 -0
- package/skills/repomix/references/configuration.md +134 -0
- package/skills/repomix/references/usage-patterns.md +106 -0
- package/skills/repomix/scripts/.coverage +0 -0
- package/skills/repomix/scripts/README.md +179 -0
- package/skills/repomix/scripts/repomix_batch.py +455 -0
- package/skills/repomix/scripts/repos.example.json +15 -0
- package/skills/repomix/scripts/requirements.txt +15 -0
- package/skills/repomix/scripts/tests/test_repomix_batch.py +531 -0
- package/skills/research/SKILL.md +107 -0
- package/skills/security-scan/SKILL.md +101 -0
- package/skills/security-scan/references/secret-patterns.md +75 -0
- package/skills/security-scan/references/vulnerability-patterns.md +136 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MODE_PROFILES = exports.DEFAULT_MODE = exports.MODE_IDS = void 0;
|
|
4
|
+
exports.homeRuntimeForMode = homeRuntimeForMode;
|
|
5
|
+
exports.modelForMode = modelForMode;
|
|
6
|
+
exports.reasoningEffortForMode = reasoningEffortForMode;
|
|
7
|
+
exports.runtimeForMode = runtimeForMode;
|
|
8
|
+
exports.isModeId = isModeId;
|
|
9
|
+
exports.parseMode = parseMode;
|
|
10
|
+
const model_context_1 = require("./model-context");
|
|
11
|
+
/**
|
|
12
|
+
* Dial công suất — `low` · `medium` · `high` · `ultra`, cộng `puck`.
|
|
13
|
+
*
|
|
14
|
+
* Ý tưởng mượn từ Amp: người dùng không nên phải nhớ model nào giỏi việc gì, câu hỏi duy
|
|
15
|
+
* nhất còn lại là **"việc này khó cỡ nào"**. Nấc trả lời câu đó bằng một **loadout hoàn
|
|
16
|
+
* chỉnh**: mỗi vai đúng **một** model và một mức suy nghĩ.
|
|
17
|
+
*
|
|
18
|
+
* Một model cho mỗi vai kéo theo một hệ quả lớn: **model quyết định runtime**. `claude-*`
|
|
19
|
+
* phóng Claude Code, `gpt-*` phóng Codex CLI (`MODEL_RUNTIMES`). Không còn bước "chọn
|
|
20
|
+
* runtime rồi tra model" — nấc là lựa chọn duy nhất, và một nấc có thể trộn hai CLI trong
|
|
21
|
+
* cùng một phiên, đúng như Amp trộn. `oracle` luôn đứng ở runtime **đối diện** `main` — người
|
|
22
|
+
* được hỏi khi bí phải là một cách nhìn khác, không phải cùng model tự hỏi lại chính nó
|
|
23
|
+
* (vd `medium`: main Sol/Codex, oracle Opus 5/Claude).
|
|
24
|
+
*
|
|
25
|
+
* Bốn nấc dial chỉ xoay hai ghế mà độ khó chạm tới — `main` (người làm) và `oracle` (người
|
|
26
|
+
* được hỏi khi bí). Sáu vai còn lại giữ nguyên qua cả bốn nấc, đúng chỗ Amp ghim cứng
|
|
27
|
+
* subagent: model của chúng là **một phần công việc** chứ không phải một mức cố gắng —
|
|
28
|
+
* `search` cần retrieval nhanh dù câu hỏi to hay nhỏ, `titling` viết một dòng.
|
|
29
|
+
*
|
|
30
|
+
* `puck` nằm ngoài trục độ khó: nó là câu trả lời cho "chạy toàn Codex", cho máy chỉ cài
|
|
31
|
+
* `codex`, cho lúc hạn mức Claude đã hết, hoặc cho người muốn đúng loadout Amp mặc định.
|
|
32
|
+
*/
|
|
33
|
+
exports.MODE_IDS = ["low", "medium", "high", "ultra", "puck"];
|
|
34
|
+
/**
|
|
35
|
+
* Nấc mặc định khi không ai nói gì — cùng lựa chọn của Amp. `medium` đủ cho phần lớn việc
|
|
36
|
+
* thường ngày; hai nấc trên dành cho việc mà một câu trả lời sai tốn nhiều hơn phần chênh.
|
|
37
|
+
*/
|
|
38
|
+
exports.DEFAULT_MODE = "medium";
|
|
39
|
+
/**
|
|
40
|
+
* Sáu vai không nằm trên trục độ khó, giống nhau ở cả bốn nấc dial.
|
|
41
|
+
*
|
|
42
|
+
* `search` và `librarian` lấy thẳng lựa chọn của Amp (Terra cho search, Sol cho librarian):
|
|
43
|
+
* đó là hai việc retrieval thuần, nơi nhanh và rẻ ăn đứt sâu sắc. Bốn vai còn lại ở phía
|
|
44
|
+
* Claude, giữ đúng loadout ALP đang chạy trước khi có dial.
|
|
45
|
+
*/
|
|
46
|
+
const FIXED_ROLES = Object.freeze({
|
|
47
|
+
search: { model: "gpt-5.6-terra", reasoningEffort: "low" },
|
|
48
|
+
librarian: { model: "gpt-5.6-sol", reasoningEffort: "high" },
|
|
49
|
+
"read-thread": { model: "claude-haiku-4-5", reasoningEffort: "low" },
|
|
50
|
+
review: { model: "claude-opus-5", reasoningEffort: "high" },
|
|
51
|
+
compaction: { model: "claude-opus-5", reasoningEffort: "medium" },
|
|
52
|
+
titling: { model: "claude-haiku-4-5", reasoningEffort: "low" },
|
|
53
|
+
});
|
|
54
|
+
exports.MODE_PROFILES = Object.freeze({
|
|
55
|
+
low: {
|
|
56
|
+
summary: "việc vặt, câu trả lời nhanh — rẻ và đủ",
|
|
57
|
+
roles: {
|
|
58
|
+
...FIXED_ROLES,
|
|
59
|
+
main: { model: "claude-sonnet-5", reasoningEffort: "high" },
|
|
60
|
+
oracle: { model: "gpt-5.6-sol", reasoningEffort: "high" },
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
medium: {
|
|
64
|
+
summary: "mặc định — việc thường ngày, sửa và đọc code trong một repo quen",
|
|
65
|
+
roles: {
|
|
66
|
+
...FIXED_ROLES,
|
|
67
|
+
main: { model: "gpt-5.6-sol", reasoningEffort: "high" },
|
|
68
|
+
oracle: { model: "claude-opus-5", reasoningEffort: "high" },
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
high: {
|
|
72
|
+
summary: "việc khó — refactor xuyên module, bug không tái hiện được ngay",
|
|
73
|
+
roles: {
|
|
74
|
+
...FIXED_ROLES,
|
|
75
|
+
main: { model: "claude-opus-5", reasoningEffort: "high" },
|
|
76
|
+
oracle: { model: "gpt-5.6-sol", reasoningEffort: "xhigh" },
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
ultra: {
|
|
80
|
+
summary: "việc mà trả lời sai tốn hơn phần chênh — thiết kế, migration, sự cố",
|
|
81
|
+
roles: {
|
|
82
|
+
...FIXED_ROLES,
|
|
83
|
+
main: { model: "claude-opus-5", reasoningEffort: "high" },
|
|
84
|
+
oracle: { model: "gpt-6-astra", reasoningEffort: "high" },
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
puck: {
|
|
88
|
+
summary: "toàn Codex — máy chỉ có `codex`, hết hạn mức Claude, hoặc muốn đúng loadout Amp",
|
|
89
|
+
roles: {
|
|
90
|
+
main: { model: "gpt-5.6-sol", reasoningEffort: "xhigh" },
|
|
91
|
+
oracle: { model: "gpt-5.6-sol", reasoningEffort: "xhigh" },
|
|
92
|
+
search: { model: "gpt-5.6-terra", reasoningEffort: "low" },
|
|
93
|
+
librarian: { model: "gpt-5.6-sol", reasoningEffort: "high" },
|
|
94
|
+
"read-thread": { model: "gpt-5.6-luna", reasoningEffort: "low" },
|
|
95
|
+
review: { model: "gpt-5.6-terra", reasoningEffort: "medium" },
|
|
96
|
+
compaction: { model: "gpt-5.6-sol", reasoningEffort: "medium" },
|
|
97
|
+
titling: { model: "gpt-5.6-luna", reasoningEffort: "low" },
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
/**
|
|
102
|
+
* Runtime "nhà" của một nấc — runtime của ghế `main`.
|
|
103
|
+
*
|
|
104
|
+
* Chỉ dùng làm chỗ dựa cho vai **không** có trong loadout (custom agent mai này): nó vẫn
|
|
105
|
+
* khai `model: {claude, codex}`, và phía được chọn là phía mà nấc đang đứng. Tám vai
|
|
106
|
+
* built-in đều có mặt trong mọi nấc nên không bao giờ đi qua nhánh này.
|
|
107
|
+
*/
|
|
108
|
+
function homeRuntimeForMode(mode) {
|
|
109
|
+
return (0, model_context_1.runtimeForModel)(exports.MODE_PROFILES[mode].roles.main.model);
|
|
110
|
+
}
|
|
111
|
+
function modelForMode(definition, mode) {
|
|
112
|
+
const profile = exports.MODE_PROFILES[mode].roles[definition.id];
|
|
113
|
+
return profile?.model ?? definition.model[homeRuntimeForMode(mode)];
|
|
114
|
+
}
|
|
115
|
+
function reasoningEffortForMode(definition, mode) {
|
|
116
|
+
const profile = exports.MODE_PROFILES[mode].roles[definition.id];
|
|
117
|
+
return profile?.reasoningEffort ?? definition.reasoningEffort[homeRuntimeForMode(mode)];
|
|
118
|
+
}
|
|
119
|
+
/** CLI nào phóng vai này ở nấc này — suy từ model, vì model mới là thứ được chạy. */
|
|
120
|
+
function runtimeForMode(definition, mode) {
|
|
121
|
+
return (0, model_context_1.runtimeForModel)(modelForMode(definition, mode));
|
|
122
|
+
}
|
|
123
|
+
function isModeId(value) {
|
|
124
|
+
return typeof value === "string" && exports.MODE_IDS.includes(value);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Fail-closed: một nấc gõ sai (`--mode smart`, `ALP_MODE=deep`) không được lặng lẽ rơi về
|
|
128
|
+
* mặc định, vì lúc đó người dùng tin mình đang chạy nấc khác với nấc thật sự chạy.
|
|
129
|
+
*/
|
|
130
|
+
function parseMode(value) {
|
|
131
|
+
if (isModeId(value))
|
|
132
|
+
return value;
|
|
133
|
+
throw new Error(`mode must be one of ${exports.MODE_IDS.join(", ")}, received \`${String(value)}\``);
|
|
134
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.oracleAgent = void 0;
|
|
4
|
+
const agent_definition_1 = require("./agent-definition");
|
|
5
|
+
const house_rules_1 = require("./shared/house-rules");
|
|
6
|
+
const voice_1 = require("./shared/voice");
|
|
7
|
+
const types_1 = require("../workflow/types");
|
|
8
|
+
exports.oracleAgent = (0, agent_definition_1.defineAgent)({
|
|
9
|
+
id: "oracle",
|
|
10
|
+
displayName: "Oracle 🔮",
|
|
11
|
+
model: { claude: "claude-opus-5", codex: "gpt-5.6-sol" },
|
|
12
|
+
reasoningEffort: { claude: "high", codex: "xhigh" },
|
|
13
|
+
reportsTo: "main",
|
|
14
|
+
delegatesTo: [],
|
|
15
|
+
// Suy luận trên cả tập bằng chứng một lượt; nén sớm là vứt đi chính bằng chứng đó. Nên
|
|
16
|
+
// vai này cũng lấy mặc định 90% như `main`, không tự siết mình xuống thấp hơn.
|
|
17
|
+
capabilities: {
|
|
18
|
+
tools: ["Read", "Glob", "Grep", "Bash", "WebSearch", "WebFetch", "Skill"],
|
|
19
|
+
skills: ["alp-debug", "alp-predict", "alp-scenario", "problem-solving"],
|
|
20
|
+
subagents: [],
|
|
21
|
+
mcpServers: [],
|
|
22
|
+
memory: {
|
|
23
|
+
read: ["shared", "project:*", "private:oracle"],
|
|
24
|
+
write: ["private:oracle"],
|
|
25
|
+
},
|
|
26
|
+
workspace: { readRoots: ["."], writeRoots: [] },
|
|
27
|
+
},
|
|
28
|
+
instructions: () => (0, voice_1.renderInstructions)("Oracle, the senior reasoning and architecture advisor", "Provide an independent second opinion, challenge assumptions, and expose trade-offs for high-risk decisions or debugging.", [...house_rules_1.CODE_NATIVE_HOUSE_RULES, ...house_rules_1.CODE_CRAFT_RULES, "Return recommendations only; do not implement changes or present assumptions as verified facts."]),
|
|
29
|
+
workflow: (0, types_1.defineLinearWorkflow)("advise", [
|
|
30
|
+
{ id: "FRAME", allowedTools: ["Read", "Glob", "Grep"] },
|
|
31
|
+
{ id: "CHALLENGE", allowedTools: ["Read", "Glob", "Grep", "Bash", "WebSearch", "WebFetch"] },
|
|
32
|
+
{ id: "EVALUATE", allowedTools: ["Read", "Glob", "Grep", "Bash", "WebSearch", "WebFetch"] },
|
|
33
|
+
{ id: "RECOMMEND", allowedTools: [] },
|
|
34
|
+
]),
|
|
35
|
+
output: (0, voice_1.textOutput)("architecture-advice"),
|
|
36
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readThreadAgent = void 0;
|
|
4
|
+
const agent_definition_1 = require("./agent-definition");
|
|
5
|
+
const house_rules_1 = require("./shared/house-rules");
|
|
6
|
+
const voice_1 = require("./shared/voice");
|
|
7
|
+
const types_1 = require("../workflow/types");
|
|
8
|
+
exports.readThreadAgent = (0, agent_definition_1.defineAgent)({
|
|
9
|
+
id: "read-thread",
|
|
10
|
+
displayName: "Read Thread 🧵",
|
|
11
|
+
model: { claude: "claude-haiku-4-5", codex: "gpt-5.6-luna" },
|
|
12
|
+
reasoningEffort: { claude: "low", codex: "low" },
|
|
13
|
+
reportsTo: "main",
|
|
14
|
+
delegatesTo: [],
|
|
15
|
+
// Một thread là hữu hạn — đây là trần, không phải kỳ vọng. Chỉ khai được phía codex:
|
|
16
|
+
// cửa sổ của haiku-4-5 đúng bằng 200k, nên trên Claude trần này là chính bức tường, và
|
|
17
|
+
// mặc định 180k mới là con số còn chừa chỗ để nén.
|
|
18
|
+
autoCompactTokens: { codex: 200_000 },
|
|
19
|
+
capabilities: {
|
|
20
|
+
tools: ["Read", "Glob", "Grep", "Skill"],
|
|
21
|
+
skills: ["agent-memory"],
|
|
22
|
+
subagents: [],
|
|
23
|
+
mcpServers: [],
|
|
24
|
+
memory: {
|
|
25
|
+
read: ["shared", "project:*", "private:read-thread"],
|
|
26
|
+
write: ["private:read-thread"],
|
|
27
|
+
},
|
|
28
|
+
workspace: { readRoots: [], writeRoots: [] },
|
|
29
|
+
},
|
|
30
|
+
instructions: () => (0, voice_1.renderInstructions)("Read Thread, the memory retrieval specialist", "Retrieve prior facts, decisions, and logs from granted memory and preserve exact anchors and uncertainty.", [...house_rules_1.CODE_NATIVE_HOUSE_RULES, "Do not inspect source workspaces or change shared/project memory."]),
|
|
31
|
+
workflow: (0, types_1.defineLinearWorkflow)("retrieve-memory", [
|
|
32
|
+
{ id: "PARSE_QUERY", allowedTools: [] },
|
|
33
|
+
{ id: "RETRIEVE", allowedTools: ["Read", "Glob", "Grep"] },
|
|
34
|
+
{ id: "VERIFY", allowedTools: ["Read", "Glob", "Grep"] },
|
|
35
|
+
{ id: "REPORT", allowedTools: [] },
|
|
36
|
+
]),
|
|
37
|
+
output: (0, voice_1.textOutput)("memory-retrieval-result"),
|
|
38
|
+
});
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.agentRegistry = exports.AGENT_DEFINITIONS = void 0;
|
|
4
|
+
exports.createAgentRegistry = createAgentRegistry;
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const agent_definition_1 = require("./agent-definition");
|
|
7
|
+
const capability_catalog_1 = require("./capability-catalog");
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
const memory_grant_1 = require("./memory-grant");
|
|
10
|
+
const model_context_1 = require("./model-context");
|
|
11
|
+
const types_1 = require("./types");
|
|
12
|
+
const KNOWN_TOOLS = new Set(types_1.TOOL_CATALOG);
|
|
13
|
+
/** Claude's documented `autoCompactWindow` bounds; Codex publishes none, so it shares them. */
|
|
14
|
+
const AUTO_COMPACT_MIN_TOKENS = 100_000;
|
|
15
|
+
const AUTO_COMPACT_MAX_TOKENS = 1_000_000;
|
|
16
|
+
const REASONING_EFFORTS = new Set(["low", "medium", "high", "xhigh", "max", "ultra"]);
|
|
17
|
+
function assertNonEmpty(value, label, agentId) {
|
|
18
|
+
if (!value.trim()) {
|
|
19
|
+
throw new errors_1.AgentRegistryError("INVALID_AGENT", `agent \`${agentId}\` has an empty ${label}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function pathIsWithin(root, target) {
|
|
23
|
+
const relation = (0, node_path_1.relative)((0, node_path_1.resolve)(root), (0, node_path_1.resolve)(target));
|
|
24
|
+
return relation === "" || (!relation.startsWith("..") && !(0, node_path_1.isAbsolute)(relation));
|
|
25
|
+
}
|
|
26
|
+
function assertWorkspaceWriteSubset(agentId, writes, reads) {
|
|
27
|
+
for (const write of writes) {
|
|
28
|
+
if (!reads.some((read) => pathIsWithin(read, write))) {
|
|
29
|
+
throw new errors_1.AgentRegistryError("INVALID_WORKSPACE_GRANT", `agent \`${agentId}\` workspace write root \`${write}\` is not readable`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function assertMemoryWriteSubset(agentId, writes, reads) {
|
|
34
|
+
for (const write of writes) {
|
|
35
|
+
if (!reads.some((read) => (0, memory_grant_1.memoryGrantCovers)(read, write))) {
|
|
36
|
+
throw new errors_1.AgentRegistryError("INVALID_MEMORY_GRANT", `agent \`${agentId}\` memory write grant \`${write}\` is not readable`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function privateOwner(grant) {
|
|
41
|
+
return grant.startsWith("private:") ? grant.slice("private:".length) : null;
|
|
42
|
+
}
|
|
43
|
+
function assertNoDuplicates(agentId, label, names) {
|
|
44
|
+
const seen = new Set();
|
|
45
|
+
for (const name of names) {
|
|
46
|
+
if (seen.has(name)) {
|
|
47
|
+
throw new errors_1.AgentRegistryError("DUPLICATE_GRANT", `agent \`${agentId}\` names ${label} \`${name}\` twice`);
|
|
48
|
+
}
|
|
49
|
+
seen.add(name);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The three name-declared grants of §5.3, checked against the catalog the principal keeps.
|
|
54
|
+
*
|
|
55
|
+
* A name that resolves to nothing is refused rather than ignored: a definition asking for
|
|
56
|
+
* `mcpServers: ["github"]` on a machine that never trusted `github` is stating an intent
|
|
57
|
+
* the execution cannot honour, and the quiet reading of that — no server, run anyway — is
|
|
58
|
+
* how a role ends up reporting failure for a reason nobody can see.
|
|
59
|
+
*/
|
|
60
|
+
function assertCapabilityGrants(definition, catalog) {
|
|
61
|
+
const { skills, subagents, mcpServers, tools } = definition.capabilities;
|
|
62
|
+
assertNoDuplicates(definition.id, "skill", skills);
|
|
63
|
+
assertNoDuplicates(definition.id, "subagent", subagents);
|
|
64
|
+
assertNoDuplicates(definition.id, "mcp server", mcpServers);
|
|
65
|
+
const known = new Set(catalog.skills);
|
|
66
|
+
for (const skill of skills) {
|
|
67
|
+
if (!known.has(skill)) {
|
|
68
|
+
throw new errors_1.AgentRegistryError("UNKNOWN_SKILL", `agent \`${definition.id}\` has unknown skill \`${skill}\``);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (const subagent of subagents) {
|
|
72
|
+
if (!Object.hasOwn(catalog.subagents, subagent)) {
|
|
73
|
+
throw new errors_1.AgentRegistryError("UNKNOWN_SUBAGENT", `agent \`${definition.id}\` has unknown subagent \`${subagent}\``);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
for (const server of mcpServers) {
|
|
77
|
+
if (!Object.hasOwn(catalog.mcpServers, server)) {
|
|
78
|
+
throw new errors_1.AgentRegistryError("UNKNOWN_MCP_SERVER", `agent \`${definition.id}\` has unknown mcp server \`${server}\``);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// A subagent runs inside this role's own process. Handing it a tool the role does not
|
|
82
|
+
// hold would make the grant a way around the role's limits — the thing the house rule
|
|
83
|
+
// says it is not.
|
|
84
|
+
for (const subagent of subagents) {
|
|
85
|
+
for (const tool of catalog.subagents[subagent]?.tools ?? []) {
|
|
86
|
+
if (!definition.capabilities.tools.includes(tool)) {
|
|
87
|
+
throw new errors_1.AgentRegistryError("UNKNOWN_TOOL", `agent \`${definition.id}\` grants subagent \`${subagent}\` the ungranted tool \`${tool}\``);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const holdsSkillTool = tools.includes("Skill");
|
|
92
|
+
if (holdsSkillTool && skills.length === 0) {
|
|
93
|
+
throw new errors_1.AgentRegistryError("INVALID_SKILL_GRANT", `agent \`${definition.id}\` grants the \`Skill\` tool but names no skill`);
|
|
94
|
+
}
|
|
95
|
+
if (!holdsSkillTool && skills.length > 0) {
|
|
96
|
+
throw new errors_1.AgentRegistryError("INVALID_SKILL_GRANT", `agent \`${definition.id}\` names skills but has no \`Skill\` tool to invoke them`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function assertDefinitionInvariants(definition, catalog) {
|
|
100
|
+
assertNonEmpty(definition.id, "id", definition.id);
|
|
101
|
+
assertNonEmpty(definition.displayName, "displayName", definition.id);
|
|
102
|
+
if (!definition.model.claude.trim()) {
|
|
103
|
+
throw new errors_1.AgentRegistryError("INVALID_AGENT", `agent \`${definition.id}\` is missing Claude runtime model`);
|
|
104
|
+
}
|
|
105
|
+
if (!definition.model.codex.trim()) {
|
|
106
|
+
throw new errors_1.AgentRegistryError("INVALID_AGENT", `agent \`${definition.id}\` is missing Codex runtime model`);
|
|
107
|
+
}
|
|
108
|
+
for (const runtime of types_1.RUNTIME_IDS) {
|
|
109
|
+
if (!REASONING_EFFORTS.has(definition.reasoningEffort[runtime])) {
|
|
110
|
+
throw new errors_1.AgentRegistryError("INVALID_AGENT", `agent \`${definition.id}\` has invalid ${runtime} reasoning effort`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
for (const runtime of types_1.RUNTIME_IDS) {
|
|
114
|
+
const autoCompact = definition.autoCompactTokens?.[runtime];
|
|
115
|
+
if (autoCompact === undefined)
|
|
116
|
+
continue;
|
|
117
|
+
const prefix = `agent \`${definition.id}\` has ${runtime} auto-compact threshold \`${autoCompact}\``;
|
|
118
|
+
if (!Number.isInteger(autoCompact)
|
|
119
|
+
|| autoCompact < AUTO_COMPACT_MIN_TOKENS
|
|
120
|
+
|| autoCompact > AUTO_COMPACT_MAX_TOKENS) {
|
|
121
|
+
throw new errors_1.AgentRegistryError("INVALID_AUTO_COMPACT_LIMIT", `${prefix}, outside ${AUTO_COMPACT_MIN_TOKENS}–${AUTO_COMPACT_MAX_TOKENS} whole tokens`);
|
|
122
|
+
}
|
|
123
|
+
// A threshold above the model's own window is a line the transcript can never cross:
|
|
124
|
+
// the runtime falls back to its hard limit and compacts later than the role asked,
|
|
125
|
+
// while argv still prints a number that says otherwise. Refused here rather than
|
|
126
|
+
// clamped at launch — the number is wrong where it is written, not where it is read.
|
|
127
|
+
const window = model_context_1.MODEL_CONTEXT_WINDOWS[definition.model[runtime]];
|
|
128
|
+
if (window !== undefined && autoCompact > window) {
|
|
129
|
+
throw new errors_1.AgentRegistryError("INVALID_AUTO_COMPACT_LIMIT", `${prefix} above the context window of \`${definition.model[runtime]}\` (${window} tokens)`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
assertNonEmpty(definition.workflow.id, "workflow id", definition.id);
|
|
133
|
+
assertNonEmpty(definition.output.name, "output contract name", definition.id);
|
|
134
|
+
assertWorkspaceWriteSubset(definition.id, definition.capabilities.workspace.writeRoots, definition.capabilities.workspace.readRoots);
|
|
135
|
+
assertMemoryWriteSubset(definition.id, definition.capabilities.memory.write, definition.capabilities.memory.read);
|
|
136
|
+
for (const tool of definition.capabilities.tools) {
|
|
137
|
+
if (!KNOWN_TOOLS.has(tool)) {
|
|
138
|
+
throw new errors_1.AgentRegistryError("UNKNOWN_TOOL", `agent \`${definition.id}\` has unknown tool \`${tool}\``);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
assertCapabilityGrants(definition, catalog);
|
|
142
|
+
for (const grant of [
|
|
143
|
+
...definition.capabilities.memory.read,
|
|
144
|
+
...definition.capabilities.memory.write,
|
|
145
|
+
]) {
|
|
146
|
+
const owner = privateOwner(grant);
|
|
147
|
+
if (owner !== null && owner !== definition.id) {
|
|
148
|
+
throw new errors_1.AgentRegistryError("INVALID_MEMORY_GRANT", `agent \`${definition.id}\` cannot access private memory for \`${owner}\``);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function assertRelations(definitions, known) {
|
|
153
|
+
for (const definition of definitions) {
|
|
154
|
+
if (definition.reportsTo !== "principal" && !known.has(definition.reportsTo)) {
|
|
155
|
+
throw new errors_1.AgentRegistryError("UNKNOWN_RELATION", `agent \`${definition.id}\` has unknown reportsTo \`${definition.reportsTo}\``);
|
|
156
|
+
}
|
|
157
|
+
for (const target of definition.delegatesTo) {
|
|
158
|
+
if (target === definition.id) {
|
|
159
|
+
throw new errors_1.AgentRegistryError("INVALID_DELEGATION", `agent \`${definition.id}\` cannot delegate to itself`);
|
|
160
|
+
}
|
|
161
|
+
if (!known.has(target)) {
|
|
162
|
+
throw new errors_1.AgentRegistryError("UNKNOWN_RELATION", `agent \`${definition.id}\` has unknown delegation target \`${target}\``);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function assertNoDelegationCycles(definitions, byId) {
|
|
168
|
+
const state = new Map();
|
|
169
|
+
const trail = [];
|
|
170
|
+
const visit = (id) => {
|
|
171
|
+
if (state.get(id) === "visited")
|
|
172
|
+
return;
|
|
173
|
+
if (state.get(id) === "visiting") {
|
|
174
|
+
const cycleStart = trail.indexOf(id);
|
|
175
|
+
const cycle = [...trail.slice(cycleStart), id];
|
|
176
|
+
throw new errors_1.AgentRegistryError("INVALID_DELEGATION", `delegation cycle: ${cycle.join(" -> ")}`);
|
|
177
|
+
}
|
|
178
|
+
state.set(id, "visiting");
|
|
179
|
+
trail.push(id);
|
|
180
|
+
for (const target of byId.get(id)?.delegatesTo ?? [])
|
|
181
|
+
visit(target);
|
|
182
|
+
trail.pop();
|
|
183
|
+
state.set(id, "visited");
|
|
184
|
+
};
|
|
185
|
+
for (const definition of definitions)
|
|
186
|
+
visit(definition.id);
|
|
187
|
+
}
|
|
188
|
+
function createAgentRegistry(input, options = {}) {
|
|
189
|
+
const catalog = options.catalog ?? capability_catalog_1.capabilityCatalog;
|
|
190
|
+
const definitions = [];
|
|
191
|
+
const byId = new Map();
|
|
192
|
+
for (const candidate of input) {
|
|
193
|
+
const definition = (0, agent_definition_1.defineAgent)(candidate);
|
|
194
|
+
if (byId.has(definition.id)) {
|
|
195
|
+
throw new errors_1.AgentRegistryError("DUPLICATE_AGENT", `duplicate agent \`${definition.id}\``);
|
|
196
|
+
}
|
|
197
|
+
assertDefinitionInvariants(definition, catalog);
|
|
198
|
+
definitions.push(definition);
|
|
199
|
+
byId.set(definition.id, definition);
|
|
200
|
+
}
|
|
201
|
+
assertRelations(definitions, new Set(byId.keys()));
|
|
202
|
+
assertNoDelegationCycles(definitions, byId);
|
|
203
|
+
const list = Object.freeze(definitions.slice());
|
|
204
|
+
return Object.freeze({
|
|
205
|
+
get(id) {
|
|
206
|
+
const definition = byId.get(id);
|
|
207
|
+
if (!definition) {
|
|
208
|
+
throw new errors_1.AgentRegistryError("UNKNOWN_AGENT", `unknown agent \`${id}\``);
|
|
209
|
+
}
|
|
210
|
+
return definition;
|
|
211
|
+
},
|
|
212
|
+
has(id) {
|
|
213
|
+
return byId.has(id);
|
|
214
|
+
},
|
|
215
|
+
list() {
|
|
216
|
+
return list;
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
const main_1 = require("./main");
|
|
221
|
+
const search_1 = require("./search");
|
|
222
|
+
const librarian_1 = require("./librarian");
|
|
223
|
+
const read_thread_1 = require("./read-thread");
|
|
224
|
+
const review_1 = require("./review");
|
|
225
|
+
const oracle_1 = require("./oracle");
|
|
226
|
+
const compaction_1 = require("./compaction");
|
|
227
|
+
const titling_1 = require("./titling");
|
|
228
|
+
exports.AGENT_DEFINITIONS = Object.freeze([
|
|
229
|
+
main_1.mainAgent,
|
|
230
|
+
search_1.searchAgent,
|
|
231
|
+
librarian_1.librarianAgent,
|
|
232
|
+
read_thread_1.readThreadAgent,
|
|
233
|
+
review_1.reviewAgent,
|
|
234
|
+
oracle_1.oracleAgent,
|
|
235
|
+
compaction_1.compactionAgent,
|
|
236
|
+
titling_1.titlingAgent,
|
|
237
|
+
]);
|
|
238
|
+
exports.agentRegistry = createAgentRegistry(exports.AGENT_DEFINITIONS);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderIdentityDocument = renderIdentityDocument;
|
|
4
|
+
/**
|
|
5
|
+
* Renders a role's static identity as a standalone Markdown document.
|
|
6
|
+
*
|
|
7
|
+
* This is what `alp identity sync` writes to `.alp/agents/<role>.md`, and what the
|
|
8
|
+
* SessionStart hook injects on the native path — the principal ran `claude`/`codex`
|
|
9
|
+
* directly, so no adapter wrote a session context. Keeping it a flat file is the point:
|
|
10
|
+
* the hook reads it with one `readFileSync` and no `dist/` load.
|
|
11
|
+
*
|
|
12
|
+
* Only static facts belong here. A launch through `alp` gets `renderSessionContext`
|
|
13
|
+
* instead, which adds what only an execution knows: invariants, policy context, and the
|
|
14
|
+
* workspace grant. Per-task facts belong to `renderTaskInput`.
|
|
15
|
+
*/
|
|
16
|
+
function renderIdentityDocument(definition) {
|
|
17
|
+
const list = (values) => values.length === 0 ? "—" : values.join(", ");
|
|
18
|
+
return [
|
|
19
|
+
`# ${definition.displayName} — \`${definition.id}\``,
|
|
20
|
+
"",
|
|
21
|
+
definition.instructions(),
|
|
22
|
+
"",
|
|
23
|
+
"## Authority",
|
|
24
|
+
"",
|
|
25
|
+
"| | |",
|
|
26
|
+
"| --- | --- |",
|
|
27
|
+
`| Reports to | \`${definition.reportsTo}\` |`,
|
|
28
|
+
`| Delegates to | ${list(definition.delegatesTo)} |`,
|
|
29
|
+
`| Tools | ${list(definition.capabilities.tools)} |`,
|
|
30
|
+
`| Memory read | ${list(definition.capabilities.memory.read)} |`,
|
|
31
|
+
`| Memory write | ${list(definition.capabilities.memory.write)} |`,
|
|
32
|
+
`| Workspace read | ${list(definition.capabilities.workspace.readRoots)} |`,
|
|
33
|
+
`| Workspace write | ${list(definition.capabilities.workspace.writeRoots)} |`,
|
|
34
|
+
"",
|
|
35
|
+
"That table is the whole of your authority. If something you need is blocked, report it — do not route around it.",
|
|
36
|
+
"",
|
|
37
|
+
].join("\n");
|
|
38
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reviewAgent = void 0;
|
|
4
|
+
const agent_definition_1 = require("./agent-definition");
|
|
5
|
+
const house_rules_1 = require("./shared/house-rules");
|
|
6
|
+
const voice_1 = require("./shared/voice");
|
|
7
|
+
const types_1 = require("../workflow/types");
|
|
8
|
+
exports.reviewAgent = (0, agent_definition_1.defineAgent)({
|
|
9
|
+
id: "review",
|
|
10
|
+
displayName: "Review 🔎",
|
|
11
|
+
model: { claude: "claude-opus-5", codex: "gpt-5.6-terra" },
|
|
12
|
+
reasoningEffort: { claude: "high", codex: "medium" },
|
|
13
|
+
reportsTo: "main",
|
|
14
|
+
delegatesTo: [],
|
|
15
|
+
// Một diff cộng code quanh nó, và mối nghi phải sống tới lúc ra phán quyết. Phía codex
|
|
16
|
+
// bỏ trống vì mặc định 90% của 272k đã thấp hơn trần này.
|
|
17
|
+
autoCompactTokens: { claude: 300_000 },
|
|
18
|
+
capabilities: {
|
|
19
|
+
tools: ["Read", "Glob", "Grep", "Bash", "Skill"],
|
|
20
|
+
skills: ["code-review", "alp-scenario", "security-scan"],
|
|
21
|
+
subagents: [],
|
|
22
|
+
mcpServers: [],
|
|
23
|
+
memory: {
|
|
24
|
+
read: ["shared", "project:*", "private:review"],
|
|
25
|
+
write: ["private:review"],
|
|
26
|
+
},
|
|
27
|
+
workspace: { readRoots: ["."], writeRoots: [] },
|
|
28
|
+
},
|
|
29
|
+
instructions: () => (0, voice_1.renderInstructions)("Review, the code review specialist", "Review one named concern per execution and report only actionable findings backed by concrete code evidence.", [...house_rules_1.CODE_NATIVE_HOUSE_RULES, ...house_rules_1.CODE_CRAFT_RULES, "Do not edit the implementation; rank findings by impact and explain the failure mode."]),
|
|
30
|
+
workflow: (0, types_1.defineLinearWorkflow)("review-concern", [
|
|
31
|
+
{ id: "SCOPE_CONCERN", allowedTools: ["Read", "Glob", "Grep"] },
|
|
32
|
+
{ id: "INSPECT", allowedTools: ["Read", "Glob", "Grep", "Bash"] },
|
|
33
|
+
{ id: "VERIFY", allowedTools: ["Read", "Glob", "Grep", "Bash"] },
|
|
34
|
+
{ id: "REPORT", allowedTools: [] },
|
|
35
|
+
]),
|
|
36
|
+
output: (0, voice_1.textOutput)("code-review-report"),
|
|
37
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.searchAgent = void 0;
|
|
4
|
+
const agent_definition_1 = require("./agent-definition");
|
|
5
|
+
const house_rules_1 = require("./shared/house-rules");
|
|
6
|
+
const voice_1 = require("./shared/voice");
|
|
7
|
+
const types_1 = require("../workflow/types");
|
|
8
|
+
exports.searchAgent = (0, agent_definition_1.defineAgent)({
|
|
9
|
+
id: "search",
|
|
10
|
+
displayName: "Search 🔍",
|
|
11
|
+
model: { claude: "claude-sonnet-5", codex: "gpt-5.6-terra" },
|
|
12
|
+
reasoningEffort: { claude: "low", codex: "low" },
|
|
13
|
+
reportsTo: "main",
|
|
14
|
+
delegatesTo: [],
|
|
15
|
+
// Một cuộc tìm phình tới đây là đã hỏng; nén là cách hỏng rẻ hơn. Bằng nhau hai phía:
|
|
16
|
+
// trần này nói về việc tìm kiếm, không về model.
|
|
17
|
+
autoCompactTokens: { claude: 150_000, codex: 150_000 },
|
|
18
|
+
capabilities: {
|
|
19
|
+
tools: ["Read", "Glob", "Grep", "Bash", "Skill"],
|
|
20
|
+
skills: ["gkg", "repomix"],
|
|
21
|
+
subagents: [],
|
|
22
|
+
mcpServers: [],
|
|
23
|
+
memory: {
|
|
24
|
+
read: ["shared", "project:*", "private:search"],
|
|
25
|
+
write: ["private:search"],
|
|
26
|
+
},
|
|
27
|
+
workspace: { readRoots: ["."], writeRoots: [] },
|
|
28
|
+
},
|
|
29
|
+
instructions: () => (0, voice_1.renderInstructions)("Search, the local code retrieval specialist", "Locate symbols, call sites, and execution flows in the active workspace and return exact path/line evidence.", [...house_rules_1.CODE_NATIVE_HOUSE_RULES, "Do not modify source files or broaden beyond the requested retrieval question."]),
|
|
30
|
+
workflow: (0, types_1.defineLinearWorkflow)("retrieve-code", [
|
|
31
|
+
{ id: "VALIDATE_WORKSPACE", allowedTools: ["Read", "Glob"] },
|
|
32
|
+
{ id: "RETRIEVE", allowedTools: ["Read", "Glob", "Grep", "Bash"] },
|
|
33
|
+
{ id: "VERIFY", allowedTools: ["Read", "Glob", "Grep", "Bash"] },
|
|
34
|
+
{ id: "REPORT", allowedTools: [] },
|
|
35
|
+
]),
|
|
36
|
+
output: (0, voice_1.textOutput)("code-search-result"),
|
|
37
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CODE_CRAFT_RULES = exports.CODE_NATIVE_HOUSE_RULES = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Two bans, not one, because they rest on different reasons.
|
|
6
|
+
*
|
|
7
|
+
* Herdr and Paseo are foreign runtimes: whatever they launch is outside ALP policy entirely,
|
|
8
|
+
* and no grant can ever put it back inside. An in-process subagent is the opposite — it runs
|
|
9
|
+
* inside the session ALP itself started, under the workspace, sandbox and deny list this
|
|
10
|
+
* execution already carries, so it is bannable by *not being granted*, not by being what it is.
|
|
11
|
+
*
|
|
12
|
+
* These lived in one sentence ("never launch raw Herdr, Paseo, or in-process agents") until
|
|
13
|
+
* 2026-09-04. That sentence forbids the whole class, so the day a definition first declares
|
|
14
|
+
* `capabilities.subagents` the prompt would contradict the grant — vision §4.6. Splitting it
|
|
15
|
+
* before any grant exists means the rule needs no rewrite when one does: today no role is
|
|
16
|
+
* granted a subagent, and the rule already says exactly what that means.
|
|
17
|
+
*/
|
|
18
|
+
exports.CODE_NATIVE_HOUSE_RULES = Object.freeze([
|
|
19
|
+
"Use ALP policy and delegation boundaries; never launch raw Herdr or Paseo.",
|
|
20
|
+
"Launch no in-process subagent that this execution's policy does not grant — a subagent is not a way around your own limits.",
|
|
21
|
+
"Treat private memory as owner-only; hierarchy does not grant private access.",
|
|
22
|
+
"Do not commit, push, deploy, or perform destructive operations without explicit principal approval.",
|
|
23
|
+
"Return verifiable evidence and do not claim checks that were not run.",
|
|
24
|
+
]);
|
|
25
|
+
// Craft standard for roles that write or judge implementation code. Kept separate from the
|
|
26
|
+
// house rules so read-only roles (search, librarian, read-thread, compaction, titling) do
|
|
27
|
+
// not carry prompt they never act on.
|
|
28
|
+
exports.CODE_CRAFT_RULES = Object.freeze([
|
|
29
|
+
"Surface assumptions instead of acting on them; when a request has multiple readings, present them rather than silently picking one.",
|
|
30
|
+
"Prefer the smallest solution that solves the stated problem: no abstraction, option, or error path nobody asked for.",
|
|
31
|
+
"Keep changes surgical: every changed line traces to the request, surrounding style is matched, and only orphans the change itself created are removed.",
|
|
32
|
+
"Turn the task into a check that can be run, then loop until that check passes.",
|
|
33
|
+
]);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.principalInstruction = principalInstruction;
|
|
4
|
+
const principal_profile_store_1 = require("../../principal/principal-profile-store");
|
|
5
|
+
/**
|
|
6
|
+
* The one line of every role's prompt that names who is being served.
|
|
7
|
+
*
|
|
8
|
+
* The profile is read from `~/.alp/principal.json` rather than compiled in: the name and
|
|
9
|
+
* the forms of address belong to the person running the install, not to the source tree.
|
|
10
|
+
* Until `alp init` (or `alp principal set`) captures one, roles get a neutral wording —
|
|
11
|
+
* a missing profile degrades the prompt, it never blocks a session or invents a name.
|
|
12
|
+
*/
|
|
13
|
+
function principalInstruction(profile = (0, principal_profile_store_1.readPrincipalProfile)().profile) {
|
|
14
|
+
const voice = "Communicate in Vietnamese, keep technical terms in English, and lead with the verified outcome.";
|
|
15
|
+
if (profile === null)
|
|
16
|
+
return `Serve the principal. ${voice}`;
|
|
17
|
+
return `Serve ${profile.name}. Address the principal as "${profile.addressAs}" and refer to yourself as "${profile.selfAs}". ${voice}`;
|
|
18
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderInstructions = renderInstructions;
|
|
4
|
+
exports.textOutput = textOutput;
|
|
5
|
+
const principal_1 = require("./principal");
|
|
6
|
+
function renderInstructions(role, purpose, rules, options = {}) {
|
|
7
|
+
const principalFacing = (options.audience ?? "principal") === "principal";
|
|
8
|
+
return [
|
|
9
|
+
`You are ${role}. ${purpose}`,
|
|
10
|
+
...(principalFacing
|
|
11
|
+
? [
|
|
12
|
+
(0, principal_1.principalInstruction)(),
|
|
13
|
+
"State status or conclusion first. Be concise, direct, and explicit about evidence and uncertainty.",
|
|
14
|
+
]
|
|
15
|
+
: []),
|
|
16
|
+
...rules.map((rule) => `- ${rule}`),
|
|
17
|
+
].join("\n");
|
|
18
|
+
}
|
|
19
|
+
function textOutput(name) {
|
|
20
|
+
return {
|
|
21
|
+
name,
|
|
22
|
+
schema: { type: "string", minLength: 1 },
|
|
23
|
+
validate(value) {
|
|
24
|
+
return typeof value === "string" && value.trim().length > 0
|
|
25
|
+
? { ok: true, value }
|
|
26
|
+
: { ok: false, issues: ["output must be non-empty text"] };
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|