@tenkara/afm-linux-arm64 0.0.0-stage → 4.0.0-alpha.6
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 +4256 -0
- package/content/PRINCIPLES.md +121 -0
- package/content/README-light.md +160 -0
- package/content/README.md +152 -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 +265 -0
- package/content/core/afm.md +496 -0
- package/content/core/gotchas.md +18 -0
- package/content/core/prd.md +143 -0
- package/content/core/protocol.md +160 -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 +72 -0
- package/content/interview/bootstrap.md +415 -0
- package/content/interview/promotion.md +117 -0
- package/content/interview/refactor.md +381 -0
- package/content/interview/triggers.md +109 -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 +129 -0
- package/content/ops/clarify.md +86 -0
- package/content/ops/deliver.md +211 -0
- package/content/ops/diagnose.md +146 -0
- package/content/ops/evolve.md +317 -0
- package/content/ops/export-template.md +97 -0
- package/content/ops/generalize.md +120 -0
- package/content/ops/gotcha.md +46 -0
- package/content/ops/plan.md +61 -0
- package/content/ops/policy.md +63 -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 +180 -0
- package/content/ops/remediate.md +146 -0
- package/content/ops/restructure.md +145 -0
- package/content/ops/rule.md +165 -0
- package/content/ops/specify.md +62 -0
- package/content/ops/tasks.md +67 -0
- package/content/ops/update.md +223 -0
- package/content/ops/verify.md +69 -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 +28 -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 +113 -0
- package/content/rubrics/negative-filters.md +38 -0
- package/content/rubrics/solid-triggers.md +121 -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 +34 -0
- package/content/skills/clarify.md +34 -0
- package/content/skills/deliver.md +42 -0
- package/content/skills/diagnose.md +50 -0
- package/content/skills/evolve.md +67 -0
- package/content/skills/export-template.md +40 -0
- package/content/skills/generalize.md +47 -0
- package/content/skills/gotcha.md +40 -0
- package/content/skills/init.md +82 -0
- package/content/skills/plan.md +34 -0
- package/content/skills/policy.md +31 -0
- package/content/skills/promote.md +41 -0
- package/content/skills/protocol.md +42 -0
- package/content/skills/reconcile.md +49 -0
- package/content/skills/refactor.md +84 -0
- package/content/skills/reflect.md +53 -0
- package/content/skills/remediate.md +39 -0
- package/content/skills/restructure.md +52 -0
- package/content/skills/rule.md +44 -0
- package/content/skills/specify.md +34 -0
- package/content/skills/tasks.md +34 -0
- package/content/skills/update.md +56 -0
- package/content/skills/verify.md +31 -0
- package/content/templates/adr.template.md +51 -0
- package/content/templates/evolution-report.template.md +129 -0
- package/content/templates/feature-plan.template.md +86 -0
- package/content/templates/feature-research.template.md +57 -0
- package/content/templates/feature-spec.template.md +86 -0
- package/content/templates/feature-tasks.induced.template.md +67 -0
- package/content/templates/feature-tasks.template.md +60 -0
- package/content/templates/focus.template.md +30 -0
- package/content/templates/gotcha.template.md +31 -0
- package/content/templates/guardrail-runner.template.md +81 -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 +44 -0
- package/plugin/agy/skills/afm-analyze/SKILL.md +36 -0
- package/plugin/agy/skills/afm-clarify/SKILL.md +36 -0
- package/plugin/agy/skills/afm-deliver/SKILL.md +44 -0
- package/plugin/agy/skills/afm-diagnose/SKILL.md +50 -0
- package/plugin/agy/skills/afm-evolve/SKILL.md +69 -0
- package/plugin/agy/skills/afm-export-template/SKILL.md +42 -0
- package/plugin/agy/skills/afm-generalize/SKILL.md +49 -0
- package/plugin/agy/skills/afm-gotcha/SKILL.md +42 -0
- package/plugin/agy/skills/afm-init/SKILL.md +84 -0
- package/plugin/agy/skills/afm-plan/SKILL.md +36 -0
- package/plugin/agy/skills/afm-policy/SKILL.md +31 -0
- package/plugin/agy/skills/afm-promote/SKILL.md +41 -0
- package/plugin/agy/skills/afm-protocol/SKILL.md +42 -0
- package/plugin/agy/skills/afm-reconcile/SKILL.md +49 -0
- package/plugin/agy/skills/afm-refactor/SKILL.md +86 -0
- package/plugin/agy/skills/afm-reflect/SKILL.md +55 -0
- package/plugin/agy/skills/afm-remediate/SKILL.md +41 -0
- package/plugin/agy/skills/afm-restructure/SKILL.md +54 -0
- package/plugin/agy/skills/afm-rule/SKILL.md +46 -0
- package/plugin/agy/skills/afm-specify/SKILL.md +36 -0
- package/plugin/agy/skills/afm-tasks/SKILL.md +34 -0
- package/plugin/agy/skills/afm-update/SKILL.md +58 -0
- package/plugin/agy/skills/afm-verify/SKILL.md +33 -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 +44 -0
- package/plugin/claude-code/skills/analyze/SKILL.md +36 -0
- package/plugin/claude-code/skills/clarify/SKILL.md +36 -0
- package/plugin/claude-code/skills/deliver/SKILL.md +44 -0
- package/plugin/claude-code/skills/diagnose/SKILL.md +50 -0
- package/plugin/claude-code/skills/evolve/SKILL.md +69 -0
- package/plugin/claude-code/skills/export-template/SKILL.md +42 -0
- package/plugin/claude-code/skills/generalize/SKILL.md +49 -0
- package/plugin/claude-code/skills/gotcha/SKILL.md +42 -0
- package/plugin/claude-code/skills/init/SKILL.md +84 -0
- package/plugin/claude-code/skills/plan/SKILL.md +36 -0
- package/plugin/claude-code/skills/policy/SKILL.md +31 -0
- package/plugin/claude-code/skills/promote/SKILL.md +41 -0
- package/plugin/claude-code/skills/protocol/SKILL.md +42 -0
- package/plugin/claude-code/skills/reconcile/SKILL.md +49 -0
- package/plugin/claude-code/skills/refactor/SKILL.md +86 -0
- package/plugin/claude-code/skills/reflect/SKILL.md +55 -0
- package/plugin/claude-code/skills/remediate/SKILL.md +41 -0
- package/plugin/claude-code/skills/restructure/SKILL.md +54 -0
- package/plugin/claude-code/skills/rule/SKILL.md +46 -0
- package/plugin/claude-code/skills/specify/SKILL.md +36 -0
- package/plugin/claude-code/skills/tasks/SKILL.md +34 -0
- package/plugin/claude-code/skills/update/SKILL.md +58 -0
- package/plugin/claude-code/skills/verify/SKILL.md +33 -0
- package/plugin/opencode/afm.js +173 -0
- package/plugin/opencode/agents/afm-executor.md +31 -0
- package/plugin/opencode/agents/afm-explorer.md +47 -0
- package/plugin/opencode/agents/afm-reviewer.md +48 -0
- package/plugin/opencode/skills/afm-adr/SKILL.md +44 -0
- package/plugin/opencode/skills/afm-analyze/SKILL.md +36 -0
- package/plugin/opencode/skills/afm-clarify/SKILL.md +36 -0
- package/plugin/opencode/skills/afm-deliver/SKILL.md +44 -0
- package/plugin/opencode/skills/afm-diagnose/SKILL.md +50 -0
- package/plugin/opencode/skills/afm-evolve/SKILL.md +69 -0
- package/plugin/opencode/skills/afm-export-template/SKILL.md +42 -0
- package/plugin/opencode/skills/afm-generalize/SKILL.md +49 -0
- package/plugin/opencode/skills/afm-gotcha/SKILL.md +42 -0
- package/plugin/opencode/skills/afm-init/SKILL.md +84 -0
- package/plugin/opencode/skills/afm-plan/SKILL.md +36 -0
- package/plugin/opencode/skills/afm-policy/SKILL.md +31 -0
- package/plugin/opencode/skills/afm-promote/SKILL.md +41 -0
- package/plugin/opencode/skills/afm-protocol/SKILL.md +42 -0
- package/plugin/opencode/skills/afm-reconcile/SKILL.md +49 -0
- package/plugin/opencode/skills/afm-refactor/SKILL.md +86 -0
- package/plugin/opencode/skills/afm-reflect/SKILL.md +55 -0
- package/plugin/opencode/skills/afm-remediate/SKILL.md +41 -0
- package/plugin/opencode/skills/afm-restructure/SKILL.md +54 -0
- package/plugin/opencode/skills/afm-rule/SKILL.md +46 -0
- package/plugin/opencode/skills/afm-specify/SKILL.md +36 -0
- package/plugin/opencode/skills/afm-tasks/SKILL.md +34 -0
- package/plugin/opencode/skills/afm-update/SKILL.md +58 -0
- package/plugin/opencode/skills/afm-verify/SKILL.md +33 -0
- package/README.md +0 -3
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: op
|
|
3
|
+
description: Turns a spec into an approach, the affected components and the architectural decisions.
|
|
4
|
+
load: warm
|
|
5
|
+
writes: ["docs/features/*/plan.md"]
|
|
6
|
+
composes: []
|
|
7
|
+
needs: ["feature"]
|
|
8
|
+
---
|
|
9
|
+
# Sub-flow: plan a feature (`plan`)
|
|
10
|
+
|
|
11
|
+
> **Form** — effect: `features/NNN/plan.md` · trigger: `afm plan`, composition · precondition: `spec.md` · composed by: `deliver` 1.C · **degree of freedom: low**
|
|
12
|
+
|
|
13
|
+
Triggers: `afm plan`, or natural language ("plan feature", "draft the plan for feature X").
|
|
14
|
+
|
|
15
|
+
> **Autonomy-first (#6):** running this op alone is already the approval to produce the plan. The agent infers everything from the scan (discover-first #2), materializes the plan and reports (review through `git diff`). **Under the assisted-planning protocol** (`plan=assisted`, run `afm protocol` to read it) this rule does not apply and the op keeps its own gate. With no declared protocol, the default applies (autonomous). See [`core/protocol.md`](../core/protocol.md) § 2. **In orchestrated mode** (called by [`deliver.md`](deliver.md)) the approval moves to the single `deliver` gate; see its suppression contract.
|
|
16
|
+
|
|
17
|
+
The fixed question of this op is data: `questions/plan.questions.yaml`. Ask it with `afm ask plan --scope <slug>` and record one answer with `afm answer plan <id> <label> --scope <slug>`. A choice among features or components is a dynamic list, which a question file cannot hold: ask it in plain words.
|
|
18
|
+
|
|
19
|
+
Procedure:
|
|
20
|
+
|
|
21
|
+
1. **Pre-check.** Run `afm preflight` (exit 3: no `docs/.afm-version`, redirect to `afm init` or `afm refactor`). Pick the feature: the folder whose branch is `feat/NNN-*`, or the operator's hint, or the one `afm feature status <NNN> --json` reports as `plan` or `discovery`. If no `docs/features/NNN-*/spec.md` exists, stop and suggest `afm specify <slug>` first. If the choice is still ambiguous, ask in plain words with the candidate folders.
|
|
22
|
+
|
|
23
|
+
2. **Read the full spec** of the chosen feature.
|
|
24
|
+
|
|
25
|
+
3. **Soft block if the spec has an open `[NEEDS CLARIFICATION:]` marker.** `afm feature status <NNN> --json` lists them in `blockers`. When it is not empty, ask the question `open-markers` (principle #8, see [`../PRINCIPLES.md`](../PRINCIPLES.md)):
|
|
26
|
+
- `clarify-first` (recommended): run `afm clarify` (a structured scan of 9 categories, up to 5 recommendation-first questions, a dated session in the spec's `## Clarifications`), then return to `afm plan`. Redirect to [`clarify.md`](clarify.md) and stop; the operator calls `plan` again afterwards.
|
|
27
|
+
- `resolve-inline`: a quick fallback with no structured scan and no Clarifications section. Ask for each marker in plain words, update the spec and report (#6).
|
|
28
|
+
- `keep-going`: not recommended. The plan inherits the markers and `afm tasks` refuses to run until they are gone.
|
|
29
|
+
- `cancel`: go back to the spec.
|
|
30
|
+
|
|
31
|
+
4. **Discover-first (#2): read `docs/ach.md` and scan the code.** `ach.md` gives the stack and the component types: do not reopen the stack discussion. Search the files and modules the feature touches. The scan infers the current state: what exists, what is net-new, which components the feature affects. If the relevant layer of `ach.md` is `[TBD]`, mark it in plan § 1 and consider a block.
|
|
32
|
+
|
|
33
|
+
**Steps 6 to 9 fill the plan from this discovery. Asking is the last resort, only for what the scan cannot resolve.**
|
|
34
|
+
|
|
35
|
+
5. **Create `docs/features/NNN-slug/plan.md`** with `afm new feature-plan --feature NNN-slug --description "..."` (add `--us`/`--rf` carried from the spec). Fix findings with `afm lint --fix`.
|
|
36
|
+
|
|
37
|
+
**The generator populates the frontmatter the template's `frontmatter_for_output:` names** (hard rule 39): `type: feature-plan`, `description`, `load: cold`, `status: planned` (set the same value in `spec.md`'s frontmatter, in the same step; never write a Status line in a body), and `us`/`rf` carried from `spec.md` when it set them. `for_paths` gets its first real entries HERE, from § 2 below: `spec.md` opened it empty on purpose, because the paths were not known until this scan.
|
|
38
|
+
|
|
39
|
+
6. **Fill § 2, the affected components, inferred from the scan.** List the component types touched (`Procedure-like`, `Domain-like`, `Task-like`, `Lib-like`, `Adapter-like`) and, for each, the file or module and whether it is new or edited (`afm detect --for <file>` shows which rubrics a file fires). Show the inferred list. Ask only when something is genuinely ambiguous (two plausible spots for one component), never blindly (#2).
|
|
40
|
+
|
|
41
|
+
7. **Fill § 4, the architectural decisions, from the discovery.** Record the decisions the scan and the nasca research already show (a library the research recommended, for example). Each decision carries a rejected alternative and a reason. An empty section is valid. Ask (free text) only for a non-obvious decision the discovery did not cover. For a load-bearing decision, suggest an ADR: `afm adr new <slug>` (see [`adr.md`](adr.md)).
|
|
42
|
+
|
|
43
|
+
8. **Fill § 5, the contracts.** For each new external boundary the scan and the research detect, give the shape: input, output and errors (API, webhook, CLI, pub-sub). With no new boundary, write "no new external boundary". Ask only about what the scan did not determine.
|
|
44
|
+
|
|
45
|
+
9. **Fill § 6, the complexity tracking, from the scan.** Record non-trivial complexity as: accepted, simpler alternative rejected, reason. Empty is valid: a simple baseline.
|
|
46
|
+
|
|
47
|
+
10. **Validation § 7.** List mechanically the hard rules of `docs/afm.md` § 3 that apply to the feature, each with a status (pass, justified violation, N/A). Do not invent rules; only list them. When a rule applies, the validation is binary, not optional.
|
|
48
|
+
|
|
49
|
+
11. **Materialize and report** (#6): write `plan.md`, print a summary (components, key decisions, open markers) and the path, for review through `git diff`. No blocking question: invoking the op was the approval. In orchestrated mode even the summary goes to the `deliver` gate.
|
|
50
|
+
|
|
51
|
+
12. **Output to the operator:** the path of the plan, the `[NEEDS CLARIFICATION:]` markers still open, and the next step: "Plan ready. Run `afm tasks` when the clarifications are all resolved."
|
|
52
|
+
|
|
53
|
+
## Anti-patterns
|
|
54
|
+
|
|
55
|
+
- ❌ Do not decide the stack in the plan. Read it from `ach.md` (universal #5).
|
|
56
|
+
- ❌ Do not invent contracts with no evidence in the code or the research (#5). Inferring from scan and research is discovery; guessing with no basis is not.
|
|
57
|
+
- ❌ Do not ask blindly about a component, contract or decision the scan already reveals (#2).
|
|
58
|
+
- ❌ Do not duplicate spec content. The plan references it.
|
|
59
|
+
- ❌ Do not block with a question before each write. Materialize and report.
|
|
60
|
+
- ❌ Do not materialize the plan while ignoring an open `[NEEDS CLARIFICATION:]` in the spec without asking first.
|
|
61
|
+
- ❌ Do not skip the § 7 validation against the hard rules.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: op
|
|
3
|
+
description: Reports what the organisation policy imposes in this project, and never writes to it.
|
|
4
|
+
load: warm
|
|
5
|
+
writes: []
|
|
6
|
+
composes: []
|
|
7
|
+
---
|
|
8
|
+
# Sub-flow: report the organisation policy (`policy`)
|
|
9
|
+
|
|
10
|
+
> **In this file:** What policy is / is not · Procedure · What it must never do · Invariants
|
|
11
|
+
|
|
12
|
+
> **Form** — effect: a report in chat, no file written · trigger: `afm policy` · precondition: `.afm-version` · **degree of freedom: low**
|
|
13
|
+
|
|
14
|
+
Triggers: `afm policy`. Also natural language about the organisation layer. Examples: "what does the
|
|
15
|
+
organisation impose here", "which rules come from outside this repository", "why can I not edit this
|
|
16
|
+
rule".
|
|
17
|
+
|
|
18
|
+
## What `policy` is, and is not
|
|
19
|
+
|
|
20
|
+
It answers one question: **what reaches this project from the organisation bundle, and what does it
|
|
21
|
+
change here.** The bundle is the directory the global config names under `[org] dir`. The op is read
|
|
22
|
+
only: it writes nothing, to either bundle.
|
|
23
|
+
|
|
24
|
+
It is not `afm update`. `update` syncs the instance with the plugin. This reports a second bundle that
|
|
25
|
+
is never synced, because it is read live (hard rule 34).
|
|
26
|
+
|
|
27
|
+
## Procedure
|
|
28
|
+
|
|
29
|
+
1. **Run `afm policy report`.** It does the pre-checks and the reading, and prints the report:
|
|
30
|
+
- Not an AFM project (no `docs/.afm-version`): it says so and stops.
|
|
31
|
+
- No `[org] dir` in the config: *no organisation policy*, a valid state and not a defect.
|
|
32
|
+
- A directory with no `policy.md`: it reports that the config points at something that is not a
|
|
33
|
+
policy bundle, and stops. A mistyped path must not be read as an organisation.
|
|
34
|
+
2. **Read the report by family**, using the precedence table:
|
|
35
|
+
|
|
36
|
+
| Family | What the report shows |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| `rules`, `guardrails` | the organisation wins; each one with its number and description |
|
|
39
|
+
| `gotchas`, `learnings`, `rubrics` | both roots contribute; the organisation ones are marked |
|
|
40
|
+
| `prd`, `ust`, `ach` | nothing: the organisation does not participate, by design |
|
|
41
|
+
|
|
42
|
+
3. **Say plainly that nothing here blocks.** A policy bundle injects context. Nothing in it is
|
|
43
|
+
executed, so nothing in it can fail a commit. An operator who expects enforcement needs to hear that
|
|
44
|
+
from this report, not discover it when a violation ships. The path to enforcement is a runner in
|
|
45
|
+
this project's own gate directory, written from the organisation's rule with `afm rule`.
|
|
46
|
+
4. **Report a collision.** An organisation rule numbered below 100 is a defect in the policy bundle, and
|
|
47
|
+
so is a number that also exists locally. The command names both files and exits 1. Never merge them.
|
|
48
|
+
5. **Say what the reader may change.** A local rule is theirs. An organisation rule is not, and the path
|
|
49
|
+
is the owner of the bundle, not this repository. `afm config print` shows the effective
|
|
50
|
+
config, `[org]` locks included.
|
|
51
|
+
|
|
52
|
+
## What it must never do
|
|
53
|
+
|
|
54
|
+
- Never edit the organisation bundle. Not a typo, not a description, not a number.
|
|
55
|
+
- Never copy the bundle into the project. Hard rule 34, and a copied policy is one that ages.
|
|
56
|
+
- Never infer an organisation from a directory that has no `policy.md`.
|
|
57
|
+
- Never report a policy rule as enforced. It is context. Saying otherwise sells a gate that does not
|
|
58
|
+
exist, which is worse than having no gate at all.
|
|
59
|
+
|
|
60
|
+
## Invariant principles
|
|
61
|
+
|
|
62
|
+
The single canonical source is `afm path PRINCIPLES`. Universals §1-8 apply. #5 applies to the
|
|
63
|
+
attribution: a rule reported under the wrong organisation is an invented fact about a person's employer.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: op
|
|
3
|
+
description: Promotes a learning from one project into the plugin, so every project inherits it.
|
|
4
|
+
load: warm
|
|
5
|
+
writes: []
|
|
6
|
+
composes: []
|
|
7
|
+
---
|
|
8
|
+
# Sub-flow: register a learning that generalizes to the plugin
|
|
9
|
+
|
|
10
|
+
> **Form** — effect: one finding recorded in the project's machine state, never in the repo · trigger: `afm promote` · pre-condition: validated learning · composed of: — · **degree of freedom: medium**
|
|
11
|
+
|
|
12
|
+
Triggers: `afm promote`, or natural language ("promote learning", "this applies to any project").
|
|
13
|
+
|
|
14
|
+
> **Absolute boundary (#6/#7): this op does NOT write to the shipped content.** Not from here, and not
|
|
15
|
+
> from the plugin repo. It **classifies and registers** a finding. The maintainer applies it to the
|
|
16
|
+
> plugin, in the plugin repo, after reading the registered findings. "Promote" here means promote a
|
|
17
|
+
> **candidate**, not content.
|
|
18
|
+
>
|
|
19
|
+
> *Why:* the content an installed `afm` resolves through `afm path` is a versioned, read-only copy of
|
|
20
|
+
> the plugin. An edit there dies at the next update, with no error and no signal. The owner invariant
|
|
21
|
+
> and the defect point to the same place.
|
|
22
|
+
|
|
23
|
+
The operator added something to `docs/` that may generalize to the plugin's content. Identical for
|
|
24
|
+
greenfield or refactored projects.
|
|
25
|
+
|
|
26
|
+
## Procedure
|
|
27
|
+
|
|
28
|
+
1. Read `afm path interview/promotion`: the decision table and the criterion for "applies to any
|
|
29
|
+
project".
|
|
30
|
+
2. **Entry gate (register only validated work).** Do not register a guess. The finding must carry
|
|
31
|
+
**reproducible mechanical evidence**: the command that proves the defect or that proved the
|
|
32
|
+
learning, with its output before and the expected output after.
|
|
33
|
+
- A learning from **code** (a pattern or rule that passed green): the test or type-check run that
|
|
34
|
+
went green. Add `test -e <cited-path>` to confirm the code the learning references **exists**. If
|
|
35
|
+
it references uncommitted code, record that fact as part of the evidence.
|
|
36
|
+
- A learning from **meta** (a finding from `afm reflect`, `afm diagnose` or `afm evolve` about the
|
|
37
|
+
plugin itself): the `grep`, `diff` or `test -e` that **proves** the defect in the shipped content,
|
|
38
|
+
plus the command that would return zero after the fix.
|
|
39
|
+
|
|
40
|
+
No reproducible command means **do not register it**. Note it as an observation in the report
|
|
41
|
+
instead. This is the same filter as #5 (do not invent without a real case).
|
|
42
|
+
3. **Walk the classification** and decide the finding's `target`. It is a label, not a write destination:
|
|
43
|
+
- Depends on a project entity or project-specific naming: it stays in `docs/`. **Do not register
|
|
44
|
+
it** (not a plugin gap).
|
|
45
|
+
- Specific to one stack and a FACT about it (a real constraint, an SDK behavior): `modules/<stack>/`.
|
|
46
|
+
- A repeated code smell with a general decision that is not tied to any one project's entities:
|
|
47
|
+
`patterns/`. Never register the OPPOSITE direction: a finding that some code should have used a
|
|
48
|
+
pattern and did not is a review comment for that project, not a plugin gap.
|
|
49
|
+
- A naming, test-placement, file-size, error-boundary or imports CONVENTION is different from a
|
|
50
|
+
fact: the operator could reasonably decide it the other way. Route it to `code-style/<stack>/`
|
|
51
|
+
when it applies to one stack only, or to `code-style/_any/` regardless of stack.
|
|
52
|
+
- `modules/` may not cross this line any more. A convention that reads as `(mandatory)` inside a
|
|
53
|
+
module is the defect this split fixes. Do not re-route a convention back into
|
|
54
|
+
`modules/<stack>/` by classifying it as a "fact".
|
|
55
|
+
- Universal (no stack assumption, not a style convention): `core/`.
|
|
56
|
+
4. **Register** the finding: `afm findings record --target <target> --title "<short, imperative title>" --evidence "<command> → <today's output> · expected after fix: <output>" --note "<1-3 sentences: what changes in the plugin and why it applies to any instance>"`. The command adds the
|
|
57
|
+
origin (project and the version pinned in `docs/.afm-version`) and stores the finding under the
|
|
58
|
+
project's state in `AFM_HOME`, never in the repo. It prints the finding as an **issue body ready to
|
|
59
|
+
paste**, because harvesting is manual.
|
|
60
|
+
5. **Report and stop.** Tell the operator what you registered and where. Do **not** open a PR, do
|
|
61
|
+
**not** publish, and do **not** bump any version. The maintainer bumps the plugin's version and
|
|
62
|
+
changelog in the plugin repo, outside this op.
|
|
63
|
+
|
|
64
|
+
## Anti-patterns
|
|
65
|
+
|
|
66
|
+
- ❌ **Editing the shipped content.** Absolute boundary. There is no path around it, not even with the
|
|
67
|
+
operator's approval in this session: the target it can reach is a disposable copy.
|
|
68
|
+
- ❌ **Registering without a reproducible command.** An impression is not a finding (#5).
|
|
69
|
+
- ❌ **Registering a learning that names a project entity** without generalizing it first.
|
|
70
|
+
- ❌ **Registering an ADR.** An ADR is a decision for this project. The learning *from* the decision
|
|
71
|
+
(a gotcha, a rule) can become a finding. The ADR itself cannot.
|
|
72
|
+
- ❌ **Registering in anticipation** ("this will be useful later"). Register on demand, with a real case.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: op
|
|
3
|
+
description: Declares or changes the autonomy posture that parametrizes the loop.
|
|
4
|
+
load: warm
|
|
5
|
+
writes: ["docs/_focus.md"]
|
|
6
|
+
composes: []
|
|
7
|
+
---
|
|
8
|
+
# Sub-flow: declare or change the current protocol (`protocol`)
|
|
9
|
+
|
|
10
|
+
> **Form** — effect: `protocol:` in `_focus.md` · trigger: `afm protocol` · pre-condition: `.afm-version` · composed of: — · **degree of freedom: low**
|
|
11
|
+
|
|
12
|
+
Triggers: `afm protocol [<name>]`, or a natural-language ask ("what protocol am I using", "switch to
|
|
13
|
+
assisted", "decide this delivery on your own").
|
|
14
|
+
|
|
15
|
+
> A protocol is **data**, not code. It parametrizes operations that already exist. The canonical
|
|
16
|
+
> definition of the fields and presets is `afm path core/protocol`. The presets are a typed table in the
|
|
17
|
+
> CLI, so "p1 only by an explicit act" is a property of the command, not a promise of the prose.
|
|
18
|
+
|
|
19
|
+
## Procedure
|
|
20
|
+
|
|
21
|
+
1. **Report the current protocol.** `afm protocol` with no argument reads `protocol:` from
|
|
22
|
+
`docs/_focus.md` and prints it. It writes nothing.
|
|
23
|
+
- Line missing or `[TBD]`: the project runs the **defaults** (pre-v4 behavior). The report lists the
|
|
24
|
+
available presets, one line each.
|
|
25
|
+
- Name present: the report prints the name, the effective fields and the file path.
|
|
26
|
+
2. **Make a preset current:** `afm protocol <p1|p2|p3>`. The command materializes
|
|
27
|
+
`docs/protocols/<name>.md` from the shipped preset when it is absent and writes `protocol: <name>`
|
|
28
|
+
in `docs/_focus.md` (slot-state OVERWRITE, rule 20: it never appends a second line).
|
|
29
|
+
3. **A custom protocol** is a file the operator wrote by hand at `docs/protocols/<name>.md`. Outside
|
|
30
|
+
`p1|p2|p3` the command refuses a name whose file is absent: **never invent a preset** (principle
|
|
31
|
+
#5). Report the expected path and the required fields from `afm path core/protocol`.
|
|
32
|
+
4. **P1 needs an explicit act in this session.** Granting p1 widens autonomy, and the repo never grants
|
|
33
|
+
it to itself (`core/protocol` § 6: a host that honours a project-declared autonomy mode would let any
|
|
34
|
+
cloned repo switch off its own gates). A person runs `afm protocol p1 --i-mean-it`; the command
|
|
35
|
+
refuses an agent actor and refuses the call without the flag. Never infer p1 from natural language
|
|
36
|
+
and never inherit it from `git pull`.
|
|
37
|
+
5. **Report the behavior delta**, not just the name. The command prints which parameters change value
|
|
38
|
+
against the previous protocol (table in `core/protocol` § 2). Switching protocols without knowing
|
|
39
|
+
what changes means switching contracts blind.
|
|
40
|
+
|
|
41
|
+
## Anti-patterns
|
|
42
|
+
|
|
43
|
+
- ❌ Infer a protocol switch from ambiguous natural language. "go for it" is an ephemeral gate override
|
|
44
|
+
(`plan=auto` for this delivery), **not** a change to the project's contract. Otherwise the contract
|
|
45
|
+
stops being a contract.
|
|
46
|
+
- ❌ Append `protocol:` when the line already exists. `_focus.md` is slot-state (rule 20).
|
|
47
|
+
- ❌ Invent a preset. Outside `p1|p2|p3`, the file must already exist.
|
|
48
|
+
- ❌ Apply a protocol to the bright lines, to `afm reconcile`, or to the self-evolution operations.
|
|
49
|
+
These stay invariant under every protocol (`core/protocol` § 4).
|
|
50
|
+
- ❌ Propagate the escalation contract to a sub-agent. The protocol declares a **delegation ceiling**.
|
|
51
|
+
Escalation does not flow down, because a sub-agent has no useful `afm ask` channel.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: op
|
|
3
|
+
description: Observes the session passively and proposes the doc edit that the work earned.
|
|
4
|
+
load: warm
|
|
5
|
+
writes: []
|
|
6
|
+
composes: []
|
|
7
|
+
---
|
|
8
|
+
# Sub-flow: reconcile (passive)
|
|
9
|
+
|
|
10
|
+
> **Form** — effect: proposes. Overwrites `docs/_focus.md` when the focus changed. · trigger: **always-on** (passive) · precondition: `.afm-version` · composed by: `deliver` 4.B · **degree of freedom: high**
|
|
11
|
+
|
|
12
|
+
Passive trigger. No explicit command. It applies during any session, in a greenfield or refactored project, in any harness.
|
|
13
|
+
|
|
14
|
+
This op asks nothing a question file could hold: it proposes in one short line at the end of the turn.
|
|
15
|
+
|
|
16
|
+
Procedure:
|
|
17
|
+
|
|
18
|
+
1. Watch the signals listed in [`interview/triggers.md`](../interview/triggers.md). Examples: a new structural decision, a runtime surprise twice, a correction with a reusable rule, a new component.
|
|
19
|
+
|
|
20
|
+
- **Read the capture substrate (a safety net against a volatile signal), not only the session memory.** The harness hooks write every edit of a normative doc to an append-only ledger in the AFM state directory (outside the repository), and show you the delta you have not seen in the session context. **Add** what that delta shows to what you observed. The log is a safety net, not a substitute for attention. The hook owns the cursor: you read, you never move it.
|
|
21
|
+
- **Cadence and telemetry `kind` values are not a reconcile signal.** `task`, `deliverable`, `failure` and `op` record the *work rhythm* and *which operation ran*, not *learned knowledge*. A commit has no doc to propose, and neither does the fact that an operation was invoked. They feed the **derived** counters that decide when `reflect` or `evolve` becomes due (the thresholds are `afm protocol` fields) and, for `failure`, the recurrence promotion that `afm remediate` uses. Filter them out of the delta.
|
|
22
|
+
2. When a signal fires, **propose** the matching edit at the end of the turn: an ADR, a hard rule, a gotcha, or a note in `ach.md` or `prd.md`. Use the matching op ([`adr.md`](adr.md), [`rule.md`](rule.md), [`gotcha.md`](gotcha.md)), whose mechanical steps are `afm adr new`, `afm rule new` and `afm gotcha new`.
|
|
23
|
+
|
|
24
|
+
A **recognized failure** (a test, type-check or command that stayed unresolved past the retry cap of `afm.md § 5.1`, or a user correction) goes to the **CRITIC loop** (`afm remediate`, see [`remediate.md`](remediate.md)). It classifies the failure and proposes a **procedure** (mechanical) or a **learning** (conceptual). The gate needs *one user correction or a `sig=` that recurs twice or more*: `afm failures promotable` lists the signatures that did. A single or transient failure stays only as evidence (#5).
|
|
25
|
+
|
|
26
|
+
**Continuity (state, not a decision, #1):** if the focus changed in the session, **overwrite** `docs/_focus.md`. This is the fourth destination, OVERWRITE (rule 20), exempt from rule 17.
|
|
27
|
+
|
|
28
|
+
A session handoff that the session-start context shows you is context, not a doc. The hook owns its state. It stays **below** the gate for promotion to a normative doc, and becomes a gotcha, ADR or rule only if the learning crosses criterion #1 ("another agent without my memory needs to know this"). See [`../rubrics/episodic-vs-semantic-boundary.md`](../rubrics/episodic-vs-semantic-boundary.md).
|
|
29
|
+
|
|
30
|
+
In a **template-origin** project (`docs/.template` was the seed), apply the precedence rule when a signal **contradicts** an inherited artifact: see [`../rubrics/template-vs-streaming-precedence.md`](../rubrics/template-vs-streaming-precedence.md). The streaming signal wins locally and you add a tombstone to the inherited artifact. **Never merge** the two: offline and online are not additive (AWM).
|
|
31
|
+
|
|
32
|
+
2.5. **Apply the negative filter before you promote (entry gate, #5).** Before you propose any signal as a durable doc, apply the checklist of [`../rubrics/negative-filters.md`](../rubrics/negative-filters.md).
|
|
33
|
+
|
|
34
|
+
**Reject** these cases. They become evidence or state, not a doc: a negative tool claim that hardens into a fossil refusal; a transient failure that is a dead constraint; a one-off narrative (a session entry); a user-visible status (`_focus.md`).
|
|
35
|
+
|
|
36
|
+
The four tests: Does it have a durable antidote? Does it survive a fix to the root cause? Does another agent without my memory need to know it (#1)? Did it recur twice or more, or come from a user correction or an external SDK (#5)? **Four yes answers** promote it.
|
|
37
|
+
|
|
38
|
+
**Cardinality fan-out:** if the signal **redefines** a term that lives in several docs, cover **all** of them. Run `grep -rl "<term>" docs/`, not only the obvious one (§ 1.3).
|
|
39
|
+
3. **Delta, never a rewrite (ACE, anti-context-collapse).** Every proposal is (a) a **structured append** at the end of the right section, or (b) an **update in place** of one named item. **Never** rewrite the whole doc.
|
|
40
|
+
|
|
41
|
+
A proposal that would delete more than 50% of a `docs/` file violates **hard rule 17** (`afm.md § 3`). Stop and flag it to the operator; do not propose a blind edit.
|
|
42
|
+
|
|
43
|
+
Before you propose a **new gotcha**, run `afm index --for <path>` and `grep -r "<area>" docs/gotchas/` for a similar surface or area. If **two or more similar gotchas** already exist, suggest `afm generalize` instead of appending one more: it merges them at the root. This stops inflation where it starts. Reactive curation still lives in `afm generalize` and `afm diagnose` axis A6; here it is only a signal-gated nudge, not a sweep.
|
|
44
|
+
4. **Never apply automatically.** Reconcile PROPOSES. The operator decides what goes into the doc. This is consistent with #6: an observed passive signal is not scope the operator approved. Autonomy-first applies inside an invoked op or an approved feature, not to edits nobody asked for.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: op
|
|
3
|
+
description: Refines a doc that guided the agent wrong, using evidence from the session itself, and proposes the full cycle when that evidence outgrows one doc.
|
|
4
|
+
load: warm
|
|
5
|
+
writes: ["docs/evolution/*.md"]
|
|
6
|
+
composes: []
|
|
7
|
+
---
|
|
8
|
+
# Sub-flow: behavioral self-reflection on the docs (`reflect`)
|
|
9
|
+
|
|
10
|
+
> **In this file:** What reflect is / is not · Pre-check · 1. Behavioral evidence collection · 2. Self-critique: doc-wrong vs agent-non-conforman… · 3. Proposal: make the doc more assertive + s… · 4. Own gate (à-la-carte) — suppressed und… · 5. Record + session closing + handoff · Suppression contract · Anti-patterns
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
> **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**
|
|
14
|
+
|
|
15
|
+
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".
|
|
16
|
+
|
|
17
|
+
> **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).
|
|
18
|
+
>
|
|
19
|
+
> **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`.
|
|
20
|
+
>
|
|
21
|
+
> **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**).
|
|
22
|
+
>
|
|
23
|
+
> Reflect(session_trace) -> φ_b:
|
|
24
|
+
> 1. scan session_trace for a point where a core doc guided the agent badly
|
|
25
|
+
> 2. φ_b := (symptom-lived, causal-status-of-the-doc, mechanism)
|
|
26
|
+
> # both a doc passage AND a session event MUST be cited — else φ_b is not evidence
|
|
27
|
+
> 3. MetaReflect(φ_b) -> proposal:
|
|
28
|
+
> a. rival := "the doc was clear AND correct — I am the one who did not follow it"
|
|
29
|
+
> b. if rival holds -> discard: φ_b stays an observation, no proposal
|
|
30
|
+
> c. else -> proposal := a rewrite that makes the doc passage more assertive and clear
|
|
31
|
+
> 4. Instructiveness := proposal disambiguates, adds a missing trigger, or resolves a
|
|
32
|
+
> contradiction — it never adds knowledge the doc did not already carry
|
|
33
|
+
>
|
|
34
|
+
> 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).
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## What `reflect` is / is not
|
|
39
|
+
|
|
40
|
+
**It is:** the reflection on where the **local docs underperformed as a harness** during real work.
|
|
41
|
+
|
|
42
|
+
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.
|
|
43
|
+
|
|
44
|
+
The evidence is **the session's trajectory** — 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.
|
|
45
|
+
|
|
46
|
+
**It is NOT:**
|
|
47
|
+
- `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.*
|
|
48
|
+
- `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).
|
|
49
|
+
- `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.
|
|
50
|
+
- 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/`).
|
|
51
|
+
- 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."
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Pre-check
|
|
56
|
+
|
|
57
|
+
1. **Does `<consumer>/docs/.afm-version` exist?** If not, stop. Suggest `afm init` or `afm refactor` first.
|
|
58
|
+
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.
|
|
59
|
+
3. **Capture the events lived in this session.** The `reflect` trigger is in-session — see `interview/triggers.md`. Note which core docs the agent read or followed, and where they guided badly. With no lived event this session, and no clear symptom, stop: there is no reflection to do. Report "no doc friction observed in this session", 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.
|
|
60
|
+
|
|
61
|
+
> **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.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 1. Behavioral evidence collection (≈ *Reflect* — traces → hypotheses)
|
|
66
|
+
|
|
67
|
+
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 this session where a core doc guided badly. Record a **behavioral signature** for it: `φ_b = (symptom-lived, causal-status-of-the-doc, mechanism)`.
|
|
68
|
+
|
|
69
|
+
- *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.
|
|
70
|
+
- *causal-status-of-the-doc* — was **the doc** causally implicated? This slot is the *causal status*, not "who is to blame."
|
|
71
|
+
- *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.
|
|
72
|
+
|
|
73
|
+
**Golden rule:** every signature cites **the doc passage** (`file:section`). It also cites **the session event** — what the agent did, or what the user said. Without both sides, it is not evidence. It is only an impression.
|
|
74
|
+
|
|
75
|
+
### 1.2 — The second sweep: what I corrected by hand more than once
|
|
76
|
+
|
|
77
|
+
Beyond a doc that guided badly, `reflect` sweeps the session 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.
|
|
78
|
+
|
|
79
|
+
Each occurrence becomes a **guardrail candidate**: `(the defect, how many times this session, 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, or one explicit user correction.
|
|
80
|
+
|
|
81
|
+
> **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.
|
|
82
|
+
|
|
83
|
+
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.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 2. Self-critique: doc-wrong vs. agent-non-conformant (mandatory filter)
|
|
88
|
+
|
|
89
|
+
Before proposing any refinement, list the **mandatory rival hypothesis** for **each** signature. State it this way:
|
|
90
|
+
|
|
91
|
+
*"the doc was clear and correct — I am the one who did not follow it."*
|
|
92
|
+
|
|
93
|
+
Only a finding that survives this filter becomes a refinement proposal.
|
|
94
|
+
|
|
95
|
+
- **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).
|
|
96
|
+
- **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.
|
|
97
|
+
|
|
98
|
+
> **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.
|
|
99
|
+
|
|
100
|
+
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.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 3. Proposal: make the doc more assertive + suggestions for the human (≈ *MetaReflect*)
|
|
105
|
+
|
|
106
|
+
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.
|
|
107
|
+
|
|
108
|
+
- **(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:
|
|
109
|
+
- Rewrite the ambiguous passage so it reads only one way.
|
|
110
|
+
- **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).
|
|
111
|
+
- Disambiguate a contradiction, or itemize an ADR for it.
|
|
112
|
+
- Move buried guidance, or point to it from a clearer spot.
|
|
113
|
+
- **(c) Guardrail candidate** (from § 1.2) — the defect the agent corrected by hand 2 or more times this session. 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.
|
|
114
|
+
- **(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 this session. 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.
|
|
115
|
+
|
|
116
|
+
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.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 4. Own gate (à-la-carte) — suppressed under `evolve`
|
|
121
|
+
|
|
122
|
+
À-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).
|
|
123
|
+
|
|
124
|
+
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.
|
|
125
|
+
|
|
126
|
+
> 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`.
|
|
127
|
+
|
|
128
|
+
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.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 5. Record + session closing + handoff
|
|
133
|
+
|
|
134
|
+
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, 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.
|
|
135
|
+
|
|
136
|
+
> **The report name is `YYYY-MM-DD-NNN.md` and its frontmatter MUST carry `mechanism: reflect`.**
|
|
137
|
+
> Three mechanisms write into `docs/evolution/`, and each one's cadence window is "since MY last
|
|
138
|
+
> report". A report with no `mechanism:` is invisible to every window, and an ordinal-first name
|
|
139
|
+
> makes the selector order by ordinal before date. Both were live defects until 3.13.0.
|
|
140
|
+
|
|
141
|
+
> **À-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.
|
|
142
|
+
|
|
143
|
+
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:
|
|
144
|
+
|
|
145
|
+
- **`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.
|
|
146
|
+
- **`## 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.
|
|
147
|
+
- **`## 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.
|
|
148
|
+
- **`## 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.
|
|
149
|
+
- **`reflection:`** — the link to the `docs/evolution/<date>-NNN` file from step 1. 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.
|
|
150
|
+
|
|
151
|
+
**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.
|
|
152
|
+
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.
|
|
153
|
+
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).
|
|
154
|
+
|
|
155
|
+
> **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).
|
|
156
|
+
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.
|
|
157
|
+
|
|
158
|
+
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.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Suppression contract (back-pointer)
|
|
163
|
+
|
|
164
|
+
`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`.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Anti-patterns
|
|
169
|
+
|
|
170
|
+
- ❌ **Reflecting with no lived event** — for example "this rule seems ambiguous" with no actual stumble this session. That is an impression, not evidence (rule #5). No friction observed: report "no friction", run `afm cadence close --arm reflect --reason "no doc friction observed"` and stop.
|
|
171
|
+
- ❌ **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.
|
|
172
|
+
- ❌ **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.
|
|
173
|
+
- ❌ **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).
|
|
174
|
+
- ❌ **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.
|
|
175
|
+
- ❌ **Classifying a trigger or hook-path edit as auto-applicable**. It is always bucket (b). It narrows the agent's own oversight.
|
|
176
|
+
- ❌ **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`.
|
|
177
|
+
- ❌ **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.
|
|
178
|
+
- ❌ **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.
|
|
179
|
+
- ❌ **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.
|
|
180
|
+
- ❌ **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.
|