@tenkara/afm-linux-arm64 0.0.0-stage → 4.0.0-alpha.11
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/bin/afm +4 -0
- package/content/.coupling-baseline.tsv +1 -0
- package/content/.pending-commands.txt +2 -0
- package/content/CHANGELOG-archive.md +806 -0
- package/content/CHANGELOG.md +4330 -0
- package/content/PRINCIPLES.md +119 -0
- package/content/README-light.md +158 -0
- package/content/README.md +150 -0
- package/content/code-style/_any/file-size.md +62 -0
- package/content/code-style/_any/imports.md +68 -0
- package/content/code-style/_any/naming.md +72 -0
- package/content/code-style/_any/test-placement.md +57 -0
- package/content/code-style/nextjs-app-router/imports.md +50 -0
- package/content/code-style/nextjs-app-router/naming.md +50 -0
- package/content/code-style/prisma-postgres/error-boundary.md +55 -0
- package/content/code-style/prisma-postgres/imports.md +61 -0
- package/content/code-style/shadcn-ui/naming.md +48 -0
- package/content/code-style/stripe-billing/naming.md +76 -0
- package/content/code-style/trigger-dev-v4/imports.md +58 -0
- package/content/code-style/trigger-dev-v4/naming.md +49 -0
- package/content/code-style/trigger-dev-v4/test-placement.md +61 -0
- package/content/code-style/trpc-v11/error-boundary.md +51 -0
- package/content/code-style/trpc-v11/file-size.md +44 -0
- package/content/code-style/trpc-v11/naming.md +60 -0
- package/content/code-style/trpc-v11/test-placement.md +52 -0
- package/content/core/ach.md +260 -0
- package/content/core/afm.md +514 -0
- package/content/core/gotchas.md +18 -0
- package/content/core/prd.md +141 -0
- package/content/core/protocol.md +158 -0
- package/content/core/ust.md +65 -0
- package/content/guardrails/README.md +55 -0
- package/content/guardrails/dsl-com-ordem-obrigatoria.md +47 -0
- package/content/guardrails/exaustividade-de-union.md +48 -0
- package/content/guardrails/fronteira-de-import.md +57 -0
- package/content/hooks/README.md +70 -0
- package/content/interview/bootstrap.md +417 -0
- package/content/interview/promotion.md +115 -0
- package/content/interview/refactor.md +379 -0
- package/content/interview/triggers.md +107 -0
- package/content/modules/nextjs-app-router/ach.patch.md +44 -0
- package/content/modules/nextjs-app-router/gotchas.seed.md +78 -0
- package/content/modules/nextjs-app-router/rules.patch.md +35 -0
- package/content/modules/prisma-postgres/ach.patch.md +65 -0
- package/content/modules/prisma-postgres/rules.patch.md +28 -0
- package/content/modules/shadcn-ui/ach.patch.md +42 -0
- package/content/modules/stripe-billing/ach.patch.md +46 -0
- package/content/modules/stripe-billing/gotchas.seed.md +73 -0
- package/content/modules/stripe-billing/rules.patch.md +30 -0
- package/content/modules/trigger-dev-v4/ach.patch.md +64 -0
- package/content/modules/trigger-dev-v4/gotchas.seed.md +53 -0
- package/content/modules/trigger-dev-v4/rules.patch.md +35 -0
- package/content/modules/trpc-v11/ach.patch.md +56 -0
- package/content/modules/trpc-v11/rules.patch.md +34 -0
- package/content/modules/vireya-ui/ach.patch.md +85 -0
- package/content/modules/vireya-ui/gotchas.seed.md +98 -0
- package/content/modules/vireya-ui/rules.patch.md +36 -0
- package/content/ops/adr.md +54 -0
- package/content/ops/analyze.md +130 -0
- package/content/ops/clarify.md +86 -0
- package/content/ops/deliver.md +209 -0
- package/content/ops/diagnose.md +143 -0
- package/content/ops/evolve.md +366 -0
- package/content/ops/export-template.md +97 -0
- package/content/ops/generalize.md +117 -0
- package/content/ops/gotcha.md +46 -0
- package/content/ops/obligations.md +145 -0
- package/content/ops/plan.md +61 -0
- package/content/ops/policy.md +61 -0
- package/content/ops/promote.md +72 -0
- package/content/ops/protocol.md +51 -0
- package/content/ops/reconcile.md +44 -0
- package/content/ops/reflect.md +182 -0
- package/content/ops/remediate.md +143 -0
- package/content/ops/restructure.md +142 -0
- package/content/ops/rule.md +170 -0
- package/content/ops/specify.md +62 -0
- package/content/ops/tasks.md +67 -0
- package/content/ops/update.md +252 -0
- package/content/ops/verify.md +67 -0
- package/content/patterns/adapter.md +46 -0
- package/content/patterns/facade.md +47 -0
- package/content/patterns/factory.md +46 -0
- package/content/patterns/null-object.md +55 -0
- package/content/patterns/result-vs-exception.md +52 -0
- package/content/patterns/strategy.md +45 -0
- package/content/patterns/template-method-vs-composition.md +50 -0
- package/content/questions/adr.questions.yaml +14 -0
- package/content/questions/analyze.questions.yaml +12 -0
- package/content/questions/bootstrap-mapping.questions.yaml +14 -0
- package/content/questions/bootstrap-rules.questions.yaml +10 -0
- package/content/questions/bootstrap-stack.questions.yaml +23 -0
- package/content/questions/clarify.questions.yaml +10 -0
- package/content/questions/code-style.questions.yaml +12 -0
- package/content/questions/confirm.questions.yaml +12 -0
- package/content/questions/deliver.questions.yaml +23 -0
- package/content/questions/evolve.questions.yaml +15 -0
- package/content/questions/export-template-apply.questions.yaml +11 -0
- package/content/questions/export-template.questions.yaml +23 -0
- package/content/questions/gates.questions.yaml +27 -0
- package/content/questions/generalize.questions.yaml +13 -0
- package/content/questions/gotcha.questions.yaml +11 -0
- package/content/questions/init-template.questions.yaml +10 -0
- package/content/questions/init.questions.yaml +41 -0
- package/content/questions/obligations.questions.yaml +17 -0
- package/content/questions/plan.questions.yaml +14 -0
- package/content/questions/refactor.questions.yaml +23 -0
- package/content/questions/reflect.questions.yaml +13 -0
- package/content/questions/remediate.questions.yaml +27 -0
- package/content/questions/restructure.questions.yaml +15 -0
- package/content/questions/rf-mapping.questions.yaml +12 -0
- package/content/questions/rule-scope.questions.yaml +12 -0
- package/content/questions/rule.questions.yaml +12 -0
- package/content/questions/specify.questions.yaml +23 -0
- package/content/questions/update-artifacts.questions.yaml +10 -0
- package/content/questions/update-strings.questions.yaml +14 -0
- package/content/questions/update.questions.yaml +10 -0
- package/content/questions/verify.questions.yaml +9 -0
- package/content/roles/executor.md +18 -0
- package/content/roles/explorer.md +22 -0
- package/content/roles/reviewer.md +23 -0
- package/content/rubrics/enum-vs-union-vs-branded.md +40 -0
- package/content/rubrics/episodic-vs-semantic-boundary.md +37 -0
- package/content/rubrics/error-classification.md +98 -0
- package/content/rubrics/failure-classification.md +111 -0
- package/content/rubrics/negative-filters.md +38 -0
- package/content/rubrics/solid-triggers.md +119 -0
- package/content/rubrics/template-vs-streaming-precedence.md +34 -0
- package/content/rubrics/validation-boundary.md +94 -0
- package/content/rubrics/when-to-create-dsl.md +65 -0
- package/content/rubrics/when-to-create-lib.md +49 -0
- package/content/rubrics/when-to-create-module.md +39 -0
- package/content/rubrics/when-to-evolve-methodology.md +62 -0
- package/content/skills/adr.md +42 -0
- package/content/skills/analyze.md +28 -0
- package/content/skills/clarify.md +28 -0
- package/content/skills/deliver.md +26 -0
- package/content/skills/diagnose.md +42 -0
- package/content/skills/evolve.md +43 -0
- package/content/skills/export-template.md +37 -0
- package/content/skills/generalize.md +31 -0
- package/content/skills/gotcha.md +40 -0
- package/content/skills/init.md +77 -0
- package/content/skills/obligations.md +27 -0
- package/content/skills/plan.md +28 -0
- package/content/skills/policy.md +25 -0
- package/content/skills/promote.md +39 -0
- package/content/skills/protocol.md +41 -0
- package/content/skills/reconcile.md +45 -0
- package/content/skills/refactor.md +79 -0
- package/content/skills/reflect.md +43 -0
- package/content/skills/remediate.md +33 -0
- package/content/skills/restructure.md +46 -0
- package/content/skills/rule.md +43 -0
- package/content/skills/specify.md +28 -0
- package/content/skills/tasks.md +24 -0
- package/content/skills/update.md +58 -0
- package/content/skills/verify.md +29 -0
- package/content/templates/adr.template.md +51 -0
- package/content/templates/evolution-report.template.md +132 -0
- package/content/templates/feature-plan.template.md +84 -0
- package/content/templates/feature-research.template.md +56 -0
- package/content/templates/feature-spec.template.md +86 -0
- package/content/templates/feature-tasks.induced.template.md +91 -0
- package/content/templates/feature-tasks.template.md +82 -0
- package/content/templates/focus.template.md +30 -0
- package/content/templates/gotcha.template.md +31 -0
- package/content/templates/guardrail-runner.template.md +97 -0
- package/content/templates/guardrail.template.md +63 -0
- package/content/templates/learning.template.md +40 -0
- package/content/templates/procedure.template.md +47 -0
- package/content/templates/protocols/p1.md +29 -0
- package/content/templates/protocols/p2.md +28 -0
- package/content/templates/protocols/p3.md +47 -0
- package/content/templates/research.template.md +50 -0
- package/content/templates/session-handoff.template.md +58 -0
- package/content/templates/us.template.md +39 -0
- package/content/tools/gate/core-rules/PLUGIN-13-secrets.sh +36 -0
- package/content/tools/gate/core-rules/PLUGIN-21-code-language.sh +27 -0
- package/content/tools/gate/core-rules/PLUGIN-35-gate-complete.sh +19 -0
- package/content/tools/gate/core-rules/PLUGIN-36-absolute-path.sh +38 -0
- package/content/tools/gate/core-rules/PLUGIN-37-prose-language.sh +56 -0
- package/content/tools/gate/core-rules/PLUGIN-38-parser-marker.sh +82 -0
- package/content/tools/gate/core-rules/PLUGIN-39-frontmatter-ops.sh +325 -0
- package/content/tools/gate/core-rules/PLUGIN-40-dead-reference.sh +74 -0
- package/content/tools/gate/core-rules/README.md +55 -0
- package/content/tools/gate/guardrails.sh +740 -0
- package/content/tools/gate/lib/ratchet.sh +119 -0
- package/content/tools/gate/lib/scope.sh +85 -0
- package/content/tools/gate/ratchet.seed.tsv +1 -0
- package/content/tools/gate/rules/README.md +50 -0
- package/package.json +19 -5
- package/plugin/agy/hooks.json +29 -0
- package/plugin/agy/mcp_config.json +7 -0
- package/plugin/agy/plugin.json +6 -0
- package/plugin/agy/skills/afm-adr/SKILL.md +48 -0
- package/plugin/agy/skills/afm-analyze/SKILL.md +34 -0
- package/plugin/agy/skills/afm-clarify/SKILL.md +34 -0
- package/plugin/agy/skills/afm-deliver/SKILL.md +30 -0
- package/plugin/agy/skills/afm-diagnose/SKILL.md +46 -0
- package/plugin/agy/skills/afm-evolve/SKILL.md +49 -0
- package/plugin/agy/skills/afm-export-template/SKILL.md +43 -0
- package/plugin/agy/skills/afm-generalize/SKILL.md +37 -0
- package/plugin/agy/skills/afm-gotcha/SKILL.md +46 -0
- package/plugin/agy/skills/afm-init/SKILL.md +81 -0
- package/plugin/agy/skills/afm-obligations/SKILL.md +31 -0
- package/plugin/agy/skills/afm-plan/SKILL.md +34 -0
- package/plugin/agy/skills/afm-policy/SKILL.md +29 -0
- package/plugin/agy/skills/afm-promote/SKILL.md +43 -0
- package/plugin/agy/skills/afm-protocol/SKILL.md +45 -0
- package/plugin/agy/skills/afm-reconcile/SKILL.md +49 -0
- package/plugin/agy/skills/afm-refactor/SKILL.md +83 -0
- package/plugin/agy/skills/afm-reflect/SKILL.md +49 -0
- package/plugin/agy/skills/afm-remediate/SKILL.md +39 -0
- package/plugin/agy/skills/afm-restructure/SKILL.md +52 -0
- package/plugin/agy/skills/afm-rule/SKILL.md +49 -0
- package/plugin/agy/skills/afm-specify/SKILL.md +34 -0
- package/plugin/agy/skills/afm-tasks/SKILL.md +28 -0
- package/plugin/agy/skills/afm-update/SKILL.md +64 -0
- package/plugin/agy/skills/afm-verify/SKILL.md +35 -0
- package/plugin/claude-code/.claude-plugin/marketplace.json +15 -0
- package/plugin/claude-code/.claude-plugin/plugin.json +9 -0
- package/plugin/claude-code/.mcp.json +7 -0
- package/plugin/claude-code/agents/afm-executor.md +18 -0
- package/plugin/claude-code/agents/afm-explorer.md +20 -0
- package/plugin/claude-code/agents/afm-reviewer.md +21 -0
- package/plugin/claude-code/hooks/hooks.json +85 -0
- package/plugin/claude-code/skills/adr/SKILL.md +48 -0
- package/plugin/claude-code/skills/analyze/SKILL.md +34 -0
- package/plugin/claude-code/skills/clarify/SKILL.md +34 -0
- package/plugin/claude-code/skills/deliver/SKILL.md +30 -0
- package/plugin/claude-code/skills/diagnose/SKILL.md +46 -0
- package/plugin/claude-code/skills/evolve/SKILL.md +49 -0
- package/plugin/claude-code/skills/export-template/SKILL.md +43 -0
- package/plugin/claude-code/skills/generalize/SKILL.md +37 -0
- package/plugin/claude-code/skills/gotcha/SKILL.md +46 -0
- package/plugin/claude-code/skills/init/SKILL.md +81 -0
- package/plugin/claude-code/skills/obligations/SKILL.md +31 -0
- package/plugin/claude-code/skills/plan/SKILL.md +34 -0
- package/plugin/claude-code/skills/policy/SKILL.md +29 -0
- package/plugin/claude-code/skills/promote/SKILL.md +43 -0
- package/plugin/claude-code/skills/protocol/SKILL.md +45 -0
- package/plugin/claude-code/skills/reconcile/SKILL.md +49 -0
- package/plugin/claude-code/skills/refactor/SKILL.md +83 -0
- package/plugin/claude-code/skills/reflect/SKILL.md +49 -0
- package/plugin/claude-code/skills/remediate/SKILL.md +39 -0
- package/plugin/claude-code/skills/restructure/SKILL.md +52 -0
- package/plugin/claude-code/skills/rule/SKILL.md +49 -0
- package/plugin/claude-code/skills/specify/SKILL.md +34 -0
- package/plugin/claude-code/skills/tasks/SKILL.md +28 -0
- package/plugin/claude-code/skills/update/SKILL.md +64 -0
- package/plugin/claude-code/skills/verify/SKILL.md +35 -0
- package/plugin/opencode/afm/index.js +245 -0
- package/plugin/opencode/afm/tui.js +21 -0
- package/plugin/opencode/agents/afm-executor.md +39 -0
- package/plugin/opencode/agents/afm-explorer.md +92 -0
- package/plugin/opencode/agents/afm-reviewer.md +93 -0
- package/plugin/opencode/skills/afm-adr/SKILL.md +48 -0
- package/plugin/opencode/skills/afm-analyze/SKILL.md +34 -0
- package/plugin/opencode/skills/afm-clarify/SKILL.md +34 -0
- package/plugin/opencode/skills/afm-deliver/SKILL.md +30 -0
- package/plugin/opencode/skills/afm-diagnose/SKILL.md +46 -0
- package/plugin/opencode/skills/afm-evolve/SKILL.md +49 -0
- package/plugin/opencode/skills/afm-export-template/SKILL.md +43 -0
- package/plugin/opencode/skills/afm-generalize/SKILL.md +37 -0
- package/plugin/opencode/skills/afm-gotcha/SKILL.md +46 -0
- package/plugin/opencode/skills/afm-init/SKILL.md +81 -0
- package/plugin/opencode/skills/afm-obligations/SKILL.md +31 -0
- package/plugin/opencode/skills/afm-plan/SKILL.md +34 -0
- package/plugin/opencode/skills/afm-policy/SKILL.md +29 -0
- package/plugin/opencode/skills/afm-promote/SKILL.md +43 -0
- package/plugin/opencode/skills/afm-protocol/SKILL.md +45 -0
- package/plugin/opencode/skills/afm-reconcile/SKILL.md +49 -0
- package/plugin/opencode/skills/afm-refactor/SKILL.md +83 -0
- package/plugin/opencode/skills/afm-reflect/SKILL.md +49 -0
- package/plugin/opencode/skills/afm-remediate/SKILL.md +39 -0
- package/plugin/opencode/skills/afm-restructure/SKILL.md +52 -0
- package/plugin/opencode/skills/afm-rule/SKILL.md +49 -0
- package/plugin/opencode/skills/afm-specify/SKILL.md +34 -0
- package/plugin/opencode/skills/afm-tasks/SKILL.md +28 -0
- package/plugin/opencode/skills/afm-update/SKILL.md +64 -0
- package/plugin/opencode/skills/afm-verify/SKILL.md +35 -0
- package/README.md +0 -3
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: op
|
|
3
|
+
description: Refines a doc that guided the agent wrong, using evidence from the live session and the project's sessions since the last cycle, and proposes the full cycle when that evidence outgrows one doc.
|
|
4
|
+
load: warm
|
|
5
|
+
writes: ["docs/evolution/*.md"]
|
|
6
|
+
composes: []
|
|
7
|
+
ancestors: the *Reflect* operator from Autogenesis (arXiv 2604.15034 — execution traces build causal hypotheses of failure), composed with the *MetaReflect* step of MetaReflection (arXiv 2405.13009 — self-reflection on failure is **episodic memory**).
|
|
8
|
+
---
|
|
9
|
+
# Sub-flow: behavioral self-reflection on the docs (`reflect`)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
> **Form** — effect: edits + `evolution/<date>-NNN` + `sessions/<...>` + candidates for `guardrails/` · trigger: `afm reflect`, composition, **cadence** · precondition: friction lived in the session · composed by: `evolve` 1.2, `deliver` 4.D · proposes: `afm evolve` (§ 5, à-la-carte only) · **degree of freedom: medium**
|
|
13
|
+
|
|
14
|
+
Triggers: `afm reflect`. Also natural language about a **doc that guided badly**. Examples: "this rule is ambiguous", "the doc led me the wrong way". Also: "reflect on where the doc failed me", "the docs are not helping me".
|
|
15
|
+
|
|
16
|
+
> **Target = this project's local docs (`<consumer>/docs/`), never the plugin.** `reflect` refines the docs **materialized in this repo**. It never touches the canonical framework (the bundled content, bright line #7). An improvement that fits any instance only gets **recorded** through `afm promote` (a finding with evidence). It never gets applied. See [`evolve.md § The target of evolution`](./evolve.md).
|
|
17
|
+
>
|
|
18
|
+
> **Mechanism, not conductor.** `reflect` is one of the mechanism skills in the self-evolution cycle. `evolve` is the orchestrator that composes it. `reflect` runs **à-la-carte** (this doc, with its own gate). Or it runs inside the `evolve` cycle, which suppresses the own gate and consolidates results — see `evolve.md § Suppression contract`.
|
|
19
|
+
>
|
|
20
|
+
> Reflect(session_trace) -> φ_b:
|
|
21
|
+
> 1. scan session_trace for a point where a core doc guided the agent badly
|
|
22
|
+
> 2. φ_b := (symptom-lived, causal-status-of-the-doc, mechanism)
|
|
23
|
+
> # both a doc passage AND a session event MUST be cited — else φ_b is not evidence
|
|
24
|
+
> 3. MetaReflect(φ_b) -> proposal:
|
|
25
|
+
> a. rival := "the doc was clear AND correct — I am the one who did not follow it"
|
|
26
|
+
> b. if rival holds -> discard: φ_b stays an observation, no proposal
|
|
27
|
+
> c. else -> proposal := a rewrite that makes the doc passage more assertive and clear
|
|
28
|
+
> 4. Instructiveness := proposal disambiguates, adds a missing trigger, or resolves a
|
|
29
|
+
> contradiction — it never adds knowledge the doc did not already carry
|
|
30
|
+
>
|
|
31
|
+
> This materializes, with no new principle, #1 (knowledge lives in the doc — reflect refines the doc's *instructiveness*, not memory), #6 (self-verify, then report — the gate is a load-bearing residue), and #8 (earned question or suggestion). See [`../PRINCIPLES.md`](../PRINCIPLES.md).
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## What `reflect` is / is not
|
|
36
|
+
|
|
37
|
+
**It is:** the reflection on where the **local docs underperformed as a harness** during real work.
|
|
38
|
+
|
|
39
|
+
Examples: an ambiguous rule applied wrong, a doc that misled, a section that did not guide. Also a contradiction lived in practice, or the user correcting the agent against the doc.
|
|
40
|
+
|
|
41
|
+
The evidence is **the trajectory of the live session plus the project's sessions since the last cycle** — the agent stumbled. It is not the static artifact. It produces **(a)** proposals to make the doc **more assertive and clear**. This refines what already exists. It also produces **(b)** suggestions for the human in the loop.
|
|
42
|
+
|
|
43
|
+
**It is NOT:**
|
|
44
|
+
- `reconcile` (code→docs, **additive**: the agent learns a new fact, then proposes a new gotcha or rule). `reflect` is **docs→docs refinement**: an existing doc guided badly, so it proposes making that doc assertive. *It never adds knowledge. It only improves the instructiveness of what is already there.*
|
|
45
|
+
- `diagnose` (a **static** scan of the filesystem and git). `diagnose` finds dead references, drift, a stillborn trigger. `reflect` is **behavioral**: only the agent sees its own stumble, and no `grep` reveals it. These are the two sides of the Self-Harness signature φ. `diagnose` gives `c` (mechanical cause). `reflect` gives `q/m` (causal status plus mechanism of the behavior).
|
|
46
|
+
- `generalize` (merges many similar gotchas into one abstract rule). `reflect` targets the **clarity of one specific doc** that failed. It does not consolidate many docs.
|
|
47
|
+
- An editor of the canonical plugin. **No skill is one** (absolute boundary #7). What generalizes becomes a finding, and `promote` records it. `reflect` only touches the instance (`<consumer>/docs/`).
|
|
48
|
+
- A pretext to **weaken a rule because it embarrassed me**. See the mandatory self-critique in § 2: "a violated rule is not a wrong rule."
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Pre-check
|
|
53
|
+
|
|
54
|
+
1. **Does `<consumer>/docs/.afm-version` exist?** If not, stop. Suggest `afm init` or `afm refactor` first.
|
|
55
|
+
2. **Does `afm preflight` exit 0?** A non-zero exit says why: the docs are not bootstrapped, the bundled content does not resolve, or the pin does not match. Report it to the user. Do not fall back silently.
|
|
56
|
+
3. **Capture the events lived in the evidence window: the live session plus the project's sessions since the last cycle.** The `reflect` trigger is in-session — see `interview/triggers.md` — but the evidence is wider. Run `afm sessions --since reflect --json` (it lists the project's sessions in every supported harness; `source` is `record`, `harness` or `both`) (pass the live session id with `--exclude <id>`) for the window, then `afm sessions signals --since reflect --json` for its deterministic signals: user turns, with a `correction` flag set by a fixed marker list, tool-error groups, AFM injection sizes and repeated reads. The signals are a heuristic that points at friction. You judge them. The command skips sessions whose record already names a `reflection:` (pass `--include-covered` to read them again), groups tool errors by tool and command, carries the repeated prompt rituals of the last 30 days under `repeatedPrompts` (`--repeat-window <N>d`; `--scope user` clusters them across every project of the user, listing the projects of each cluster), and gives every signal a `fingerprint` and a `status`: `new`, `resolved` (an evolution report listed its fingerprint in `resolves:`) or `regressed` (the signal recurs after that report, so the earlier fix did not hold).
|
|
57
|
+
- **Weight.** The live session is read directly, so one signal there is enough evidence. A signal from a past session counts only when it repeats across 2 or more sessions, is an explicit correction, or is `regressed`. A `resolved` signal is not a finding.
|
|
58
|
+
- **Order.** Take the `regressed` signals first: each one says an earlier fix did not hold, so revisit that report's change before proposing a new one.
|
|
59
|
+
- **Repeated prompts.** A `repeatedPrompt` signal is a first-class finding: the user types the same thing again and again. Propose the artifact that stops the retyping (a procedure, a preset in a skill, an op step, or a config default), citing the cluster sample and its sessions. A cluster that carries `suggests: procedure` (the `[runbook?]` marker in text mode) is a run of operational verbs, so propose it as an `afm new procedure` in the project where it repeats, with the steps in the order the user asks them.
|
|
60
|
+
- **Read-only bound.** Open a raw transcript only when a signal needs context, and read only the turns around its `ts`. Note which core docs the agent read or followed, and where they guided badly. With no lived event in the window, no signal, and no clear symptom, stop: there is no reflection to do. Report "no doc friction observed in the window", then **record the outcome**: run `afm cadence close --arm reflect --reason "no doc friction observed"`. That writes the durable record that resets the cadence counter, so the same task and deliverable counts do not block the next Stop again. Then end. Reflection with no behavioral evidence is the agent inventing a disease. Rule #5 forbids this.
|
|
61
|
+
|
|
62
|
+
> **If the operator would rather skip the reflection**, run `afm cadence skip --session <id> --reason "<text>"` (the id is the one the Stop message gives; `--session` is required). It records the skip as debt in the state store and does not reset the counter. Never edit the session store by hand.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 1. Behavioral evidence collection (≈ *Reflect* — traces → hypotheses)
|
|
67
|
+
|
|
68
|
+
Core docs include `afm.md`, `ach.md`, `prd.md`, `ust.md`, the rules under `rules/`, the gotchas under `gotchas/`, and the rubrics. Find each point in the window (the live session and the signals of the earlier sessions) where a core doc guided badly. Record a **behavioral signature** for it: `φ_b = (symptom-lived, causal-status-of-the-doc, mechanism)`.
|
|
69
|
+
|
|
70
|
+
- *symptom-lived* — what happened, with an anchor. Example one: the agent applied rule N of `afm.md § 3` wrong, and had to re-read it twice. The user then corrected the agent against it, in `<file>`. Example two: the agent followed `ach.md § 3.1`, and the part it named no longer existed. Example three: two docs gave opposite guidance on the same task.
|
|
71
|
+
- *causal-status-of-the-doc* — was **the doc** causally implicated? This slot is the *causal status*, not "who is to blame."
|
|
72
|
+
- *mechanism* — **why** the doc produced the stumble. Options include an ambiguous rule that reads two ways, or a rule with no executable trigger. Such a rule fails a 0/1 check. Other options: an outdated example, guidance buried where nobody finds it, or a contradiction with another doc.
|
|
73
|
+
|
|
74
|
+
**Golden rule:** every signature cites **the doc passage** (`file:section`). It also cites **the session event** as `session:<id>@<ts>` — what the agent did, or what the user said. The id and the timestamp come from the live session or from a signal of `afm sessions signals`. Without both sides, it is not evidence. It is only an impression.
|
|
75
|
+
|
|
76
|
+
### 1.2 — The second sweep: what I corrected by hand more than once
|
|
77
|
+
|
|
78
|
+
Beyond a doc that guided badly, `reflect` sweeps the window for **an error caught by non-mechanical review, and that came back**. Look for the same defect type fixed in two places. Or an ad-hoc `grep` run again, or a review repeated because no command did it for the agent.
|
|
79
|
+
|
|
80
|
+
Each occurrence becomes a **guardrail candidate**: `(the defect, how many times in the window, how the agent caught it by hand)`. The promotion gate is the rubric's, from `rubrics/failure-classification.md`. It needs 2 or more occurrences, counted across the sessions of the window, or one explicit user correction.
|
|
81
|
+
|
|
82
|
+
> **Why this lives in `reflect`, and not only in `remediate`.** `remediate` consumes the failure events of the state store (`afm failures promotable`). Those only record a failure recognized by a **terminal external signal** — a red test, a nonzero `tsc` result, a nonzero command result. An error the agent caught itself, while reading the diff, **never reaches those events**. It gets fixed before it becomes a signal. This is the most expensive class of error. Its cost is the agent's own context, invisible on the ledger. `reflect` is the only point in the cycle that sees it, because its evidence is the lived trajectory alone, across the project's sessions of the window.
|
|
83
|
+
|
|
84
|
+
Before proposing a candidate, run the same **surface discovery** as `ops/remediate.md` step 3.5. Check the linter, type-check, CI, and any git hooks the project already has. A candidate with no surface to land on stays an observation. It does not become a proposal.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 2. Self-critique: doc-wrong vs. agent-non-conformant (mandatory filter)
|
|
89
|
+
|
|
90
|
+
Before proposing any refinement, list the **mandatory rival hypothesis** for **each** signature. State it this way:
|
|
91
|
+
|
|
92
|
+
*"the doc was clear and correct — I am the one who did not follow it."*
|
|
93
|
+
|
|
94
|
+
Only a finding that survives this filter becomes a refinement proposal.
|
|
95
|
+
|
|
96
|
+
- **Doc genuinely ambiguous or wrong**: it reads two defensible ways, or an outdated example is proven. It may also contradict another doc directly. This is addressable, so it becomes a proposal (§ 3).
|
|
97
|
+
- **Agent non-conformant** — the doc was clear, and the error was the agent's. **This is not a doc finding.** At most it becomes an observation. Example: "I applied rule N wrong even though it was clear." It never becomes a proposal to weaken the rule.
|
|
98
|
+
|
|
99
|
+
> **Guardrail (same as `evolve`'s): a violated rule is not a wrong rule.** Downgrading or weakening a hard rule needs proof that the rule is *wrong* — a false positive, impossible to satisfy, or an obsolete intent proven by git. It is not enough that the rule slowed the agent down. Without that proof, the rule stays. The finding is "it was me." Without this filter, `reflect` would let the agent rewrite its own restraints — a self-serving loop.
|
|
100
|
+
|
|
101
|
+
Also apply the **addressability filter** from Self-Harness. Friction with no editable doc surface stays an observation in the report. Examples: an external limit, a hard library, an undecided product choice. It never becomes a patch.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 3. Proposal: make the doc more assertive + suggestions for the human (≈ *MetaReflect*)
|
|
106
|
+
|
|
107
|
+
For each addressable finding, follow the **shared proposal discipline** of the evolution cycle: `evolve.md § Proposal discipline (shared)`. Do not duplicate that procedure here. Read it there and follow it — the numbered steps live only there. There are two output types.
|
|
108
|
+
|
|
109
|
+
- **(a) Instructiveness refinement** — the core product, the "distill into a more assertive instruction" from MetaReflection. **Refine what exists. Do not create a new doc.** Retrieval-before-create is literal here, and it is the antidote to inflation. Actions include:
|
|
110
|
+
- Rewrite the ambiguous passage so it reads only one way.
|
|
111
|
+
- **Add the executable trigger** that was missing. A rule with no `*Verification:*` 0/1 gains a trigger, or moves down to § 1.3 as a principle (rule #3).
|
|
112
|
+
- Disambiguate a contradiction, or itemize an ADR for it.
|
|
113
|
+
- Move buried guidance, or point to it from a clearer spot.
|
|
114
|
+
- **(c) Guardrail candidate** (from § 1.2) — the defect the agent corrected by hand 2 or more times in the window. State the existing surface where the check would land and the estimated cost. This goes to the gate as an **installation proposal**. Installing writes outside `docs/`, so it is always bucket (b). It never auto-applies, and if approved, it materializes `docs/guardrails/<slug>.md` with `afm new guardrail`, with the mandatory `## What would refute this`. Then propose the config edit to the operator.
|
|
115
|
+
- **(b) Suggestion for the human** — for friction a text edit cannot fix, but that is still a real signal. Examples: "rule N cost you 3 corrections in the window. Worth rethinking the approach, not just the text." Or: "that old `[NEEDS CLARIFICATION:]` keeps blocking every session. Do you want to decide?" This goes to the report as a recommendation. It is not an edit.
|
|
116
|
+
|
|
117
|
+
An edit can touch a `*Verification:*` command in `afm.md § 3`. Or it can touch a path the hooks parse, like a gotcha's `trigger_path` key. Either edit is **always bucket (b), load-bearing**. It never auto-applies, for the same reason as `evolve`: narrowing your own oversight carries more weight than convenience.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 4. Own gate (à-la-carte) — suppressed under `evolve`
|
|
122
|
+
|
|
123
|
+
À-la-carte, `reflect` opens **its own gate** for bucket (b) refinements. It runs `afm ask reflect`, item by item (one `--scope <item-slug>` per refinement, `questions/reflect.questions.yaml`), recommendation-first. Each question carries the evidence — the signature φ_b — plus a recommendation. It also states "what changes if this is wrong" (earned #8).
|
|
124
|
+
|
|
125
|
+
The suggestions for the human, output (b) from § 3, enter **the same gate as informational items**. They are not edits. They are recommendations the user can accept by opening another skill. Restorative (a) items are listed only — seen, not asked.
|
|
126
|
+
|
|
127
|
+
> Under the `evolve` cycle, this gate is **suppressed**. The findings move up to the orchestrator's single gate — the suppression contract. This is the same mechanism `deliver` uses to suppress the per-artifact `afm ask`.
|
|
128
|
+
|
|
129
|
+
After approval, apply the change through the writing ops — `rule.md` or `gotcha.md`. Suppress only their own `afm ask`. **Postcondition:** `afm doctor --json`, `afm index --check` and `afm detect --for <file>` over the touched doc must preserve the format the hooks parse. If not, the agent rolls back and reports it. It must also pass the green boundary check from the two branches in [`evolve.md § Phase 4.3`](./evolve.md#phase-4--application--postconditions--commit-κ-applied). That check confirms the plugin was never touched.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 5. Record + session closing + handoff
|
|
134
|
+
|
|
135
|
+
1. **Materialize or append** the reflection bundle in `<consumer>/docs/evolution/<date>-NNN.md`. Create it with `afm new evolution-report --mechanism reflect` (fix findings with `afm lint --fix`). Include the φ_b signatures (each with its `session:<id>@<ts>` cite), list in `resolves:` the fingerprints of the signals this cycle handled (an applied or approved refinement; the next window reads it to tell `resolved` from `regressed`), and what got self-critiqued as "it was me" (anti-oscillation memory). Also include the refinements approved or rejected, and the suggestions for the human. À-la-carte, `reflect` generates or closes this report on its own. Under `evolve`, it feeds the cycle's report instead.
|
|
136
|
+
|
|
137
|
+
> **The report name is `YYYY-MM-DD-NNN.md` and its frontmatter MUST carry `mechanism: reflect`.**
|
|
138
|
+
> Three mechanisms write into `docs/evolution/`, and each one's cadence window is "since MY last
|
|
139
|
+
> report". A report with no `mechanism:` is invisible to every window, and an ordinal-first name
|
|
140
|
+
> makes the selector order by ordinal before date. Both were live defects until 3.13.0.
|
|
141
|
+
|
|
142
|
+
> **À-la-carte, fill only the applicable sections** of the template: behavioral findings, buckets, rejected or reverted items. Before/after vital signs and cooldown belong to the cycle. Leave them empty. Do not invent values. **There is no separate "light" template** — rule 34 requires a single source.
|
|
143
|
+
|
|
144
|
+
1.5. **Close the session handoff.** The `session.stop` hook writes its skeleton, which is where usage telemetry is born, into the state store (under `AFM_HOME`, never the repository) and names the record in its output. The hook is 0-LLM and only knows the mechanical part. The judgment is the agent's. Fill in that record:
|
|
145
|
+
|
|
146
|
+
- **`name:`** — a human label for the session, replacing the dominant subtree's mechanical slug. The **record's id does not change**. It is the dedup key, and links already point to it.
|
|
147
|
+
- **`## what was asked`** — the agent's own reading of the user's request, including where that reading changed mid-session. This is not a transcript. It is the interpretation that guided the work.
|
|
148
|
+
- **`## how it was executed`** — how AFM was used: which ops ran, which rules fired, and where the harness helped. Also note where it got in the way. This is the data no other artifact has. Git records what changed, not how the agent used the method.
|
|
149
|
+
- **`## afm_findings`** — what generalizes to the plugin, in the format of `ops/promote.md` step 4, with `evidence:`. An explicit empty result is a valid result.
|
|
150
|
+
- **`reflection:`** — the link to the `docs/evolution/<date>-NNN` file from step 1. Fill it for **every session record the window covered**, not only the live one, with `afm sessions mark <id…> --reflection docs/evolution/<file>.md` (never by editing the store; a covered record is skipped by the next `afm sessions signals`), so the next window starts after them. This field replaces a `docs_findings` field. What `reflect` found **and fixed** in the local docs already lives there. Duplicating it would be the inflation `reflect` itself forbids.
|
|
151
|
+
|
|
152
|
+
**No session with real work means no record**, because the hook writes nothing. In that case, this step is a no-op. It is not a reason to create one. The handoff block (`state:`, `open_questions`, `next_steps`) stays episodic. `state: consumed` marks **the handoff** as read, not the record itself as dead. See `rubrics/episodic-vs-semantic-boundary.md` for this dual-tier rule.
|
|
153
|
+
2. **Does it generalize?** If the friction fits any instance, record it through `afm promote`. For example, every instance might share the same ambiguous rule. Attach evidence. Never apply it directly (rule #7). The destination is the `afm_findings` field of the session record from step 1.5. It is the same place, not two.
|
|
154
|
+
3. **Escalate to `afm evolve` when the findings meet the cycle discriminant**. Check the findings collected in §§ 1-2 against the criteria `rubrics/when-to-evolve-methodology.md § 1` already defines for the cycle path. Do not restate those criteria here (rule 34) — read them there. When both hold, propose `afm evolve` to the user with the φ_b bundle from §§ 1-2 as the Phase 1.2 seed. This is always a proposal, never an auto-invocation. `reflect` PROPOSES — the user invokes it (#7, #8).
|
|
155
|
+
|
|
156
|
+
> **Recursion guard.** This step fires only when `reflect` runs à-la-carte. Under `evolve`, Phase 1.2 composes only `reflect.md §§ 1-2` — this step is never reached from inside the cycle. See [`evolve.md § Suppression contract`](./evolve.md#suppression-contract-the-honest-dry-guarantee).
|
|
157
|
+
4. **Handoff to `reconcile`**: watch, in the following sessions, whether the refinement actually cut the friction. A doc refinement has no held-out set, so the validation is future behavior, observed cross-session and long-term. **Do not confuse this with the in-task reflection** of `core/afm.md § 5.1` — short-term Reflexion, ephemeral.
|
|
158
|
+
|
|
159
|
+
There, the signal is the task's own test or `tsc` result. The "re-run" is literal and immediate: GREEN reruns in the same episode. Here, the signal is a doc that guided badly this session, and the product is a refinement of instructiveness. These are the two ends of Reflexion: short-term episodic (in-task) versus long-term, distilled into a doc (`reflect`). One does not replace the other.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Suppression contract (back-pointer)
|
|
164
|
+
|
|
165
|
+
`reflect` **reuses** three things from `evolve.md`: the proposal discipline, the bucket partition, and the postconditions. It reads and follows them, and does not copy them. It also reuses the writing ops `rule.md` and `gotcha.md`, suppressing only their per-artifact `afm ask`, which moves up to the gate. When run **inside** `evolve`, the gate in § 4 is suppressed too — it moves up to the single gate. The authoritative table lives in `evolve.md § Suppression contract`.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Anti-patterns
|
|
170
|
+
|
|
171
|
+
- ❌ **Reflecting with no lived event** — for example "this rule seems ambiguous" with no actual stumble in the window. That is an impression, not evidence (rule #5). No friction observed: report "no friction" only when the whole window has no signal, then run `afm cadence close --arm reflect --reason "no doc friction observed"` and stop.
|
|
172
|
+
- ❌ **Weakening a rule that embarrassed me**. A violated rule is not a wrong rule. The "it was me" hypothesis is mandatory, and it kills the refinement whenever the doc was clear.
|
|
173
|
+
- ❌ **Adding new knowledge** — that is the job of `reconcile`, `gotcha`, or `rule`. `reflect` only refines the instructiveness of what already exists. Output (c) is not an exception. It converts repeated manual analysis into a check. It adds no new knowledge, because the knowledge was already in the manual correction.
|
|
174
|
+
- ❌ **Proposing a guardrail from a single occurrence**. The same rubric gate applies here: 2 or more times, or one user correction. A gate born from a single case becomes a dead constraint (rule #5).
|
|
175
|
+
- ❌ **Creating a new doc to "clarify"** — retrieval-before-create applies. Refine the passage that failed. Do not create a parallel doc, because that causes inflation, the opposite of the goal.
|
|
176
|
+
- ❌ **Classifying a trigger or hook-path edit as auto-applicable**. It is always bucket (b). It narrows the agent's own oversight.
|
|
177
|
+
- ❌ **Editing the bundled content** — absolute boundary #7. Generalization gets **recorded** through `promote`. It never gets applied. See the boundary postcondition in `evolve.md § Phase 4.3`.
|
|
178
|
+
- ❌ **Transcribing the session** in the session record — the transcript already exists, and `session_ref` (harness and id) points to it. The two timeline sections hold **interpretation** — what the agent understood, how it used AFM — not a log. Transcribing adds inflation and a reading cost.
|
|
179
|
+
- ❌ **Pasting a credential into the narrative**. Quoting the command run is the common leak path. Write the command with the secret redacted. Hard rule 13 covers it.
|
|
180
|
+
- ❌ **Reading a raw transcript when the signals suffice**, or **quoting text that did not pass the redaction**. `afm sessions signals` already extracts and redacts what the cycle needs. A raw read costs context and risks a secret. Quote only signal text. If a signal is not enough, say so in the report instead of opening the transcript.
|
|
181
|
+
- ❌ **Confusing this with `diagnose`** — `reflect` does not run the static 7-axis scan. Its evidence is behavioral. For the mechanical sweep of the instance, use `afm diagnose` instead.
|
|
182
|
+
- ❌ **Reaching § 5 step 3 while running under `evolve`** — the recursion guard. `evolve` Phase 1.2 composes only `reflect.md §§ 1-2`. The escalation step is scoped out of that composition on purpose. Escalating from inside the cycle that is already running `reflect` would be `reflect` calling back into its own caller.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: op
|
|
3
|
+
description: Turns a failure that repeats into a durable artifact, recognized by an external signal.
|
|
4
|
+
load: warm
|
|
5
|
+
writes: ["docs/procedures/*.md", "docs/learnings/*.md", "docs/guardrails/*.md"]
|
|
6
|
+
composes: []
|
|
7
|
+
ancestors: "CRITIC (arXiv 2305.11738) — failure recognition is anchored in an **external tool or signal**. Self-critique with no tool degrades (PRINCIPLES #3). This op complements the short in-task loop in `afm.md § 5.1` (ephemeral Reflexion, cap 2). `remediate` is the **long loop**: when a failure crosses the § 5.1 terminal (non-transient) and recurs, it becomes a **durable** remediation."
|
|
8
|
+
---
|
|
9
|
+
# Sub-flow: remediation of a recognized failure (`remediate`) — CRITIC loop
|
|
10
|
+
|
|
11
|
+
> **Form** — effect: `guardrails/`, `procedures/`, or `learnings/` · trigger: `afm remediate`, composition · precondition: a failure in the state store that `afm failures promotable` lists · composed by: `evolve` 1.3, `reconcile` · **degree of freedom: medium**
|
|
12
|
+
|
|
13
|
+
Triggers: `afm remediate`.
|
|
14
|
+
It also triggers on natural language that asks to **resolve a failure for good**.
|
|
15
|
+
Example phrases:
|
|
16
|
+
|
|
17
|
+
- "this failed again, let's fix it for real"
|
|
18
|
+
- "make a runbook for this"
|
|
19
|
+
- "record this lesson for the next agents"
|
|
20
|
+
- "why do I keep getting this wrong?"
|
|
21
|
+
|
|
22
|
+
> **Installing a guardrail uses one procedure.** When the rubric classifies the failure as *mechanizable* and the target is `docs/guardrails/`, follow [`rule.md` § Install the gate](./rule.md) — it covers discovery of the surface the project already runs, the runner built from [`../templates/guardrail-runner.template.md`](../templates/guardrail-runner.template.md), **measuring HEAD before turning the gate on** (a gate that starts red gets turned off the next day), measured cost, doc-runner sync, and recording with `origin: recurring-failure`. This op does not repeat those steps (rule 34): the origin differs, but the install path is the same.
|
|
23
|
+
|
|
24
|
+
> **Target = this project's local docs (`<consumer>/docs/`), never the plugin.** Like every AFM write family, `remediate` writes to `<consumer>/docs/` (guardrails/procedures/learnings) and **proposes** — the human approves (#6). No op writes to the plugin: `afm promote` only records a finding for it.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## What `remediate` is / is not
|
|
29
|
+
|
|
30
|
+
**Is:** the loop **recognize → understand/classify → remediate** over the failures the failure-capture hook recorded in the state store (`afm failures promotable` lists the signatures that recurred).
|
|
31
|
+
It reads the failures that are still open: not closed by a record or by `afm failures close`.
|
|
32
|
+
It classifies each one using [`../rubrics/failure-classification.md`](../rubrics/failure-classification.md).
|
|
33
|
+
Then it **proposes** the correct durable artifact: **guardrail** (mechanizable — takes precedence), **procedure** (mechanical), or **learning** (conceptual).
|
|
34
|
+
Gate #5 and the negative filters control this step.
|
|
35
|
+
|
|
36
|
+
**Is not:**
|
|
37
|
+
- A new failure **detector**. The `afm.md § 5.1` terminal recognizes failures (external signal). `remediate` consumes what was already recorded.
|
|
38
|
+
- The short in-task loop (`§ 5.1`). That loop retries GREEN right away (ephemeral). `remediate` runs cross-turn and cross-session (durable).
|
|
39
|
+
- A plugin editor (#7) or an auto-applier (#6 — it proposes, the human approves).
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Pre-check
|
|
44
|
+
|
|
45
|
+
1. **Does `<consumer>/docs/.afm-version` exist?** If not, stop and suggest `afm init` or `afm refactor`.
|
|
46
|
+
2. **Is there an open failure?** Run **`afm failures promotable`**. It lists each `sig=` that recurred (twice or more) with its `count`, `first` and `last` date, minus those already closed. With `no failure is promotable`, and with no explicit user correction to record, report "nothing to remediate" and stop.
|
|
47
|
+
An empty result is a valid outcome — do not invent a failure.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Procedure
|
|
52
|
+
|
|
53
|
+
1. **Recognize (already done — consume the record)**.
|
|
54
|
+
Each failure is an event in the state store (`~/.afm/state/<project>/`, never the repository), keyed by `sig=<signature>` (the recurrence key).
|
|
55
|
+
The failure-capture hook writes it, or the `§ 5.1` terminal does, or the agent does when it records an explicit user correction.
|
|
56
|
+
The record carries an **external signal** (oracle plus command plus output) and a `task/feature`.
|
|
57
|
+
A failure with no external signal does not exist (CRITIC).
|
|
58
|
+
Do not invent one.
|
|
59
|
+
|
|
60
|
+
2. **Promotion gate (#5 + negative-filters)**. For each `open` failure, decide whether it becomes an artifact now:
|
|
61
|
+
- **Explicit user correction → promote at count 1** (the user is the oracle).
|
|
62
|
+
- **Mechanical → requires recurrence:** the `sig=` must appear in `afm failures promotable` (its `count` is 2 or more).
|
|
63
|
+
- **Transient → do not promote:** the § 5.1 retry resolved it, or no durable antidote exists.
|
|
64
|
+
Also reject a claim that dies once you fix the root cause — "tool X was broken" is a fossil.
|
|
65
|
+
Close it with `afm failures close --sig <sig> --as transient` and move on. A closed signature stops counting: only failures after the close are counted again.
|
|
66
|
+
This is the negative filter — Phase 4 formalizes the checklist.
|
|
67
|
+
- A failure that does not clear the gate stays open (waits for recurrence). It becomes nothing yet.
|
|
68
|
+
|
|
69
|
+
3. **Classify (executable discriminator)** by applying the `failure-classification.md` rubric to failures that passed the gate.
|
|
70
|
+
The first question is the **precedence** question: *can a 0/1 check detect this with no judgment call*?
|
|
71
|
+
If yes, the target is **guardrail**.
|
|
72
|
+
A document that relies on memory loses to a gate that fires on its own.
|
|
73
|
+
If no, choose between two targets: **procedure** is a repeatable sequence with 0/1 gates and a start trigger.
|
|
74
|
+
**Learning** is a conceptual lesson, valuable for its cause.
|
|
75
|
+
|
|
76
|
+
3.5. **Read the mechanical surface the project already has**.
|
|
77
|
+
Do this before you propose a guardrail, never before.
|
|
78
|
+
That way you do not pay for the read when nobody needs it.
|
|
79
|
+
Find out what **already runs** in this repo:
|
|
80
|
+
|
|
81
|
+
- linter config (`eslint*`, `biome*`, `ruff*`, `.golangci*`, or the stack's equivalent).
|
|
82
|
+
- type-check (`tsconfig.json`, `mypy.ini`, `go vet`).
|
|
83
|
+
- CI (`.github/workflows/*`, `.gitlab-ci.yml`).
|
|
84
|
+
- git hooks (`.husky/`, `.git/hooks/`, `lefthook*`, `pre-commit`).
|
|
85
|
+
- verification scripts already versioned (`test/`, `scripts/`, `Makefile`, `package.json` scripts).
|
|
86
|
+
|
|
87
|
+
The proposal **extends what exists**. A new tool is a **last resort**.
|
|
88
|
+
State it explicitly, with its cost declared.
|
|
89
|
+
A gate that needs one more tool often costs more than the error it catches.
|
|
90
|
+
If nothing mechanical exists in the project, that gap is the finding.
|
|
91
|
+
Propose the minimal surface, not the complete one.
|
|
92
|
+
|
|
93
|
+
> **Context economy is the point.** The failure that triggered the guardrail used to be caught by non-mechanical analysis — reading, ad-hoc `grep`, review. That costs context **every time the code is touched**. A check costs once. This is the economic case for the precedence target, and it applies to both the human and the agent.
|
|
94
|
+
|
|
95
|
+
> **Red on the old code.** Before you accept any assertion that guards the fix (a guardrail check, a regression test), run it against the old code: `git show HEAD:<file>` or the parent commit. It MUST fail there. A regression test that passes on the old code proves nothing. If it passes, the assertion does not catch the failure: rewrite it before you propose it.
|
|
96
|
+
|
|
97
|
+
4. **Propose the artifact (a delta, never a rewrite — rule 17)**.
|
|
98
|
+
- **Guardrail** → new `docs/guardrails/<slug>.md`, written by `afm new guardrail <slug> --origin recurring-failure --surface <surface> --cost <low|medium|high> --description "..."` (the generator fills the frontmatter from the template; fix findings with `afm lint --fix`).
|
|
99
|
+
The `origin` key cites the `sig=`, and the `## What would refute this` section is **mandatory**.
|
|
100
|
+
Installing the check (editing the linter config, the CI workflow, or a git hook) writes outside `docs/`.
|
|
101
|
+
Because of that, the agent **proposes it to the operator**.
|
|
102
|
+
It offers surface options — linter, CI, git hook, or free text — and never applies the check itself.
|
|
103
|
+
Until the operator installs it, the `installed_on` key stays `[TBD]`.
|
|
104
|
+
- **Procedure** → new `docs/procedures/<slug>.md`, written by `afm new procedure <slug> --fires-on <event|file-shape> --description "..."`.
|
|
105
|
+
The `origin` key cites the `sig=` value(s) for traceability (**hard rule 19**).
|
|
106
|
+
The folder appears on demand, mirroring `adr/`.
|
|
107
|
+
- **Learning** → new `docs/learnings/<slug>.md`, written by `afm new learning <slug> --fires-on file-shape --trigger-path "<glob>" --description "..."`. The `trigger_path` key uses a path (for injection through the pre-edit hook). The `origin` key cites the `sig=`.
|
|
108
|
+
- Before creating, **`grep` for an equivalent** (retrieval-before-create). If a guardrail, procedure, or learning already covers this `sig=`, **update it** (append or update-in-place) instead of duplicating it. If 2 or more learnings converge, suggest `afm generalize`.
|
|
109
|
+
|
|
110
|
+
**Gate (à la carte).** Show the evidence (the `sig=`, the count, the oracle output) and the proposed delta, then run `afm ask remediate --scope <sig>`. The `artifact` question confirms the target with the classification as the recommendation (`guardrail`, `procedure`, `learning`, or `not now`). For a guardrail, the `surface` question asks where the check is installed (linter, CI, git hook, or free text). The scope is the `sig=` turned into a slug (lowercase words joined by `-`, starting with a letter), so each failure keeps its own answers.
|
|
111
|
+
|
|
112
|
+
5. **Close the failure**.
|
|
113
|
+
Once the agent proposes the artifact and the user approves it, close the signature: `afm failures close --sig <sig> --as remediated --detail "<path of the artifact>"`.
|
|
114
|
+
Do **not** delete the failure (provenance — append-only, rule 18). The close is itself one more event, so the history stays.
|
|
115
|
+
|
|
116
|
+
6. **Report the outcome**.
|
|
117
|
+
List which failures became a guardrail (and on which surface), which became a procedure, and which became a learning.
|
|
118
|
+
List which failures stayed open or were closed as `transient`, and why.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Composition (suppression contract)
|
|
123
|
+
|
|
124
|
+
| Who uses it | Reuses | Suppresses |
|
|
125
|
+
| --- | --- | --- |
|
|
126
|
+
| `reconcile` (passive) | reads `afm failures promotable` at end of turn and **proposes** the remediation | nothing — reconcile already proposes-not-applies (#6) |
|
|
127
|
+
| `evolve` (cycle) | the failure events are **evidence** for `reflect` (a lived failure) → **final** remediation happens at the cycle's gate | `remediate`'s own gate (folds into the single gate) |
|
|
128
|
+
|
|
129
|
+
À-la-carte (`afm remediate`) has its own gate: one `afm ask remediate` question per artifact proposed (`questions/remediate.questions.yaml`). Under `reconcile` or `evolve`, approval moves up to their flow.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Anti-patterns
|
|
134
|
+
|
|
135
|
+
- ❌ **Recognizing a failure with no external signal** (self-judgment) — CRITIC: this degrades quality (#3).
|
|
136
|
+
- ❌ **Promoting a single mechanical failure**, or a **transient** one — only 2+ occurrences (or 1 user correction) qualify. Transient failures never qualify (negative filter).
|
|
137
|
+
- ❌ **Writing a procedure or learning that omits the `sig=`** — this violates rule 19's traceability requirement.
|
|
138
|
+
- ❌ **Deleting the failure when remediating it** — close it with `afm failures close --as remediated`, never delete it (provenance).
|
|
139
|
+
- ❌ **Auto-applying the fix** — `remediate` proposes, the human approves (#6).
|
|
140
|
+
- ❌ **Forcing everything into one target** — guardrail, procedure, and learning are distinct (see the rubric).
|
|
141
|
+
- ❌ **Writing a procedure or learning for what a check can catch** — the mechanizable target takes precedence. A document that relies on memory loses to a gate that fires on its own.
|
|
142
|
+
- ❌ **Proposing a guardrail without reading the existing surface** (step 3.5). A new tool by default is the fastest way for the operator to turn the mechanism off.
|
|
143
|
+
- ❌ **Installing the check alone** — installing writes outside `docs/`. The agent must propose it instead (#6).
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: op
|
|
3
|
+
description: Checks the health of the context architecture and finds what went stale.
|
|
4
|
+
load: warm
|
|
5
|
+
writes: ["docs/evolution/*.md"]
|
|
6
|
+
composes: []
|
|
7
|
+
ancestors: Codified-Context (arXiv 2602.20478).
|
|
8
|
+
---
|
|
9
|
+
# Sub-flow: context architecture health (`restructure`)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
> **Form** — effect: edits + opt-in ADR · trigger: `afm restructure`, composition · pre-condition: git + `bites`/`last_bite` · composed by: `evolve` 1.3 · **degree of freedom: medium**
|
|
13
|
+
|
|
14
|
+
Triggers: `afm restructure`, or natural language about **structure/staleness** ("the doc is out of date vs. the code", "this should load only on demand", "reorganize what is always-read vs. on-demand", "I cannot find the guidance in the doc, but it exists").
|
|
15
|
+
|
|
16
|
+
> **Target = this project's local docs (`<consumer>/docs/`), never the plugin.** `restructure` updates, relocates, or re-partitions **only** the docs materialized in this repo. It never touches the canonical framework (the bundled content, bright line #7). A loading strategy that fits any instance is only **recorded** through `afm promote` (a finding with evidence). See [`evolve.md § The target of evolution`](./evolve.md).
|
|
17
|
+
>
|
|
18
|
+
> **Mechanism, not conductor.** `restructure` is the mechanism skill that checks whether the docs are **structured to load efficiently** and **keep pace with the code**. It runs **a-la-carte** (own gate) OR inside the `evolve` cycle (which composes it when `diagnose` flags staleness or a badly partitioned doc — the own gate is then suppressed).
|
|
19
|
+
>
|
|
20
|
+
> CodifiedContext(doc, path):
|
|
21
|
+
> 1. Tier(content) := its memory temperature: hot-always (every turn) | per-task | on-demand (deep reference)
|
|
22
|
+
> 2. GitEvidence(claim) := a `git log` comparison that confirms or refutes claim # PRINCIPLES.md #2
|
|
23
|
+
> 3. Staleness(doc, path) := doc cites `path` AND path's last commit postdates doc's last commit
|
|
24
|
+
> AND doc stayed unchanged for more than N commits # PRINCIPLES.md #3
|
|
25
|
+
> 4. NullRetrieval(query) := an answer to query exists in the docs, but retrieval missed it
|
|
26
|
+
> 5. Gate := opens only after GitEvidence and self-verify confirm the finding # PRINCIPLES.md #6, #8
|
|
27
|
+
> 6. if NullRetrieval -> create or relocate a doc
|
|
28
|
+
>
|
|
29
|
+
> A doc versions its content by memory temperature. Two documented cases show a stale spec
|
|
30
|
+
> misleading the agent — the paper's only confirmed failure mode. See [`../PRINCIPLES.md`](../PRINCIPLES.md).
|
|
31
|
+
|
|
32
|
+
> **Maturity (honest YAGNI).** The paper's full tiering (108k lines of code, 3 tiers, a retrieval MCP) is **future** robustness — an AFM consumer's docs are small today. The **actionable core now** is **staleness** (git trigger) plus **findability/partition** (information exists but sits in the wrong layer). **Tiering by temperature** (marking hot-always vs. on-demand) enters only as an **opt-in ADR proposal**, never as enforcement — only when a doc has actually grown too large.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## What `restructure` is / is not
|
|
37
|
+
|
|
38
|
+
**It is:** the check of the instance's **context architecture**. It covers four items.
|
|
39
|
+
|
|
40
|
+
1. **Staleness** — a doc references code that changed. The doc was not updated.
|
|
41
|
+
2. **Findability** — guidance exists but sits in the wrong layer or place. Retrieval failed even though the content was present.
|
|
42
|
+
3. **Partition by temperature** — what is always-read vs. deep on-demand reference. This is an opt-in loading-strategy proposal.
|
|
43
|
+
4. **Dead-gotcha pruning** — a gotcha whose last-bite date is old and whose count has stopped. A dry incidence is a tombstone candidate. The `fade` axis of `afm doctor` generalizes this: a cold orphan doc with no inject, read or edit in the window and no recent bite is a tombstone candidate too.
|
|
44
|
+
|
|
45
|
+
**It is not:**
|
|
46
|
+
- `diagnose` axis A1 (**dead reference** = the path does not exist). `restructure` staleness means the path **still exists but changed** while the doc did not. The two do not overlap.
|
|
47
|
+
- `reconcile` "missing doc": if information is **genuinely absent** (never documented) → that is `reconcile`/`gotcha`/`rule` (adds new knowledge). `restructure` targets information that **exists but was not found** because it sits in the wrong place (relocation, not creation).
|
|
48
|
+
- `reflect` (a doc misled because it was **ambiguous**). `restructure` targets **location/freshness**, not writing clarity.
|
|
49
|
+
- `generalize` (merges gotchas). `restructure` reorganizes/updates. It does not consolidate content.
|
|
50
|
+
- A content rewriter. `restructure` moves, updates, and re-partitions. Missing product **content** becomes `[TBD]` (#4) or goes to `reconcile` — it is never invented (#5).
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Pre-check
|
|
55
|
+
|
|
56
|
+
1. **Does `<consumer>/docs/.afm-version` exist?** If not, stop and suggest `afm init` or `afm refactor`.
|
|
57
|
+
2. **Does `afm preflight` exit 0?** A non-zero exit says why: the docs are not bootstrapped, the bundled content does not resolve, or the pin does not match. Report it. Do not fall back silently.
|
|
58
|
+
3. **Is git available?** The staleness scan depends on the git history. Without git, `afm doctor` reports the staleness axis as "not covered: no git" (never omit it). Findability and partition still run.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 1. Staleness scan (git trigger — the paper's confirmed failure mode)
|
|
63
|
+
|
|
64
|
+
**`afm doctor --json` runs this scan** and returns each candidate as a finding with axis `staleness` (command, `file:line` and the path's commits as evidence). Read those findings; do not redo the scan by hand. What it checks, for each core doc that **references code** (`ach.md § 3.1` component-to-file map, gotchas with a path, ADRs with a path):
|
|
65
|
+
|
|
66
|
+
- Extract the paths cited (in backticks). For each path, find the **date of the last commit that touched it** (`git log -1 --format=%cd -- <path>`). Compare it with the **date of the last commit that touched the doc** (`git log -1 --format=%cd -- <doc>`).
|
|
67
|
+
- **Path changed after the doc** (code evolved, doc stayed still) → **staleness candidate**. Report the doc's `file:line` and the path's commit range. Default threshold: the path changed in at least 1 commit after the doc. The doc must also have gone untouched for more than N commits (default 20, override with `<!-- evolve: stale-commits=N -->` in `docs/.afm-version`).
|
|
68
|
+
|
|
69
|
+
> Staleness is a **signal**, not a verdict. The doc may still be correct while the code change is unrelated to the documented part. The finding goes to the gate as "this doc may be out of date vs. `<path>` (it changed in N commits since the doc's last update) — review it?" It never rewrites the doc on its own. The correct content requires reading the current code, so it becomes a proposal, not an auto-fix.
|
|
70
|
+
|
|
71
|
+
### 1.1 Dead-gotcha pruning (last-bite — incidence, not avoidance)
|
|
72
|
+
|
|
73
|
+
This applies the same staleness logic to a gotcha's **usefulness**. It uses a **falsifiable** signal: the frontmatter `bites` and `last_bite` fields (from `templates/gotcha.template.md`, filled in by `ops/gotcha.md`). `afm doctor --json` checks it for each gotcha in `gotchas/` and reports the candidates with axis `dead-gotcha`.
|
|
74
|
+
|
|
75
|
+
- **Old last bite** (`last_bite` more than N months ago — a conservative default of 12, override with `<!-- evolve: stale-gotcha-months=N -->`; the `bites` line must also be unmoved in git, and a line whose age is unknown counts as unmoved) **and** `N` unchanged since then → **prune candidate**. It goes to the gate as "this gotcha may be dead (last bite `<date>`, count `N` unchanged) — archive it?"
|
|
76
|
+
- Apply the approval as a **tombstone**: comment out the block, do not delete it. This preserves history and *adds* lines, so it does **not** trigger hard rule 17 (the same pattern as `generalize`). Never hard-delete.
|
|
77
|
+
|
|
78
|
+
> **Why incidence, not avoidance:** the signal is "how many times the gotcha **bit**" (observable in git or in the session), never "how many times it **avoided** an error." Avoidance is counterfactual, unfalsifiable, and *reward-hackable* (the agent could freely self-report avoidance — exactly what the STOP guard in `PRINCIPLES.md` #3 forbids). Pruning by dry incidence is what the Reflexion paper approximates without violating that hardening.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 2. Findability (information exists but is misplaced)
|
|
83
|
+
|
|
84
|
+
**Behavioral plus structural** signal: during the session, the agent looked for guidance in `ach.md` or `gotchas/`/rubrics and **did not find it**. The information **does exist** in another doc or section, proven by a grep that finds it outside the expected place. This is the paper's "null-retrieval" seen from the **structure** angle, not the absence angle:
|
|
85
|
+
|
|
86
|
+
- If the information **exists but sits buried or in the wrong doc** → propose a fix. Relocate it, or add a pointer to it. Move it to the expected section, or add the pointer there. Cite both places (`where I looked` vs. `where it was`).
|
|
87
|
+
- If the information **does not exist anywhere** → **this is not `restructure`**. Route it to `reconcile` (adding new knowledge is `gotcha`/`rule`/a new section). `restructure` does not create missing knowledge (#5).
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 3. Partition by temperature (opt-in loading-strategy proposal)
|
|
92
|
+
|
|
93
|
+
Apply this only when a doc has **actually grown too large** (a `diagnose` A6 signal: inflation). Part of it must also be **deep reference rarely needed**.
|
|
94
|
+
|
|
95
|
+
- Propose a **loading strategy** mark. *Hot-always* content is needed every turn — conventions, commands, § 3 rules. *On-demand* content is deep subsystem reference. It becomes an appendix, read only when needed. The paper's split is hot / per-task / on-demand.
|
|
96
|
+
- The change is **an ADR proposal** (a doc architecture decision), **not** an automatic cut. Moving content to an on-demand appendix keeps 100% of the content (only re-partitions it) and follows the minimal-change discipline.
|
|
97
|
+
- **Opt-in:** without a real inflated doc, **do not propose** tiering. Small docs do not need it (YAGNI), and forced tiering is ceremony. This is the only `restructure` axis that can have zero findings in a healthy instance. The evidence for a tier change is the `tier-drift` axis of `afm doctor` (a cold doc used often, an idle hot or warm doc, an on-demand section read in most runs of its op). It stays a proposal at the gate: nothing changes `load:` on its own.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 4. Own gate (a-la-carte) + application — suppressed under `evolve`
|
|
102
|
+
|
|
103
|
+
Follow the **shared proposal discipline** in `evolve.md § Proposal discipline (shared)`. Read it and follow it. Do not duplicate it — the numbered procedure lives only there.
|
|
104
|
+
|
|
105
|
+
The findings carry **weight**. Staleness changes what the agent believes. Relocation changes where information lives. Tiering is an architecture decision. For this reason, the findings need an item-by-item, earned gate through `afm ask restructure` (`questions/restructure.questions.yaml`, one `--scope <item-slug>` per finding).
|
|
106
|
+
|
|
107
|
+
A-la-carte opens its own gate with that command. Under `evolve`, the process suppresses it.
|
|
108
|
+
|
|
109
|
+
On approval, apply the change. Update the stale doc after reading the current code. Relocate the information, and materialize the loading-strategy ADR if approved. Use the write ops where applicable (`afm adr new <slug>` for the loading-strategy ADR), and suppress their `afm ask`.
|
|
110
|
+
|
|
111
|
+
**Post-condition:** `afm doctor --json`, `afm index --check` and `afm detect --for <file>` over the touched docs must preserve the format the hooks parse. If it does not, report a rollback. The two-branch check in [`evolve.md § Phase 4.3`](./evolve.md#phase-4--application--postconditions--commit-κ-applied) must also report a green boundary.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 5. Record + handoff
|
|
116
|
+
|
|
117
|
+
1. **Materialize or append** to `docs/evolution/<date>-NNN.md` (create it with `afm new evolution-report --mechanism <...>`; fix findings with `afm lint --fix`): the staleness candidates (with git evidence), the relocations, and the tiering decision.
|
|
118
|
+
2. **Does it generalize?** If the loading strategy fits any instance, **record** it through `afm promote`. Give it a finding with evidence. Never apply it directly (#7).
|
|
119
|
+
3. **Hand off to `reconcile`** to watch whether the relocated or updated doc gets found in later sessions.
|
|
120
|
+
|
|
121
|
+
> **The report name is `YYYY-MM-DD-NNN.md` and its frontmatter MUST carry `mechanism: restructure`.**
|
|
122
|
+
> Three mechanisms write into `docs/evolution/`, and each one's cadence window is "since MY last
|
|
123
|
+
> report". A report with no `mechanism:` is invisible to every window, and an ordinal-first name
|
|
124
|
+
> makes the selector order by ordinal before date. Both were live defects until 3.13.0.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Suppression contract (back-pointer)
|
|
129
|
+
|
|
130
|
+
`restructure` **reuses** the proposal discipline, the bucket partition, and the post-conditions from `evolve.md`. Read and follow them. It also reuses the write ops: `adr.md` for the loading strategy, and it suppresses that op's `afm ask`. Under `evolve`, the process suppresses the § 4 gate. The authoritative table is in `evolve.md § Suppression contract`.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Anti-patterns
|
|
135
|
+
|
|
136
|
+
- ❌ **Staleness without git evidence** — "it looks out of date" is not a finding. `git log` on the path vs. the doc is one (#5).
|
|
137
|
+
- ❌ **Rewriting the stale doc alone** — staleness is a signal. The correct content requires reading the current code, so it goes up as a proposal, not an auto-fix.
|
|
138
|
+
- ❌ **Creating missing knowledge** — information that does not exist anywhere belongs to `reconcile`/`gotcha`, not `restructure`. `restructure` only relocates what already exists (#5).
|
|
139
|
+
- ❌ **Forcing tiering on a small doc** — partition by temperature is opt-in. Use it only when the doc has actually grown too large (YAGNI). Small docs do not need it.
|
|
140
|
+
- ❌ **Hard-deleting a gotcha or pruning by avoidance** — gotcha pruning is a **signal**. The signal is an old last bite plus an unchanged `N`. Send it to the gate. Apply it as a **tombstone** (rule 17), never an auto-delete. The signal must be observable incidence, never a self-reported "avoided N errors" claim. That claim is unfalsifiable and conflicts with STOP/#3.
|
|
141
|
+
- ❌ **Cutting content while re-partitioning** — moving content to an on-demand appendix keeps 100% of it. That is re-partition, not pruning. Pruning is a `diagnose`/A6 decision that goes to the gate.
|
|
142
|
+
- ❌ **Editing the bundled content** — **record** a loading strategy for the plugin through `promote`. Never apply it directly (absolute boundary #7). The boundary post-condition is in `evolve.md § Phase 4.3`.
|