ostacky 0.7.3 → 0.8.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/README.md +29 -24
- package/assets/agents/ostacky.md +82 -525
- package/assets/commands/install-stack.md +2 -2
- package/assets/docs/engram-protocol.md +79 -0
- package/assets/docs/ostacky-reference.md +79 -0
- package/assets/mcp/ostacky-controller/index.js +698 -228
- package/assets/mcp/ostacky-controller/package.json +1 -1
- package/assets/mcp/ostacky-controller/security.js +87 -0
- package/assets/plugins/engram.ts +47 -79
- package/assets/plugins/ostacky-guard.ts +11 -124
- package/assets/plugins/ostacky-plugin.ts +646 -0
- package/assets/skills/brainstorming/SKILL.md +198 -197
- package/assets/skills/execution-mode-evaluation/SKILL.md +9 -9
- package/assets/skills/graceful-degradation/SKILL.md +251 -248
- package/dist/cli.js +432 -135
- package/manifest.json +31 -31
- package/package.json +1 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Engram Persistent Memory — Protocol (on-demand)
|
|
2
|
+
|
|
3
|
+
Este archivo NO se inyecta en el prompt. Se lee con `Read assets/docs/engram-protocol.md` cuando el agente necesita detalles de `mem_save`/`mem_search`.
|
|
4
|
+
|
|
5
|
+
> Fuente: `assets/plugins/engram.ts` `MEMORY_INSTRUCTIONS` — movido a lazy para ahorrar ~1.2k tokens en FULL.
|
|
6
|
+
|
|
7
|
+
## WHEN TO SAVE (mandatory — not optional)
|
|
8
|
+
|
|
9
|
+
Call `mem_save` IMMEDIATELY after any of these:
|
|
10
|
+
- Bug fix completed
|
|
11
|
+
- Architecture or design decision made
|
|
12
|
+
- Non-obvious discovery about the codebase
|
|
13
|
+
- Configuration change or environment setup
|
|
14
|
+
- Pattern established (naming, structure, convention)
|
|
15
|
+
- User preference or constraint learned
|
|
16
|
+
|
|
17
|
+
Format for `mem_save`:
|
|
18
|
+
- **title**: Verb + what — short, searchable (e.g. "Fixed N+1 query in UserList", "Chose Zustand over Redux")
|
|
19
|
+
- **type**: bugfix | decision | architecture | discovery | pattern | config | preference
|
|
20
|
+
- **scope**: `project` (default) | `personal`
|
|
21
|
+
- **topic_key** (optional, recommended for evolving decisions): stable key like `architecture/auth-model`
|
|
22
|
+
- **content**:
|
|
23
|
+
**What**: One sentence — what was done
|
|
24
|
+
**Why**: What motivated it (user request, bug, performance, etc.)
|
|
25
|
+
**Where**: Files or paths affected
|
|
26
|
+
**Learned**: Gotchas, edge cases, things that surprised you (omit if none)
|
|
27
|
+
|
|
28
|
+
Topic rules:
|
|
29
|
+
- Different topics must not overwrite each other (e.g. architecture vs bugfix)
|
|
30
|
+
- Reuse the same `topic_key` to update an evolving topic instead of creating new observations
|
|
31
|
+
- If unsure about the key, call `mem_suggest_topic_key` first and then reuse it
|
|
32
|
+
- Use `mem_update` when you have an exact observation ID to correct
|
|
33
|
+
|
|
34
|
+
## WHEN TO SEARCH MEMORY
|
|
35
|
+
|
|
36
|
+
When the user asks to recall something — any variation of "remember", "recall", "what did we do",
|
|
37
|
+
"how did we solve", or the equivalent in the user's language, or references to past work:
|
|
38
|
+
1. First call `mem_context` — checks recent session history (fast, cheap)
|
|
39
|
+
2. If not found, call `mem_search` with relevant keywords (FTS5 full-text search)
|
|
40
|
+
3. If you find a match, use `mem_get_observation` for full untruncated content
|
|
41
|
+
|
|
42
|
+
Also search memory PROACTIVELY when:
|
|
43
|
+
- Starting work on something that might have been done before
|
|
44
|
+
- The user mentions a topic you have no context on — check if past sessions covered it
|
|
45
|
+
- The user's FIRST message references the project, a feature, or a problem — call `mem_search` with keywords from their message to check for prior work before responding
|
|
46
|
+
|
|
47
|
+
## SESSION CLOSE PROTOCOL (mandatory)
|
|
48
|
+
|
|
49
|
+
Before ending a session or saying "done" / "that's it", you MUST:
|
|
50
|
+
1. Call `mem_session_summary` with this structure:
|
|
51
|
+
|
|
52
|
+
## Goal
|
|
53
|
+
[What we were working on this session]
|
|
54
|
+
|
|
55
|
+
## Instructions
|
|
56
|
+
[User preferences or constraints discovered — skip if none]
|
|
57
|
+
|
|
58
|
+
## Discoveries
|
|
59
|
+
- [Technical findings, gotchas, non-obvious learnings]
|
|
60
|
+
|
|
61
|
+
## Accomplished
|
|
62
|
+
- [Completed items with key details]
|
|
63
|
+
|
|
64
|
+
## Next Steps
|
|
65
|
+
- [What remains to be done — for the next session]
|
|
66
|
+
|
|
67
|
+
## Relevant Files
|
|
68
|
+
- path/to/file — [what it does or what changed]
|
|
69
|
+
|
|
70
|
+
This is NOT optional. If you skip this, the next session starts blind.
|
|
71
|
+
|
|
72
|
+
## AFTER COMPACTION
|
|
73
|
+
|
|
74
|
+
If you see a message about compaction or context reset, or if you see "FIRST ACTION REQUIRED" in your context:
|
|
75
|
+
1. IMMEDIATELY call `mem_session_summary` with the compacted summary content — this persists what was done before compaction
|
|
76
|
+
2. Then call `mem_context` to recover any additional context from previous sessions
|
|
77
|
+
3. Only THEN continue working
|
|
78
|
+
|
|
79
|
+
Do not skip step 1. Without it, everything done before compaction is lost from memory.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Ostacky Reference — Detalle no crítico para prompt
|
|
2
|
+
|
|
3
|
+
Este archivo NO se inyecta en el prompt. Se lee on-demand con `Read assets/docs/ostacky-reference.md` cuando el LLM necesita detalle exacto.
|
|
4
|
+
|
|
5
|
+
## TRANSITIONS (controller)
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
INTERPRETATION_PENDING: request_clarification→CLARIFICATION_PENDING, proceed_to_discovery→DISCOVERY, record_discovery→ROUTE_DECISION_PENDING, block→BLOCKED
|
|
9
|
+
CLARIFICATION_PENDING: record_clarification→DISCOVERY, block→BLOCKED, abandon→BLOCKED
|
|
10
|
+
DISCOVERY: record_discovery→ROUTE_DECISION_PENDING, block→BLOCKED, abandon→BLOCKED
|
|
11
|
+
ROUTE_DECISION_PENDING: consume_route_decision(SPEC→SPECIFICATION, DIRECT→EXECUTION_ANALYSIS), block→BLOCKED
|
|
12
|
+
SPECIFICATION: spec_complete→EXECUTION_ANALYSIS, block→BLOCKED
|
|
13
|
+
EXECUTION_ANALYSIS: record_execution_analysis→EXECUTION_DECISION_PENDING, block→BLOCKED
|
|
14
|
+
EXECUTION_DECISION_PENDING: consume_execution_decision(INLINE→EXECUTING_INLINE, SUBAGENT→EXECUTING_SUBAGENTS), block→BLOCKED
|
|
15
|
+
EXECUTING_INLINE/SUBAGENTS: implementation_complete→SYNC, block→BLOCKED (block preserva tasks, replan prohibido)
|
|
16
|
+
SYNC: sync_complete→DONE
|
|
17
|
+
BLOCKED: replan→INTERPRETATION_PENDING, abandon→DONE
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`proceed_to_route` deprecated → no-op alias retorna `{deprecated:true, state:"ROUTE_DECISION_PENDING"}` (compat).
|
|
21
|
+
|
|
22
|
+
## Retry / Timeouts
|
|
23
|
+
|
|
24
|
+
| Tool | Timeout | Reintentos | Fallback |
|
|
25
|
+
|------|---------|------------|----------|
|
|
26
|
+
| codegraph_* | 10s | 1 | Engram → Read+Glob |
|
|
27
|
+
| controller_* | 5s | 1 | degraded |
|
|
28
|
+
| engram_* | 5s | 1 | sin memoria |
|
|
29
|
+
| context7_* | 10s | 1 | sin docs |
|
|
30
|
+
|
|
31
|
+
## Cache
|
|
32
|
+
|
|
33
|
+
- `src/cache-codegraph.ts`: `.opencode/cache/codegraph/<sha256(query)>.json` con `{ts, result, gitHead, gitDiffHash}`, TTL 1h, `OSTACKY_CACHE_DISABLE=1` bypass, LRU 50MB, invalidación `git diff --name-only` + `git status --porcelain --untracked-files=all` (hash combinado).
|
|
34
|
+
- `src/discovery-cache.ts`: `.opencode/cache/codegraph/discovery-<sha256>.json` con `{codegraph, engramHits, gitDiffHash, gitHead, ts, query}`, mismo TTL/LRU. `getDiscoverySnapshot` → hit reusar sin llamar tools; miss → SHALL `putDiscoverySnapshot` antes de `record_discovery` (auditable `WARN:cache_miss_without_put`).
|
|
35
|
+
- `record_cache_hit/miss` internos: `cache-codegraph.ts` hace write directo a `ostacky-state.json` incrementando `cacheHitCount/tokenSavingEstimate` sin tool LLM.
|
|
36
|
+
|
|
37
|
+
## Metrics (get_metrics)
|
|
38
|
+
|
|
39
|
+
`revision, state, degraded, taskCounts{completed,pending,total,expected}, expectedTaskCount, auditSize, stateFileSize, diskFreeMB, uptimeMs, stateOversizedCount, codegraphBypassCount, degradedEditsCount, cacheHitCount, cacheMissCount, tokenSavingEstimate, sensitiveAccess, subagentFailedCount, discoveryCacheHitCount, redundantCallCount, cacheMissWithoutPutCount, stateCheckCount, toolCallCount`
|
|
40
|
+
|
|
41
|
+
## BASH_SENSITIVE_RE
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
/(?:^|[^a-zA-Z0-9_.-])(\.env(\b|[_.-])|\.secrets\b|\.pem\b|\.key\b|credentials\.json|\.aws\b|\.ssh\b|\.npmrc\b)/i
|
|
45
|
+
```
|
|
46
|
+
Allowlist: `.env.example/.template/.sample` nunca bloquea. `extractPathsFromBash` tokeniza `| ; && || > >> <`.
|
|
47
|
+
|
|
48
|
+
## validate_edit contrato
|
|
49
|
+
|
|
50
|
+
`content` requerido salvo `content:"hash:"+fastFingerprint` cuando `lastValidated.filePath==filePath && fingerprint==hash` y fingerprint coincide con disco → EDITABLE sin body. Hash stale → CONFLICT `stale fingerprint`.
|
|
51
|
+
|
|
52
|
+
## Enforcement (plugin)
|
|
53
|
+
|
|
54
|
+
El plugin hace cumplir `PENDING` en `tool.execute.before`; `lastCheck={revision, result}` cachea ALLOW por revisión, revalida si cambia o >5 tools; `BLOCKED` nunca cacheado. Métricas `stateCheckCount` cuentan checks del plugin (no del LLM).
|
|
55
|
+
|
|
56
|
+
## Tiered Behaviour
|
|
57
|
+
|
|
58
|
+
`isTrivial(msg,state) = state==DONE && msg.trim().length<30 && /^(hola|hey|gracias|buenas|hi|hello)\b/i.test(msg) && !/(necesito|quiero|agregá|fix|bug|feature|auth|spec|implementar)/i.test(msg)`
|
|
59
|
+
|
|
60
|
+
- **Trivial + DONE**: `output.system[0]` permanece `FULL` diet cacheable (10% hit), plugin añade suffix hint `[PLUGIN HINT: Saludo trivial — responde breve sin tools]` y bloquea `mem_context`/`codegraph_*` con `SKIP`. Solo Engram pointer 1 línea, no `MEMORY_INSTRUCTIONS`.
|
|
61
|
+
- **TIER1** (0/0+1 con intent): hint `TIER1` en suffix, `FULL` sigue cacheado, `DIRECT` sin `Alternatives`.
|
|
62
|
+
- **FULL** (1+): sin hint, `FULL` con `MEMORY_INSTRUCTIONS` lazy (solo si `!isTrivial` o nudge >15m).
|
|
63
|
+
|
|
64
|
+
Principio: **eficacia > recorte** — si recorte rompiera caché y saliera más caro, se prioriza mantener `FULL` estable.
|
|
65
|
+
|
|
66
|
+
## Security single-source
|
|
67
|
+
|
|
68
|
+
`src/security.ts` único origen de `SENSITIVE_DEFAULT`/`BASH_SENSITIVE_RE`/`isSensitive`/`extractPathsFromBash`; plugin y guard importan, no copian. `BASH_SENSITIVE_RE` arriba. `OSTACKY_SENSITIVE_PATTERNS` override.
|
|
69
|
+
|
|
70
|
+
## Tiered single-source
|
|
71
|
+
|
|
72
|
+
`src/tiered.ts` único origen de `isTrivial(msg,state)` + `getControllerState(dir)`. Ambos plugins importan lógica idéntica, no duplican regex. Ver `assets/plugins/ostacky-plugin.ts` y `assets/plugins/engram.ts`.
|
|
73
|
+
|
|
74
|
+
## Prompt-efficiency
|
|
75
|
+
|
|
76
|
+
- `ostacky.md` 109→72 líneas (diet estable cacheable). Tiered vía suffix, no reemplazo `system[0]`.
|
|
77
|
+
- `controller` descriptions <150 chars
|
|
78
|
+
- `context7` lazy: `enabled:false` default, trigger `docs|api|lib|Context7` habilita
|
|
79
|
+
- `MEMORY_INSTRUCTIONS` lazy: siempre pointer (~1 línea) en `system.transform`; full vive en `assets/docs/engram-protocol.md` on-demand via `Read` (ahorro ~1.2k en FULL, trivial ya era pointer)
|