akm-cli 0.9.0-rc.1 → 0.9.0-rc.2
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 +223 -9
- package/SECURITY.md +23 -24
- package/dist/assets/help/help-improve.md +10 -10
- package/dist/assets/hints/cli-hints-full.md +44 -10
- package/dist/assets/hints/cli-hints-short.md +6 -2
- package/dist/assets/{profiles → improve-strategies}/default.json +1 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +1 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +2 -3
- package/dist/assets/{profiles → improve-strategies}/reflect-distill.json +3 -4
- package/dist/assets/stash-skeleton/README.md +28 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +12 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +11 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +7 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +7 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +98 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +63 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +127 -0
- package/dist/assets/tasks/core/backup.yml +1 -0
- package/dist/assets/tasks/core/extract.yml +1 -0
- package/dist/assets/tasks/core/improve.yml +1 -0
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +1 -0
- package/dist/assets/tasks/graph-refresh-weekly.yml +4 -4
- package/dist/assets/templates/html/health.html +5 -1
- package/dist/cli/config-migrate.js +31 -138
- package/dist/cli/config-validate.js +10 -8
- package/dist/cli.js +48 -14
- package/dist/commands/agent/agent-dispatch.js +17 -16
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +5 -15
- package/dist/commands/backup-cli.js +54 -0
- package/dist/commands/config-cli.js +45 -159
- package/dist/commands/env/secret.js +8 -5
- package/dist/commands/health/checks.js +130 -83
- package/dist/commands/health/html-report.js +4 -0
- package/dist/commands/health/improve-metrics.js +30 -32
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +4 -0
- package/dist/commands/health/metrics.js +2 -1
- package/dist/commands/health/surfaces.js +5 -4
- package/dist/commands/health.js +1 -1
- package/dist/commands/improve/consolidate/chunking.js +2 -2
- package/dist/commands/improve/consolidate.js +28 -25
- package/dist/commands/improve/distill/promote-memory.js +5 -12
- package/dist/commands/improve/distill/quality-gate.js +5 -7
- package/dist/commands/improve/distill.js +16 -5
- package/dist/commands/improve/eligibility.js +22 -12
- package/dist/commands/improve/extract-cli.js +47 -19
- package/dist/commands/improve/extract.js +110 -62
- package/dist/commands/improve/improve-cli.js +38 -16
- package/dist/commands/improve/improve-result-file.js +30 -24
- package/dist/commands/improve/improve-strategies.js +137 -0
- package/dist/commands/improve/improve.js +60 -30
- package/dist/commands/improve/locks.js +66 -45
- package/dist/commands/improve/loop-stages.js +75 -33
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +12 -4
- package/dist/commands/improve/preparation.js +71 -73
- package/dist/commands/improve/procedural.js +3 -2
- package/dist/commands/improve/recombine.js +2 -1
- package/dist/commands/improve/reflect.js +119 -214
- package/dist/commands/improve/shared.js +11 -5
- package/dist/commands/lint/base-linter.js +152 -42
- package/dist/commands/mv-cli.js +809 -0
- package/dist/commands/proposal/proposal-cli.js +18 -8
- package/dist/commands/proposal/propose.js +64 -69
- package/dist/commands/read/knowledge.js +436 -4
- package/dist/commands/read/remember-cli.js +39 -2
- package/dist/commands/read/search-cli.js +6 -1
- package/dist/commands/registry-cli.js +29 -14
- package/dist/commands/remember.js +2 -0
- package/dist/commands/sources/init.js +13 -14
- package/dist/commands/sources/schema-repair.js +2 -4
- package/dist/commands/sources/source-add.js +62 -73
- package/dist/commands/sources/source-manage.js +50 -46
- package/dist/commands/sources/stash-cli.js +41 -4
- package/dist/commands/tasks/default-tasks.js +12 -12
- package/dist/commands/tasks/tasks-cli.js +7 -3
- package/dist/commands/tasks/tasks.js +113 -18
- package/dist/commands/wiki-cli.js +9 -10
- package/dist/core/asset/frontmatter.js +12 -2
- package/dist/core/common.js +5 -3
- package/dist/core/config/config-io.js +28 -17
- package/dist/core/config/config-schema.js +358 -66
- package/dist/core/config/config-types.js +3 -3
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +98 -27
- package/dist/core/config/config.js +132 -266
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +32 -0
- package/dist/core/errors.js +2 -2
- package/dist/core/extra-params.js +61 -0
- package/dist/core/file-lock.js +201 -56
- package/dist/core/improve-result.js +178 -0
- package/dist/core/maintenance-barrier.js +119 -0
- package/dist/core/migration-backup.js +416 -0
- package/dist/core/paths.js +3 -0
- package/dist/core/redaction.js +358 -0
- package/dist/core/state/migrations.js +17 -2
- package/dist/core/state-db.js +44 -1
- package/dist/indexer/db/db.js +116 -1
- package/dist/indexer/graph/graph-extraction.js +28 -16
- package/dist/indexer/index-writer-lock.js +31 -24
- package/dist/indexer/index-written-assets.js +15 -6
- package/dist/indexer/indexer.js +47 -2
- package/dist/indexer/passes/memory-inference.js +10 -6
- package/dist/indexer/passes/metadata.js +250 -0
- package/dist/indexer/search/db-search.js +111 -44
- package/dist/indexer/search/fts-query.js +41 -0
- package/dist/indexer/search/ranking-contributors.js +48 -0
- package/dist/indexer/search/ranking.js +36 -23
- package/dist/indexer/search/search-fields.js +11 -1
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -52
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +202 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +7 -2
- package/dist/integrations/agent/profiles.js +6 -99
- package/dist/integrations/agent/runner-dispatch.js +76 -13
- package/dist/integrations/agent/runner.js +76 -207
- package/dist/integrations/agent/spawn.js +4 -6
- package/dist/integrations/harnesses/aider/agent-builder.js +2 -3
- package/dist/integrations/harnesses/aider/index.js +0 -1
- package/dist/integrations/harnesses/amazonq/agent-builder.js +2 -3
- package/dist/integrations/harnesses/amazonq/index.js +0 -1
- package/dist/integrations/harnesses/claude/agent-builder.js +2 -3
- package/dist/integrations/harnesses/claude/index.js +0 -2
- package/dist/integrations/harnesses/codex/agent-builder.js +2 -3
- package/dist/integrations/harnesses/codex/index.js +0 -1
- package/dist/integrations/harnesses/copilot/agent-builder.js +2 -3
- package/dist/integrations/harnesses/copilot/index.js +0 -1
- package/dist/integrations/harnesses/gemini/agent-builder.js +2 -3
- package/dist/integrations/harnesses/gemini/index.js +0 -1
- package/dist/integrations/harnesses/index.js +1 -24
- package/dist/integrations/harnesses/opencode/agent-builder.js +2 -3
- package/dist/integrations/harnesses/opencode/index.js +0 -6
- package/dist/integrations/harnesses/opencode-sdk/harness.js +1 -6
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +274 -191
- package/dist/integrations/harnesses/openhands/agent-builder.js +2 -3
- package/dist/integrations/harnesses/openhands/index.js +0 -1
- package/dist/integrations/harnesses/pi/agent-builder.js +2 -3
- package/dist/integrations/harnesses/pi/index.js +0 -1
- package/dist/integrations/harnesses/types.js +1 -32
- package/dist/integrations/lockfile.js +32 -21
- package/dist/llm/client.js +48 -14
- package/dist/llm/feature-gate.js +15 -47
- package/dist/llm/graph-extract.js +1 -1
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer-impl.js +1 -1
- package/dist/llm/usage-persist.js +4 -0
- package/dist/llm/usage-telemetry.js +35 -5
- package/dist/output/shapes/helpers.js +2 -1
- package/dist/output/shapes/passthrough.js +2 -0
- package/dist/output/text/helpers.js +3 -1
- package/dist/schemas/akm-config.json +11013 -8600
- package/dist/schemas/akm-task.json +87 -0
- package/dist/schemas/akm-workflow.json +57 -13
- package/dist/scripts/migrate-storage.js +8591 -509
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +8623 -484
- package/dist/setup/detected-engines.js +142 -0
- package/dist/setup/engine-config.js +89 -0
- package/dist/setup/setup.js +236 -132
- package/dist/setup/steps/connection.js +61 -32
- package/dist/setup/steps/platforms.js +4 -4
- package/dist/setup/steps.js +3 -2
- package/dist/storage/database.js +13 -1
- package/dist/storage/engines/sqlite-migrations.js +1 -0
- package/dist/storage/repositories/improve-runs-repository.js +5 -5
- package/dist/storage/repositories/task-history-repository.js +78 -0
- package/dist/storage/repositories/workflow-runs-repository.js +9 -8
- package/dist/tasks/parser.js +138 -52
- package/dist/tasks/runner.js +71 -75
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/validator.js +11 -6
- package/dist/wiki/wiki.js +9 -8
- package/dist/workflows/authoring/workflow-program-template.yaml +3 -3
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/db.js +65 -13
- package/dist/workflows/exec/brief.js +18 -24
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +124 -65
- package/dist/workflows/exec/report.js +93 -33
- package/dist/workflows/exec/run-workflow.js +38 -25
- package/dist/workflows/exec/scheduler.js +12 -41
- package/dist/workflows/exec/step-work.js +91 -35
- package/dist/workflows/ir/compile.js +13 -26
- package/dist/workflows/ir/freeze.js +243 -0
- package/dist/workflows/ir/plan-hash.js +40 -5
- package/dist/workflows/ir/schema.js +542 -1
- package/dist/workflows/parser.js +7 -0
- package/dist/workflows/program/parser.js +132 -23
- package/dist/workflows/program/project.js +3 -4
- package/dist/workflows/program/schema.js +2 -2
- package/dist/workflows/resource-limits.js +20 -0
- package/dist/workflows/runtime/plan-classifier.js +187 -0
- package/dist/workflows/runtime/runs.js +54 -47
- package/dist/workflows/runtime/workflow-asset-loader.js +0 -22
- package/dist/workflows/validator.js +25 -0
- package/docs/data-and-telemetry.md +2 -2
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +5 -4
- package/docs/migration/v0.8-to-v0.9.md +401 -0
- package/package.json +4 -2
- package/schemas/akm-config.json +16638 -0
- package/schemas/akm-task.json +87 -0
- package/schemas/akm-workflow.json +372 -0
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- package/dist/llm/call-ai.js +0 -62
- package/dist/setup/legacy-config.js +0 -106
- package/docs/README.md +0 -104
- /package/dist/assets/{profiles → improve-strategies}/catchup.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/consolidate.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/frequent.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/memory-focus.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/quick.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/recombine-only.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/synthesize.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/thorough.json +0 -0
|
@@ -17,10 +17,38 @@ consistency and reducing repeated context-setting.
|
|
|
17
17
|
| `workflows/` | Workflows | Multi-step orchestration sequences |
|
|
18
18
|
| `tasks/` | Tasks | Scheduled or on-demand automation tasks |
|
|
19
19
|
| `lessons/` | Lessons | Durable lessons extracted from past sessions |
|
|
20
|
+
| `facts/` | Facts | Durable stash-level context; the house conventions in `facts/conventions/` are auto-surfaced to authoring agents |
|
|
21
|
+
| `wikis/` | Wikis | Agent-maintained knowledge bases (see `akm wiki`) |
|
|
22
|
+
| `scripts/` | Scripts | Executable helpers agents and humans can run |
|
|
23
|
+
| `env/`, `secrets/` | Env & Secrets | Configuration groups and single credentials; values are never content-indexed |
|
|
20
24
|
|
|
21
25
|
Add your own assets to any of these directories. AKM will index them automatically
|
|
22
26
|
on the next `akm index` run (or when the background improve pipeline picks them up).
|
|
23
27
|
|
|
28
|
+
## How to organize assets
|
|
29
|
+
|
|
30
|
+
A file's path under its type directory becomes part of its ref
|
|
31
|
+
(`knowledge/auth/oauth-refresh-races.md` → `knowledge:auth/oauth-refresh-races`),
|
|
32
|
+
and its segments are search terms: `akm search "auth" --type knowledge` narrows
|
|
33
|
+
to that subtree. Retrieval is search, not folder-browse, so pick subdirectories
|
|
34
|
+
deliberately. The house rules live in three convention facts under
|
|
35
|
+
`facts/conventions/` and are surfaced to agents automatically when they author
|
|
36
|
+
assets:
|
|
37
|
+
|
|
38
|
+
- **`fact:conventions/organization`** — the single path axis, chosen by asset
|
|
39
|
+
type. **Scope-born** types (`memory`, `lesson`, `task`, `env`, `secret`) go
|
|
40
|
+
under the current **project/client** slug; **reuse-born** types (`knowledge`,
|
|
41
|
+
`skill`, `wiki`, `fact`, `script`) go under a stable **domain**; global types
|
|
42
|
+
stay at the type root.
|
|
43
|
+
- **`fact:conventions/backlinks`** — how to cross-link: a provenance xref
|
|
44
|
+
whenever an asset derives from another, sparse real associative links,
|
|
45
|
+
corrections as new assets, canonical entity naming.
|
|
46
|
+
- **`fact:conventions/domains`** — the (editable) domain vocabulary for
|
|
47
|
+
reuse-born assets, plus canonical entity spellings.
|
|
48
|
+
|
|
49
|
+
Per-type nuances live in `facts/conventions/assets/<type>.md`. All of these are
|
|
50
|
+
soft guidance — edit them to match how your stash is queried.
|
|
51
|
+
|
|
24
52
|
## For agents: how to access this stash
|
|
25
53
|
|
|
26
54
|
All assets in this stash are searchable via the `akm` CLI. Use these commands to
|
|
@@ -36,3 +36,9 @@ Use an agent when a recurring task benefits from a specialized role, bounded res
|
|
|
36
36
|
- Add explicit negative guidance when the agent overreaches.
|
|
37
37
|
- Keep role instructions stable and concise; move large background material into knowledge assets.
|
|
38
38
|
- Use lessons to capture operational improvements, then promote stable ones into the agent when they become part of the role.
|
|
39
|
+
|
|
40
|
+
## Placement & linking
|
|
41
|
+
|
|
42
|
+
- Agent definitions are usually **global**: keep them at the type root or under a
|
|
43
|
+
role/domain slug (`agent:reviewer`). Point the agent at the standards and type
|
|
44
|
+
conventions it must read first via xrefs.
|
|
@@ -36,3 +36,9 @@ Use a command when the user or agent needs to perform the same prompt-shaped tas
|
|
|
36
36
|
- If command output regularly becomes useful durable knowledge, instruct the agent to file the result into the right asset type.
|
|
37
37
|
- If the command starts handling multiple unrelated tasks, split it into smaller commands.
|
|
38
38
|
- Preserve a clear invocation contract so future agents can call the command safely.
|
|
39
|
+
|
|
40
|
+
## Placement & linking
|
|
41
|
+
|
|
42
|
+
- Commands are usually **global**: keep them at the type root or under a
|
|
43
|
+
tool/domain slug. Scope to a project only when the command is genuinely
|
|
44
|
+
project-specific.
|
|
@@ -34,6 +34,17 @@ Use a fact for stable information that future agents should treat as true or nor
|
|
|
34
34
|
## Maintenance strategy
|
|
35
35
|
|
|
36
36
|
- Revise or supersede facts when the durable truth changes.
|
|
37
|
-
- Do not allow contradictory facts to remain equally active
|
|
37
|
+
- Do not allow contradictory facts to remain equally active: mark the loser
|
|
38
|
+
`beliefState: superseded` / `supersededBy: [<new ref>]` so ranking demotes it.
|
|
38
39
|
- Promote repeated memories or lessons into facts only when they become stable context.
|
|
39
40
|
- Keep convention and meta facts especially clear, because they steer future asset creation.
|
|
41
|
+
|
|
42
|
+
## Placement & linking
|
|
43
|
+
|
|
44
|
+
- Facts are **reuse-born**: give a policy/standard fact a domain-like prefix
|
|
45
|
+
(`fact:policies/pii-handling`) or the type root for personal/meta facts.
|
|
46
|
+
- Facts are also the **delivery layer** for stash-wide conventions:
|
|
47
|
+
`category: convention` or `category: meta` facts are surfaced to every non-wiki
|
|
48
|
+
author, so this is where naming, placement, and linking house-rules live. Keep
|
|
49
|
+
each one short — they inject into authoring prompts. Reserve `pinned: true` for
|
|
50
|
+
the small always-injected core.
|
|
@@ -36,5 +36,15 @@ Use a knowledge asset for durable reference material, synthesized explanations,
|
|
|
36
36
|
|
|
37
37
|
- Update the existing page when new information changes the same topic; append a dated note rather than silently rewriting when provenance matters.
|
|
38
38
|
- Create a new page when the concept deserves its own durable entry.
|
|
39
|
-
- Add
|
|
39
|
+
- Add a return link when you are already editing the related page in the same pass.
|
|
40
40
|
- Periodically scan for orphaned, stale, or overlapping knowledge docs and consolidate them.
|
|
41
|
+
|
|
42
|
+
## Placement & linking
|
|
43
|
+
|
|
44
|
+
- Knowledge is **reuse-born**: file it under a stable **domain** prefix from
|
|
45
|
+
`fact:conventions/domains` (`knowledge:auth/oauth-refresh-races`), not under a
|
|
46
|
+
project — that domain slug is what any project searches to reuse it.
|
|
47
|
+
- Knowledge pages are the rewritable synthesized layer — update them in place.
|
|
48
|
+
Ingested source material stays immutable; corrections to it are new assets
|
|
49
|
+
that xref the source. Carry a provenance xref when derived, and a
|
|
50
|
+
self-situating header.
|
|
@@ -41,3 +41,9 @@ Use a lesson to record:
|
|
|
41
41
|
- Create a new lesson only when the trigger or failure mode is meaningfully different.
|
|
42
42
|
- Deprecate or revise stale lessons instead of allowing contradictory guidance to accumulate.
|
|
43
43
|
- When a lesson becomes broadly normative, consider promoting the stable rule into a `fact:conventions/...` asset.
|
|
44
|
+
|
|
45
|
+
## Placement & linking
|
|
46
|
+
|
|
47
|
+
- Lessons are **scope-born**: file them under the **project/client** they were
|
|
48
|
+
learned in (`lesson:projectA/token-refresh-gotcha`) and xref the asset the
|
|
49
|
+
lesson corrects or refines.
|
|
@@ -36,3 +36,12 @@ Use a memory when a future agent would make a better decision by knowing a speci
|
|
|
36
36
|
- Consolidate repeated memories into a clearer fact or knowledge asset.
|
|
37
37
|
- Convert broad, stable conventions into `fact` assets.
|
|
38
38
|
- Archive memories that are no longer current rather than letting stale context keep influencing agents.
|
|
39
|
+
|
|
40
|
+
## Placement & linking
|
|
41
|
+
|
|
42
|
+
- Memories are **scope-born**: file them under the **current project/client**
|
|
43
|
+
slug (`memory:projectA/auth-token-refresh`) — the working context is the
|
|
44
|
+
answer, so no per-asset judgment is needed. Add the subject as a tag
|
|
45
|
+
(`tags: [auth, projectA]`) for cross-cutting recall.
|
|
46
|
+
- When a memory turns out to be domain-general, **append** a new
|
|
47
|
+
`knowledge:<domain>/…` asset that xrefs it — never rename the memory up a rung.
|
|
@@ -41,3 +41,10 @@ Use a script when a task is mechanical, repeatable, and better handled by a dete
|
|
|
41
41
|
- Keep dangerous actions behind explicit flags.
|
|
42
42
|
- When a script becomes a core operation, add or update a workflow that explains when to run it.
|
|
43
43
|
- If the script encodes a convention, also document that convention in a fact or knowledge asset.
|
|
44
|
+
|
|
45
|
+
## Placement & linking
|
|
46
|
+
|
|
47
|
+
- Scripts are **reuse-born**: file a general helper under a tool/domain slug
|
|
48
|
+
from `fact:conventions/domains` (`script:build/release`). Use the project slug
|
|
49
|
+
only when the script hard-codes project-specific paths, endpoints, or
|
|
50
|
+
credentials.
|
|
@@ -38,3 +38,10 @@ Use a skill when the stash needs reusable procedural guidance for a recurring cl
|
|
|
38
38
|
- Add companion knowledge docs when the skill needs background material that would bloat the main procedure.
|
|
39
39
|
- Promote durable recurring corrections into the skill; leave one-off observations in memories or lessons.
|
|
40
40
|
- Prefer small edits that preserve the skill’s operational shape over broad rewrites that erase tested guidance.
|
|
41
|
+
|
|
42
|
+
## Placement & linking
|
|
43
|
+
|
|
44
|
+
- Skills are **reuse-born**: place `skills/<domain>/<name>/SKILL.md` under a
|
|
45
|
+
stable **domain** prefix from `fact:conventions/domains`
|
|
46
|
+
(`skill:testing/flaky-test-triage`) so any project finds and reuses it instead
|
|
47
|
+
of duplicating the procedure.
|
|
@@ -41,3 +41,9 @@ Use a workflow when the task requires multiple steps, branching decisions, repea
|
|
|
41
41
|
- Add logging expectations when the workflow creates durable state.
|
|
42
42
|
- Extract reusable sub-procedures into skills or scripts when the workflow grows too broad.
|
|
43
43
|
- Record recurring mistakes as lessons, then fold stable corrections back into the workflow.
|
|
44
|
+
|
|
45
|
+
## Placement & linking
|
|
46
|
+
|
|
47
|
+
- Workflows are usually **global**: keep them at the type root or under a
|
|
48
|
+
tool/domain slug (`workflow:release-train`). Scoping a workflow to one project
|
|
49
|
+
rarely improves retrieval and adds rename risk.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: convention
|
|
3
|
+
description: How to cross-link assets so retrieval compounds — a provenance xref when derived, sparse real associative xrefs, corrections as new assets, and canonical entity naming.
|
|
4
|
+
when_to_use: Surfaced to authoring agents when they create or revise any non-wiki asset that derives from, corrects, or relates to another asset.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!--
|
|
8
|
+
SOFT guidance only — advice, not a contract. Back-linking here is a RETRIEVAL
|
|
9
|
+
mechanism, not decoration: `xrefs:` frontmatter folds into the search index;
|
|
10
|
+
the entity/relation graph is extracted from BODY prose (memory + knowledge),
|
|
11
|
+
never from frontmatter. Over-linking degrades ranking, so these rules are
|
|
12
|
+
deliberately conservative. Wikis have their own xref + lint system — this
|
|
13
|
+
convention is for non-wiki assets.
|
|
14
|
+
-->
|
|
15
|
+
|
|
16
|
+
# Back-linking conventions
|
|
17
|
+
|
|
18
|
+
Cross-references are how knowledge compounds instead of being re-derived every
|
|
19
|
+
session. In AKM they are also **indexed**: the strings in an asset's `xrefs:`
|
|
20
|
+
frontmatter fold into its search-hint text, and knowledge/memory bodies feed an
|
|
21
|
+
LLM-extracted entity/relation graph that boosts ranking. So links are a retrieval
|
|
22
|
+
lever — which means both too few and too many hurt.
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
---
|
|
26
|
+
description: OAuth refresh-token race on token rotation
|
|
27
|
+
tags: [auth, projectA]
|
|
28
|
+
xrefs:
|
|
29
|
+
- knowledge:auth/vendor-x-token-api # provenance: what this was synthesized from
|
|
30
|
+
- lesson:projectA/token-refresh-gotcha # one real associative link
|
|
31
|
+
---
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Link rules
|
|
35
|
+
|
|
36
|
+
- **One xref is mandatory when the asset derives from another: cite the source
|
|
37
|
+
ref** (`memory:projectA/token-quirk` xrefs `knowledge:auth/vendor-x-token-api`
|
|
38
|
+
— it also makes this asset findable from searches for its source). An
|
|
39
|
+
original observation with no source carries none — never invent provenance.
|
|
40
|
+
`akm remember`/`akm import` write this channel via `--xref <ref>`
|
|
41
|
+
(repeatable; refs are checked at write time). Wikis enforce the analogous
|
|
42
|
+
rule mechanically (`sources:` + `uncited-raw` lint); non-wiki provenance is
|
|
43
|
+
discipline only.
|
|
44
|
+
- **Associative xrefs are discretionary — real relationships only.** Add one when
|
|
45
|
+
you already know a genuine load-bearing connection. Do **not** hit a link
|
|
46
|
+
quota by pointing at the topically-nearest sibling — a plausible-but-wrong
|
|
47
|
+
xref makes this asset a false search match for the other topic, and a wrong
|
|
48
|
+
relationship asserted in prose poisons the entity graph. A relationship you
|
|
49
|
+
want the graph to learn must be named in the body (e.g. open with "Corrects
|
|
50
|
+
knowledge:auth/oauth-refresh-races").
|
|
51
|
+
- **Cap total xrefs at ~5 (a heuristic, not a measured threshold).** Each xref
|
|
52
|
+
folds its ref tokens into THIS asset's search hints — past a handful, the
|
|
53
|
+
asset matches queries about several other topics and its own ranking signal
|
|
54
|
+
blurs.
|
|
55
|
+
- **Corrections are new assets; ingested material is immutable.** Treat wiki
|
|
56
|
+
`raw/`, vendored docs, and transcripts as immutable-by-discipline: a hard-won
|
|
57
|
+
fix is a new `lesson:` or `knowledge:` asset that xrefs what it corrects.
|
|
58
|
+
Synthesized `knowledge:` pages are the rewritable layer — update them in
|
|
59
|
+
place. When a correction supersedes a standalone asset (memory OR knowledge),
|
|
60
|
+
also set the old asset's `beliefState: superseded` and
|
|
61
|
+
`supersededBy: [<new ref>]` — a metadata edit, not a content edit — so the
|
|
62
|
+
ranker demotes the stale version instead of letting it outrank your fix.
|
|
63
|
+
`akm remember`/`akm import` do both writes in one step via
|
|
64
|
+
`--supersedes <old ref>` (adds the xref and demotes the old asset).
|
|
65
|
+
- **Bidirectional back-links are best-effort.** Add a return xref only when you
|
|
66
|
+
are already editing the target in the same pass. Never require editing a
|
|
67
|
+
separate hot file just to add a back-xref — concurrent writes drop it under
|
|
68
|
+
last-writer-wins and no lint will notice.
|
|
69
|
+
|
|
70
|
+
## Self-situating headers and canonical naming
|
|
71
|
+
|
|
72
|
+
Put the one-line orientation in `description:` and the trigger conditions in
|
|
73
|
+
`when_to_use:` — those are indexed fields; body prose is not indexed by
|
|
74
|
+
default (only headings reach the index; the opt-in `index.indexBodyOpening`
|
|
75
|
+
flag adds just the first body paragraph, at the lowest weight —
|
|
76
|
+
`description:`/`when_to_use:` remain the primary orientation channel). Then
|
|
77
|
+
open the body with a plain title plus a one-line
|
|
78
|
+
orientation naming what it is, its scope/domain, and its key entities in
|
|
79
|
+
canonical spelling (`Postgres`, `OAuth`, `TLS`, `Acme`) — the entity/relation
|
|
80
|
+
graph is extracted from body prose, and readers land here from `akm show`.
|
|
81
|
+
Keep the canonical-spelling list in `fact:conventions/domains` so agents don't
|
|
82
|
+
fragment `postgres` / `postgresql` / `pg`.
|
|
83
|
+
|
|
84
|
+
## Hubs are optional, not per-namespace obligations
|
|
85
|
+
|
|
86
|
+
A hub (a `wiki:` overview page that xrefs the key assets in a domain) is worth
|
|
87
|
+
authoring for a **few genuinely high-traffic domains** — wikis are the one type
|
|
88
|
+
with real orphan/broken-xref/stale-index lint to keep a hub honest. Do **not**
|
|
89
|
+
mandate a hub per namespace and do not edit a hub on every write: that is O(n)
|
|
90
|
+
maintenance, a concurrent-write contention point, and it flattens the multi-hop
|
|
91
|
+
graph into a namespace-wide star. Let the FTS index be the catalog; spend the
|
|
92
|
+
effort on per-asset self-situating headers instead.
|
|
93
|
+
|
|
94
|
+
## Keep assets atomic
|
|
95
|
+
|
|
96
|
+
One concept per asset. If a note covers two concepts, write two assets and xref
|
|
97
|
+
them — atomic assets give the ranker clean, single-topic targets and give you a
|
|
98
|
+
real relationship to link rather than a blurred one to bury.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: convention
|
|
3
|
+
description: The closed vocabulary of domain prefixes for reuse-born assets (knowledge/skill/wiki/fact/script), plus canonical entity spellings. Edit this to match your stash.
|
|
4
|
+
when_to_use: Surfaced to authoring agents alongside the other convention facts; consult it when picking a domain prefix for a knowledge, skill, fact, or script asset (for wikis, the domain names the wiki).
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!--
|
|
8
|
+
SOFT guidance only. This is the domain vocabulary that `organization.md` refers
|
|
9
|
+
to. It is intentionally SHORT and STARTER — replace these with the domains your
|
|
10
|
+
stash actually accumulates. A closed list keeps agents from coining a new
|
|
11
|
+
folder per session (which fragments the tree and splits slug search); the flat
|
|
12
|
+
type-root fallback in organization.md handles anything that doesn't fit yet.
|
|
13
|
+
-->
|
|
14
|
+
|
|
15
|
+
# Domain vocabulary
|
|
16
|
+
|
|
17
|
+
Reuse-born assets (`knowledge`, `skill`, `wiki`, `fact`, `script`) take a
|
|
18
|
+
**domain prefix** from this list, e.g. `knowledge:auth/oauth-refresh-races`,
|
|
19
|
+
`skill:testing/flaky-test-triage` (for a wiki, the domain names the wiki:
|
|
20
|
+
`wikis/auth/`). Pick the closest match. If two fit, take the one naming the
|
|
21
|
+
SUBJECT of the doc (what it teaches, not where it was met) and put the other in
|
|
22
|
+
tags; if still tied, the earlier entry in this list wins. If nothing fits, write
|
|
23
|
+
the asset at the type root and propose an addition here — do **not** invent a
|
|
24
|
+
one-off domain mid-task.
|
|
25
|
+
|
|
26
|
+
## Starter domains
|
|
27
|
+
|
|
28
|
+
Add, remove, and rename to fit your stash. Keep the list short (roughly a dozen)
|
|
29
|
+
— the whole list rides along in every authoring prompt, and a short closed list
|
|
30
|
+
is what keeps two agents picking the same slug. Add a subdomain only where
|
|
31
|
+
volume justifies it.
|
|
32
|
+
|
|
33
|
+
- `auth` — authentication, authorization, tokens, sessions
|
|
34
|
+
- `networking` — protocols, TLS, DNS, proxies, connectivity
|
|
35
|
+
- `databases` — storage engines, queries, migrations (subdomain e.g. `databases/postgres`)
|
|
36
|
+
- `testing` — test strategy, fixtures, flaky-test triage, coverage
|
|
37
|
+
- `build` — build systems, packaging, CI pipelines
|
|
38
|
+
- `cloud` — infra, deploy targets, IaC (subdomain e.g. `cloud/aws`)
|
|
39
|
+
- `observability` — logging, metrics, tracing, alerting
|
|
40
|
+
- `security` — threat modeling, secrets handling, hardening
|
|
41
|
+
- `frontend` — UI, rendering, client state
|
|
42
|
+
- `data-pipelines` — ETL, streaming, batch processing
|
|
43
|
+
- `tooling` — dev tooling, editor/agent integration, scripts
|
|
44
|
+
- `policies` — organizational/business rules the work must obey (PII handling, licensing) (`fact:policies/…`)
|
|
45
|
+
- `conventions` — stash authoring house-rules (`fact:conventions/…`; auto-surfaced to authoring agents — keep them in this directory)
|
|
46
|
+
|
|
47
|
+
## Canonical entity spellings
|
|
48
|
+
|
|
49
|
+
Pick ONE name per entity and use it everywhere in asset **bodies** — retrieval
|
|
50
|
+
is case-insensitive but treats aliases as different entities, so alias variants
|
|
51
|
+
fragment the entity graph. Extend as your stash grows.
|
|
52
|
+
|
|
53
|
+
- Postgres (not postgresql / pg)
|
|
54
|
+
- Kubernetes (not k8s)
|
|
55
|
+
- TLS (not ssl when you mean TLS)
|
|
56
|
+
- OAuth
|
|
57
|
+
|
|
58
|
+
Project and client slugs are **not** listed here — those are scope slugs for
|
|
59
|
+
scope-born types (`memory`, `lesson`, `task`, `env`, `secret`). Keep their
|
|
60
|
+
canonical spellings in a `category: meta` fact (e.g. `fact:active-projects`) so
|
|
61
|
+
they auto-inject at authoring time — not in `.meta/`, which is unindexed and
|
|
62
|
+
invisible mid-task — and `akm search` for an existing spelling before minting a
|
|
63
|
+
new one.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: convention
|
|
3
|
+
description: Where to place an asset in the stash — the one path partition axis, chosen by asset type, so refs stay stable and slug search (akm search "<slug>" --type <type>) co-locates related assets.
|
|
4
|
+
when_to_use: Surfaced to authoring agents when they create or move any non-wiki asset and must decide its subdirectory/name.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!--
|
|
8
|
+
SOFT guidance only — advice, not a contract. Nothing here is enforced by the
|
|
9
|
+
proposal gate. It steers WHERE assets go so that path-derived refs stay stable
|
|
10
|
+
and scoped search (`akm search "<slug>" --type <type>`) keeps working. Tune
|
|
11
|
+
the axis choices and the domain vocabulary to match how your stash is queried.
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
# Stash organization conventions
|
|
15
|
+
|
|
16
|
+
A file's path under its type directory **becomes part of its ref**
|
|
17
|
+
(`knowledge/auth/oauth-refresh-races.md` → `knowledge:auth/oauth-refresh-races`).
|
|
18
|
+
That ref is an address other assets cite, and its segments are search terms —
|
|
19
|
+
`akm search "projectA" --type memory` reconstructs a project's memories. The
|
|
20
|
+
path is therefore the one facet you **cannot express twice and cannot change
|
|
21
|
+
without breaking the ref** — so spend it deliberately, on exactly one axis.
|
|
22
|
+
|
|
23
|
+
Retrieval is search, not browse: no one walks these folders at query time. A
|
|
24
|
+
subdirectory buys you three things: its tokens are indexed as part of the
|
|
25
|
+
asset's **name** (the highest-weighted search field), they are auto-added to
|
|
26
|
+
`tags` (even when you set `tags` explicitly), and for scope-born types a slug
|
|
27
|
+
matching the current repo's name earns an automatic in-project ranking boost.
|
|
28
|
+
Every other facet belongs in frontmatter, where the index can actually read it.
|
|
29
|
+
|
|
30
|
+
## Choose the partition axis by asset TYPE, not per-asset judgment
|
|
31
|
+
|
|
32
|
+
Deciding "project or domain?" per asset is non-deterministic — two agents guess
|
|
33
|
+
differently and bake the wrong guess into an immutable ref. Decide by type:
|
|
34
|
+
|
|
35
|
+
- **Scope-born types → current project / client / team slug.**
|
|
36
|
+
`memory`, `lesson`, `task`, `env`, `secret`. These are born bound to the work
|
|
37
|
+
in front of you, so the working context *is* the answer — no judgment needed.
|
|
38
|
+
When the scope is a single repo, use its repo/package name as the slug (as
|
|
39
|
+
`git remote`/package.json spell it) — ranking auto-boosts assets whose name
|
|
40
|
+
or tags match the current repo. Client/team slugs get no such boost; just
|
|
41
|
+
reuse the existing spelling.
|
|
42
|
+
- `memory:projectA/auth-token-refresh`
|
|
43
|
+
- `lesson:clientX/migration-rollback-gotcha`
|
|
44
|
+
- `secret:clientX/api-key`
|
|
45
|
+
- **Reuse-born types → stable domain from a short vocabulary.**
|
|
46
|
+
`knowledge`, `skill`, `wiki`, `fact`, `script`. These are meant to be reused
|
|
47
|
+
across projects, so co-locate them by subject — any project retrieves them
|
|
48
|
+
with `akm search "<domain>" --type <type>`. For a wiki the domain names the
|
|
49
|
+
wiki itself (`wikis/auth/`); inside it, its `schema.md` and wiki lint govern
|
|
50
|
+
layout, not these rules.
|
|
51
|
+
- `knowledge:auth/oauth-refresh-races`
|
|
52
|
+
- `skill:testing/flaky-test-triage`
|
|
53
|
+
- `fact:policies/pii-handling`
|
|
54
|
+
- **Global-by-nature types → type root or a tool slug.**
|
|
55
|
+
`command`, `agent`, `workflow`, and stash-wide `env`. Scoping these to a
|
|
56
|
+
project rarely improves precision and only adds rename risk. `env` defaults
|
|
57
|
+
to the project/client slug; only an env consumed by every project sits at
|
|
58
|
+
the type root — if any single project would break when it changes, it is
|
|
59
|
+
scope-born.
|
|
60
|
+
|
|
61
|
+
**Why reuse types don't take the project axis:** project relevance is already
|
|
62
|
+
recovered at query time — AKM blends a per-project usage signal into ranking
|
|
63
|
+
(scoped utility, keyed off the current repo, not the asset's path). Free the
|
|
64
|
+
scarce path segment for the domain — the *only* handle that co-locates
|
|
65
|
+
cross-project reuse.
|
|
66
|
+
|
|
67
|
+
## Placement rules
|
|
68
|
+
|
|
69
|
+
- **One axis only.** Never encode two dimensions in the path
|
|
70
|
+
(`client/project/subsystem`, or `domain+status`). Second dimensions go in tags.
|
|
71
|
+
- **Depth 1 by default, 2 max**, and only for strict stable containment
|
|
72
|
+
(`knowledge/databases/postgres/…`, `secret/clientX/projectA/…`). Never a third
|
|
73
|
+
semantic level — deeper axes go in frontmatter.
|
|
74
|
+
- **Segments are lowercase-hyphen semantic tokens** that read as query terms
|
|
75
|
+
(`connection-pooling`, `tls-handshake-debugging`) — never opaque IDs, numbers,
|
|
76
|
+
or Johnny.Decimal-style codes, which carry no search signal.
|
|
77
|
+
- **Never put a volatile facet in the path** — status, date, version, priority,
|
|
78
|
+
author, `wip`/`done`. Each one changes and forces a ref-breaking rename. They
|
|
79
|
+
belong in frontmatter tags.
|
|
80
|
+
- **Flat fallback beats an invented folder.** If no domain fits a reuse-type
|
|
81
|
+
asset, write it at the type root (`knowledge:http-retry-basics`) rather than
|
|
82
|
+
coining a one-off domain. An unneeded folder is pure rename liability; propose
|
|
83
|
+
a vocabulary addition instead of fragmenting the tree.
|
|
84
|
+
- **Reuse an existing slug before minting a new one.** Before coining a new
|
|
85
|
+
project/client/domain slug, `akm search` for the existing spelling
|
|
86
|
+
(`acme` vs `acme-corp`) so the prefix does not fragment. Keep the domain
|
|
87
|
+
vocabulary in `fact:conventions/domains`.
|
|
88
|
+
- **Off-axis facets go in `tags:`, not a bare field.** The indexed FTS fields are
|
|
89
|
+
name, description, tags, hints, and content (headings only — body prose is
|
|
90
|
+
not indexed by default; the opt-in `index.indexBodyOpening` flag adds just
|
|
91
|
+
the first body paragraph, at the lowest weight) — there is **no `project`
|
|
92
|
+
field**, so `project: projectA` in
|
|
93
|
+
frontmatter is invisible to search. Put the off-axis facet in `tags` instead
|
|
94
|
+
(a project-scoped memory adds `tags: [auth]`; a domain-scoped asset genuinely
|
|
95
|
+
tied to a project adds `tags: [projectA]` sparingly).
|
|
96
|
+
- **Directory tokens join `tags` on their own.** The scope/domain segments of
|
|
97
|
+
the path are always auto-added to `tags` — even when you set `tags`
|
|
98
|
+
explicitly — so there is no need to restate them; the tag-match ranking
|
|
99
|
+
boost fires for the scope token either way. Filename tokens are auto-added
|
|
100
|
+
only when `tags` is empty.
|
|
101
|
+
|
|
102
|
+
## Renames and evolution
|
|
103
|
+
|
|
104
|
+
- **A ref is chosen once. Default to not renaming.** A manual rename dangles
|
|
105
|
+
inbound xrefs silently at write time — nothing catches the breakage until
|
|
106
|
+
the next `akm lint` run flags the dead frontmatter refs (`missing-ref`) —
|
|
107
|
+
while the dead ref string keeps scoring in FTS, and a manually renamed file
|
|
108
|
+
is a new index entry, so the asset's accumulated usage-ranking history
|
|
109
|
+
resets.
|
|
110
|
+
- If a rename is truly unavoidable, prefer `akm mv <ref> <new-name>`
|
|
111
|
+
(Experimental): it moves the file, rewrites inbound references across the
|
|
112
|
+
writable stash in the same pass, and keeps the asset's usage-ranking
|
|
113
|
+
history. Citing files in read-only sources are reported for manual
|
|
114
|
+
follow-up. On an older CLI without `akm mv`, treat the rename as an
|
|
115
|
+
xref-fixing operation: grep the stash for the old ref string and fix every
|
|
116
|
+
inbound reference in the same pass.
|
|
117
|
+
- When a project-scoped note turns out to be domain-general, **append, don't
|
|
118
|
+
promote**: write a new `knowledge:<domain>/…` asset that xrefs the originating
|
|
119
|
+
memory. Never rename the memory up a rung — that breaks its ref. The atomic
|
|
120
|
+
note still serves factoid recall; the new synthesis serves reuse; the xref
|
|
121
|
+
bridges them.
|
|
122
|
+
|
|
123
|
+
## Real isolation is a separate stash, not a folder
|
|
124
|
+
|
|
125
|
+
A path prefix is a ranking scope, not a security boundary. When you need enforced
|
|
126
|
+
isolation (client confidentiality, secret-leak containment), mount a **separate
|
|
127
|
+
stash** and let source resolution keep it apart — don't rely on a subdirectory.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
version: 2
|
|
2
2
|
description: >
|
|
3
3
|
Weekly full-corpus graph extraction pass. Rebuilds entity and relation
|
|
4
|
-
indexes across all stash files using the graph-refresh improve
|
|
4
|
+
indexes across all stash files using the graph-refresh improve strategy.
|
|
5
5
|
Complements the per-run improve pipeline which only extracts graph data
|
|
6
6
|
for files touched by actionable refs.
|
|
7
|
-
command: akm improve --
|
|
7
|
+
command: akm improve --strategy graph-refresh
|
|
8
8
|
schedule: "0 3 * * 0"
|
|
9
9
|
enabled: false
|
|
10
|
-
|
|
10
|
+
timeoutMs: 3600000
|
|
@@ -391,7 +391,7 @@
|
|
|
391
391
|
<div class="table-wrap">
|
|
392
392
|
<table>
|
|
393
393
|
<thead>
|
|
394
|
-
<tr><th>Started</th><th>Task</th><th>Wall</th><th>Promoted</th><th>Merged</th><th>Contradicted</th><th>MI Written</th><th>Entities</th><th>Lint Fixed</th><th>Status</th></tr>
|
|
394
|
+
<tr><th>Started</th><th>Task</th><th>Strategy</th><th>Legacy Profile</th><th>Wall</th><th>Promoted</th><th>Merged</th><th>Contradicted</th><th>MI Written</th><th>Entities</th><th>Lint Fixed</th><th>Status</th></tr>
|
|
395
395
|
</thead>
|
|
396
396
|
<tbody id="lastRunsTable"></tbody>
|
|
397
397
|
</table>
|
|
@@ -683,12 +683,16 @@ tbody.innerHTML = '';
|
|
|
683
683
|
const ts = `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
684
684
|
const dur = r.wallTimeMs ? (r.wallTimeMs / 60000).toFixed(1) + 'm' : '—';
|
|
685
685
|
const task = r.taskId || 'manual';
|
|
686
|
+
const strategy = r.strategy || '—';
|
|
687
|
+
const legacyProfile = r.legacyProfile || '—';
|
|
686
688
|
const badge = r.ok
|
|
687
689
|
? '<span class="badge-pill badge-pass" style="padding:2px 8px;font-size:11px;"><span class="dot dot-pass" style="width:6px;height:6px;"></span> ok</span>'
|
|
688
690
|
: '<span class="badge-pill badge-fail" style="padding:2px 8px;font-size:11px;"><span class="dot dot-fail" style="width:6px;height:6px;"></span> failed</span>';
|
|
689
691
|
tr.innerHTML = `
|
|
690
692
|
<td style="font-family:monospace;font-size:12px;">${ts}</td>
|
|
691
693
|
<td><code>${task}</code></td>
|
|
694
|
+
<td><code>${strategy}</code></td>
|
|
695
|
+
<td><code>${legacyProfile}</code></td>
|
|
692
696
|
<td>${dur}</td>
|
|
693
697
|
<td style="color:var(--accent);font-weight:600;">${r.promoted || 0}</td>
|
|
694
698
|
<td>${r.merged || 0}</td>
|