[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7CPA3XVB04CCF0MFC8MA4CP":3,"skill-same:01M7CPA3XVB04CCF0MFC8MA4CP":47},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":21,"frontMatter":22,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":13,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":30,"ownerDescription":31,"updatedAt":32,"install":33,"resources":46},"01M7CPA3XVB04CCF0MFC8MA4CP","archive",null,"markosAMO\u002FAlfred","markosAMO","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F51459843?v=4","01M7CP9J22V3QPXPRGE3MJZ091","Markos Moscoso Ocampo","01M7CP9J33G8P7T5TBN51PST9G",0,"MIT","https:\u002F\u002Fgithub.com\u002FmarkosAMO\u002FAlfred\u002Fblob\u002Fmain\u002Fskills\u002Farchive\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: archive\nmode: auto\nskippable: false\nnext: []\n---\n\n# archive\n\nClose the change: fold what was learned into the places that outlive it, then commit.\n\nThis is the phase that keeps the documentation from going stale, because updating it is a\nstep in the work rather than something to remember afterwards.\n\n## Preconditions\n\n```\nverify   passed\nreview   no blocking findings\n```\n\nNeither is inferred from the absence of an error. Both reports are read and their results\nchecked. A change archived without them merges a delta describing behaviour nobody\nconfirmed exists.\n\n## Final state, not the last snapshot\n\nThe reports this phase reads are snapshots. `verify` ran at a moment; commits may have\nlanded since. Archiving the snapshot as if it were current records a state that stopped\nbeing true.\n\nRank the sources before writing anything:\n\n```\n1  the repository now: the code, the tests, what passes today\n2  facts the orchestrator carries about work done after the reports\n3  the verify and review artifacts\n4  the original request\n```\n\nWhen a higher source says resolved and a lower one says open, **report the final state and\ncite where it was resolved** — the commit, the later run. Do not repeat the stale claim.\n\nWhen two sources contradict and neither outranks the other, **record the contradiction**:\nboth statements, where each came from, and when each was written. Never resolve it\nsilently in either direction. A contradiction written down is a question someone can\nanswer; one resolved by guessing is an error nobody can find.\n\nAttribute what comes from a snapshot, rather than restating it as a present fact.\n\n```\nper the verify artifact, at verification time: 47 tests passing\n```\n\nCarry final numbers — test counts, warnings, uncovered lines — from the highest source that\ncovers them. Numbers copied from the verify artifact after later work changed them are wrong in\na document that outlives the change.\n\n## Distinct failures stay distinct\n\nNever merge two defects into one causal story because they appeared together. A cause is\nrecorded as confirmed only with evidence; otherwise the failure is recorded as\nundiagnosed.\n\nAn invented causal link is worse than an admitted gap: `diagnose` will recall it as a\nprecedent, and the next investigation starts from a conclusion nobody proved.\n\n## Features: merging the delta\n\nThe delta in `.alfred\u002Fchanges\u002F{change}\u002Fspec.md` is folded into `paths.master_specs`.\n\n```\nADDED      the requirement is appended to its specification\nMODIFIED   the existing requirement is replaced, and the Previously line is dropped\nREMOVED    the requirement is deleted\n```\n\nThe master specification describes current behaviour, in the present tense, with no history\nof how it got there. Git holds the history, and a specification carrying its own changelog\nbecomes unreadable by the fifth change.\n\nThe change directory stays, and the configuration decides what is in it.\n\n```\nkeep         every phase's artifact, plus the record\nephemeral    the record and the delta spec\npointer      the address file, and the record\n```\n\nEither way it is what a reader follows back from a master specification to understand why a\nrequirement says what it says. Under `ephemeral` that path is shorter and it is the record\nthat answers, which is the point of writing one.\n\n## The record\n\nEvery change writes one, in every mode. It is the document the change leaves behind, and\nunder `artifacts.retain: final_only` it is the only new one.\n\nWritten from `templates\u002Fdocs\u002Frecord.md` to the locator the orchestrator passed, which\nresolves under `paths.change_records`.\n\n```\n.alfred\u002Fchanges\u002Flogin-google\u002Frecord.md\n```\n\nIt is written for someone arriving from a master specification months later with no other\ncontext: what the system does now, why, how it was decided, what was required, and how it\nended. Not a list of phases that ran, and not a list of keys.\n\n**`How it was decided` is the section that pays.** It carries the approach that was taken\nand the alternatives that were rejected, with the reason each was rejected, from the design.\nUnder `final_only` the design document is about to be deleted, and this section is the only\npart of it that survives. Without it the next change reopens a decision that was already\nsettled, which is the cost the whole mode exists to avoid paying.\n\n`Result` reports the state at close, not the state when `verify` and `review` wrote their\nreports. Work continues after a report is written — a finding gets fixed in a later commit,\na blocked task gets finished — and a record that repeats a stale report sends the next reader\nto redo finished work, or to trust that something is pending when it closed. Where the two\ndisagree and neither can be ranked, both are recorded with their source and time, never\nresolved silently.\n\nA change closed incomplete says so here. `archive` may close work that did not finish when\nthe user asks for it explicitly; it may never describe that work as finished.\n\n## Removing the working documents\n\nUnder `artifacts.retain: final_only`, the working documents are removed once the record\nexists.\n\n```\nremoved     every phase's artifact of the change, {phase}.md, and inputs\u002F\nkept        record.md\n            spec.md, under artifacts.keep_delta_spec\n            paths.master_specs, architecture.md, code_conventions.md\n```\n\nThey are removed from the working tree **before staging**, so they never enter the commit\nand the closing diff shows the record, the delta, the merged specifications and the code.\n\nA document an earlier pass committed is tracked, and its removal is staged the same way the\nstate file's is. A change that ran straight through never committed them, and they are\nsimply deleted.\n\nThis is the part to be honest about: with a memory backend configured, the documents were\nindexed as each phase completed and memory is the copy. With `backend: none` there is no\ncopy, and they are gone. That is what the mode means, and it is the right trade only because\nwhat a later reader needs was lifted into the record first. `init` says so when the mode is\nchosen against no backend, and `alfred doctor` repeats it.\n\nOrder matters and is not negotiable:\n\n```\n1  merge the delta into paths.master_specs\n2  write the record\n3  read the record back and check it is not empty and carries How it was decided\n4  only then remove the working documents\n```\n\nStep 3 is the whole safety of the operation, and it is the same check `reindex` makes before\ndeleting under `pointer`. A record that was written empty, or written without the decisions,\nis indistinguishable from a correct one right up to the moment the inputs are gone. A failed\nread-back stops the phase, deletes nothing, and names the record.\n\n`retain: all` skips this section entirely and is the behaviour of every earlier version.\n\n## Removing the state file\n\nState exists so `continue` can resume. A change that closed has nothing to resume.\n\nUnder `artifacts.state_on_completion: delete`, this phase removes\n`.alfred\u002Fstate\u002F{change}.yaml`.\n\nWhether that removal is staged depends on whether the file was ever committed. A change\nthat ran and closed in one pass never committed its state, so the file is untracked and\ndeleting it is the whole operation. A change that was interrupted and resumed — the case\nthe file exists for — was committed by an earlier pass, and the removal has to be staged or\nthe file returns on the next checkout and `continue` finds a change that finished months\nago.\n\n```\ntracked     git rm, staged with the closing commit\nuntracked   delete it\n```\n\nThe phase checks which it is rather than assuming: `git rm` on an untracked file fails the\ncommit, and a plain delete on a tracked one leaves the repository asserting the change is\nstill open.\n\nIt is removed only when the change actually closed:\n\n```\nclosed complete      removed\nclosed incomplete    kept, and the record says what was left open\nverify failed        this phase never ran, so it is kept\nreview blocking      same\nabandoned            nothing closed it, so it is kept\n```\n\nThe second row is the one that looks inconsistent and is not. Open work is work somebody may\ncome back to, and a record reading \"three tasks unfinished\" beside no state leaves nothing\nable to resume them. See `skills\u002F_shared\u002Fstate-contract.md`.\n\n## Closing the address file\n\nUnder `pointer`, every phase before this one appended a row to\n`.alfred\u002Fchanges\u002F{change}\u002FREADME.md` as it completed. This phase closes it, from\n`templates\u002Fdocs\u002Faddresses.md`: the remaining rows, and the postmortem key for a bug.\n\nIt is not the description of the change — the record is, and it sits beside this file in\nevery mode. The address file is the index that makes the entries reachable, and it stops\nwhere the record starts. The outcome, the commit and the specifications that changed are\nwritten once, in the record, because two documents carrying the same outcome go out of step\nat the first correction with nothing to say which is current.\n\nBoth are staged together, for the reason the state file is: an index whose record is missing\ndescribes documents nobody can place, and a record with no index under `pointer` names\nnothing that can be fetched.\n\n## Bugs: the postmortem\n\nA bug writes a postmortem to memory rather than to the specifications.\n\n```\nremember(\n  key:   alfred\u002Fpostmortem\u002F{slug}\n  type:  postmortem\n  title: what failed, in the terms someone would search for\n)\n```\n\n```markdown\n**Symptom**: what was observed\n**Root cause**: what actually caused it\n**Fix**: what changed\n**Why it was not caught**: the gap that let it through\n```\n\n`Why it was not caught` is the field that pays. The others explain one bug; this one names\nthe missing test, the unwritten scenario or the wrong assumption that will let the next one\nthrough.\n\n`diagnose` recalls these before investigating, so a class of failure is diagnosed once.\n\nA bug whose fix changed observable behaviour also carries a delta, and that delta is merged\nas above.\n\n## Committing\n\nPer `git` in the configuration:\n\n```\nstage the files reported by apply\nstage the record, the delta spec and the merged master specifications\nstage the removal of the state file, when the change closed complete\none commit for the whole change\nconventional commit message\nno AI attribution of any kind\npush\n```\n\nOne commit, still. The working documents were already removed from the working tree, before\nstaging, so there is nothing to un-stage and no second commit to tidy up after the first.\n\nA removal is staged explicitly. `git.stage: files_changed_by_alfred` names files Alfred\nwrote, and a file Alfred deleted is not one of them: left unstaged, the state file is\ncommitted as though it still existed and comes back on the next checkout.\n\nStaging everything present would sweep in whatever the user left in progress. The file list\ncomes from the subagent reports, which is why `apply` requires it.\n\nState the scope as what is excluded, never as what is included. \"Stage the source and the\ntests\" is read literally by something that has no way to know a locale file, a migration or\na configuration key was part of the work — observed twice in one run, both times leaving the\nchange incomplete in the commit.\n\n```\neverything the change needs, excluding .alfred\u002F and .alfred\u002Fchanges\u002F\n```\n\nThat exclusion scopes the work `apply` produced, which is code. Alfred's own documents are\nnot swept in by it: the record, the delta spec and the merged specifications are staged by\nname, on the line above, and the state file's removal with them. Naming them is what keeps\nthe two rules from cancelling each other — an exclusion broad enough to keep the working\ndocuments out of the commit is broad enough to keep the record out too.\n\n**Compare before committing.** What git reports as changed is compared against the union of\nevery `files_changed` from `apply`, and any file in one and not the other is reported:\n\n```\nchanged and not reported   apply touched a file and did not say so\nreported and not changed   a task reported work it did not do\n```\n\nNeither is fatal and neither is resolved silently. A file changed and not reported is the\ncollision `apply` is built to detect, and the same difference is what `worktree.sh close`\nrefuses on afterwards — by then the commit already exists and the fix is another commit.\nCompared here, it is a question asked while the answer is still cheap.\n\nAlfred's own documents are outside that comparison. `apply` never wrote them, so every one\nof them is \"changed and not reported\" by construction, and including them would report the\nrecord as a collision on every change.\n\nState is staged with the change — its removal when the change closed complete, its current\ncontents otherwise, so a collaborator who clones mid-change can continue. Under `pointer`\nthe address file is staged with it: they answer the same question from two\nsides and neither is useful alone, per `skills\u002F_shared\u002Fphase-protocol.md`. The skill\nregistry is not: it is ignored, per `skills\u002F_shared\u002Fskill-resolver.md`.\n\n```\nfeat(auth): sign in with Google\n\nImplements .alfred\u002Fchanges\u002Flogin-google\u002Frecord.md.\n3 requirements, 7 scenarios, 47 tests.\n```\n\n## The record does not carry its own commit hash\n\nIt cannot. A commit's hash covers the tree it contains, so a file inside that tree can never\nstate the hash — writing it in changes it, and amending to correct it changes it again.\n\nGit already answers the question from both sides, and neither needs a hash in the document:\n\n```\nwhich commit closed this change      git log --oneline -1 -- \u003Cthe record>\nwhich record does this commit close  the commit message names it\n```\n\nThe record's `commit:` field therefore carries the commit's subject line, which is decided\nbefore the hash exists and is stable under amend. A phase that finds itself amending to\nwrite a hash into the tree that produced it has hit the regress, not a step it missed.\n\nThe message names the record rather than the directory. Under `final_only` the directory\nholds the record and the delta and nothing else, and a message pointing at a directory that\nused to hold eight documents reads as though seven went missing.\n\n## Changes in their own worktree\n\nWhen state carries a `worktree`, this phase runs inside it, and the commit lands on\n`branch`.\n\n**The delta is merged inside the worktree**, into the copy of `paths.master_specs` that is\non this branch, and it goes into this change's commit like every other file. Not into the\nmain checkout.\n\nWriting to the main checkout from a worktree is wrong three times over. The merged\nrequirement is not in the commit, so the branch describes behaviour its own specification\ndoes not mention. Two changes archiving close together write the same file with no branch\nbetween them and one silently wins. And the main checkout ends up dirty, which is the state\nthe worktree layout exists to prevent, discovered later by whoever works there next.\n\nMerged on the branch, two changes that touch the same requirement produce a merge conflict\nwhen the branches meet, which is a question git puts to a person rather than a loss nobody\nsees.\n\nUnder `artifacts.committed: false` there is no commit to put them in. The delta is still\nmerged in the worktree, and then this phase copies `paths.master_specs`, `paths.changes`\nand `paths.change_records` back to the main checkout before any close — they are untracked,\nso the worktree is the only place holding them and `close` discards untracked files.\n`worktree.sh close` refuses while the main checkout is missing any of them, and names what\nit found. See `docs\u002Fartifacts.md`.\n\n`paths.change_records` is in that list even though it usually resolves inside\n`paths.changes`, because it does not have to. Pointed somewhere else, the record is the one\ndocument of the change and it would be the one thing `close` discarded.\n\nThis is also where `retain: final_only` and `committed: false` have to be done in the right\norder. The working documents are removed first, in the worktree, and only what remains is\ncopied back. Copying first and deleting afterwards would carry eight documents into the main\ncheckout to delete seven of them there, and a `close` racing that deletion refuses on files\nthe main checkout has and the worktree no longer does.\n\nAfter the push:\n\n```\ngit.worktrees.pull_request: true    open a pull request from branch to base, if the\n                                    tool for it is available; report and continue if not\ngit.worktrees.remove_on_archive     run worktree.sh close --branch \u003Cbranch> --cwd \u003Cmain_checkout>\n```\n\n`close` refuses a worktree with uncommitted changes, which after a correct commit means a\nfile `apply` did not report. Stop and say which files, rather than forcing: a file changed\nand not committed is the collision `apply` is designed to detect. The branch is deleted\nonly when already merged into `base`; otherwise it stays for the pull request. Run `close`\nfrom `main_checkout`, never from inside the worktree being removed.\n\nThe pull request is off by default because opening one is a decision about the team's\nreview flow, and because it needs a tool that is not always logged in. A failed attempt is\nreported in the completion line, never treated as a failed archive.\n\n## Memory conflicts\n\nEvery conflict a phase recorded during the change, per `memory\u002FCONTRACT.md`, is collected\nhere into one list: what disagreed, which key, and which phase raised it.\n\n**Settle the ones that can be settled.** Every phase is given the backend's full tool list,\nso where the backend offers a judgment call this phase makes it, per\n`memory\u002Fadapters\u002Fengram.md`. What reaches the user is what judgment could not decide.\n\nThis is the step that used to be skipped for the wrong reason. A phase without the tool\nreads exactly like a backend that cannot settle anything, so a run recorded six open\nconflicts, then twenty, and reported them as if that were the contract working. It was a\ntool list written before the tool existed.\n\nWhat cannot be settled is reported, not guessed: what disagreed, which key, which phase\nraised it. The user settles those in one pass, or leaves them.\n\nConflicts raised between the artifacts of the same change — a spec that \"contests\" its own\ndesign — are a similarity threshold wanting tuning, not a disagreement. Say so once, with\nthe count, rather than listing each.\n\nA list of conflicts never blocks an archive. What they are about is written down twice\nalready.\n\n## Carrying findings forward\n\n`should fix` and `suggestion` findings from `review` are written to memory against the area\nthey belong to, not discarded.\n\n```\nalfred\u002Farea\u002F{area}\u002Freview-findings\n```\n\nTwo phases read them, and the key exists because for a long time neither did: `review`\nrecalls them so it raises a repeat as a repeat, and `apply` recalls them so the one phase\nthat can fix them is holding the file when it hears about them.\n\nWrite the area, the finding, the change it came from and the date. A finding with no area\ncannot be recalled by the phase that needs it, which is the same failure as not writing it.\n\n## Workspaces\n\nAt repository level this phase completes that repository's part and commits it.\n\nThe workspace change is archived only once every repository in `repos` has passed `verify`\nand `review`. Until then the workspace change stays open and `status` names the repository\nholding it. See `skills\u002F_shared\u002Fworkspace-protocol.md`.\n\n## Completion\n\nFollow `skills\u002F_shared\u002Fphase-protocol.md`: write the merged specifications, index them,\nupdate state to `completed`, notify `feature_completed`.\n\n```\narchived: 3 requirements merged, committed as feat(auth): sign in with Google\n```\n","# archive\n\nClose the change: fold what was learned into the places that outlive it, then commit.\n\nThis is the phase that keeps the documentation from going stale, because updating it is a\nstep in the work rather than something to remember afterwards.\n\n## Preconditions\n\n```\nverify   passed\nreview   no blocking findings\n```\n\nNeither is inferred from the absence of an error. Both reports are read and their results\nchecked. A change archived without them merges a delta describing behaviour nobody\nconfirmed exists.\n\n## Final state, not the last snapshot\n\nThe reports this phase reads are snapshots. `verify` ran at a moment; commits may have\nlanded since. Archiving the snapshot as if it were current records a state that stopped\nbeing true.\n\nRank the sources before writing anything:\n\n```\n1  the repository now: the code, the tests, what passes today\n2  facts the orchestrator carries about work done after the reports\n3  the verify and review artifacts\n4  the original request\n```\n\nWhen a higher source says resolved and a lower one says open, **report the final state and\ncite where it was resolved** — the commit, the later run. Do not repeat the stale claim.\n\nWhen two sources contradict and neither outranks the other, **record the contradiction**:\nboth statements, where each came from, and when each was written. Never resolve it\nsilently in either direction. A contradiction written down is a question someone can\nanswer; one resolved by guessing is an error nobody can find.\n\nAttribute what comes from a snapshot, rather than restating it as a present fact.\n\n```\nper the verify artifact, at verification time: 47 tests passing\n```\n\nCarry final numbers — test counts, warnings, uncovered lines — from the highest source that\ncovers them. Numbers copied from the verify artifact after later work changed them are wrong in\na document that outlives the change.\n\n## Distinct failures stay distinct\n\nNever merge two defects into one causal story because they appeared together. A cause is\nrecorded as confirmed only with evidence; otherwise the failure is recorded as\nundiagnosed.\n\nAn invented causal link is worse than an admitted gap: `diagnose` will recall it as a\nprecedent, and the next investigation starts from a conclusion nobody proved.\n\n## Features: merging the delta\n\nThe delta in `.alfred\u002Fchanges\u002F{change}\u002Fspec.md` is folded into `paths.master_specs`.\n\n```\nADDED      the requirement is appended to its specification\nMODIFIED   the existing requirement is replaced, and the Previously line is dropped\nREMOVED    the requirement is deleted\n```\n\nThe master specification describes current behaviour, in the present tense, with no history\nof how it got there. Git holds the history, and a specification carrying its own changelog\nbecomes unreadable by the fifth change.\n\nThe change directory stays, and the configuration decides what is in it.\n\n```\nkeep         every phase's artifact, plus the record\nephemeral    the record and the delta spec\npointer      the address file, and the record\n```\n\nEither way it is what a reader follows back from a master specification to understand why a\nrequirement says what it says. Under `ephemeral` that path is shorter and it is the record\nthat answers, which is the point of writing one.\n\n## The record\n\nEvery change writes one, in every mode. It is the document the change leaves behind, and\nunder `artifacts.retain: final_only` it is the only new one.\n\nWritten from `templates\u002Fdocs\u002Frecord.md` to the locator the orchestrator passed, which\nresolves under `paths.change_records`.\n\n```\n.alfred\u002Fchanges\u002Flogin-google\u002Frecord.md\n```\n\nIt is written for someone arriving from a master specification months later with no other\ncontext: what the system does now, why, how it was decided, what was required, and how it\nended. Not a list of phases that ran, and not a list of keys.\n\n**`How it was decided` is the section that pays.** It carries the approach that was taken\nand the alternatives that were rejected, with the reason each was rejected, from the design.\nUnder `final_only` the design document is about to be deleted, and this section is the only\npart of it that survives. Without it the next change reopens a decision that was already\nsettled, which is the cost the whole mode exists to avoid paying.\n\n`Result` reports the state at close, not the state when `verify` and `review` wrote their\nreports. Work continues after a report is written — a finding gets fixed in a later commit,\na blocked task gets finished — and a record that repeats a stale report sends the next reader\nto redo finished work, or to trust that something is pending when it closed. Where the two\ndisagree and neither can be ranked, both are recorded with their source and time, never\nresolved silently.\n\nA change closed incomplete says so here. `archive` may close work that did not finish when\nthe user asks for it explicitly; it may never describe that work as finished.\n\n## Removing the working documents\n\nUnder `artifacts.retain: final_only`, the working documents are removed once the record\nexists.\n\n```\nremoved     every phase's artifact of the change, {phase}.md, and inputs\u002F\nkept        record.md\n            spec.md, under artifacts.keep_delta_spec\n            paths.master_specs, architecture.md, code_conventions.md\n```\n\nThey are removed from the working tree **before staging**, so they never enter the commit\nand the closing diff shows the record, the delta, the merged specifications and the code.\n\nA document an earlier pass committed is tracked, and its removal is staged the same way the\nstate file's is. A change that ran straight through never committed them, and they are\nsimply deleted.\n\nThis is the part to be honest about: with a memory backend configured, the documents were\nindexed as each phase completed and memory is the copy. With `backend: none` there is no\ncopy, and they are gone. That is what the mode means, and it is the right trade only because\nwhat a later reader needs was lifted into the record first. `init` says so when the mode is\nchosen against no backend, and `alfred doctor` repeats it.\n\nOrder matters and is not negotiable:\n\n```\n1  merge the delta into paths.master_specs\n2  write the record\n3  read the record back and check it is not empty and carries How it was decided\n4  only then remove the working documents\n```\n\nStep 3 is the whole safety of the operation, and it is the same check `reindex` makes before\ndeleting under `pointer`. A record that was written empty, or written without the decisions,\nis indistinguishable from a correct one right up to the moment the inputs are gone. A failed\nread-back stops the phase, deletes nothing, and names the record.\n\n`retain: all` skips this section entirely and is the behaviour of every earlier version.\n\n## Removing the state file\n\nState exists so `continue` can resume. A change that closed has nothing to resume.\n\nUnder `artifacts.state_on_completion: delete`, this phase removes\n`.alfred\u002Fstate\u002F{change}.yaml`.\n\nWhether that removal is staged depends on whether the file was ever committed. A change\nthat ran and closed in one pass never committed its state, so the file is untracked and\ndeleting it is the whole operation. A change that was interrupted and resumed — the case\nthe file exists for — was committed by an earlier pass, and the removal has to be staged or\nthe file returns on the next checkout and `continue` finds a change that finished months\nago.\n\n```\ntracked     git rm, staged with the closing commit\nuntracked   delete it\n```\n\nThe phase checks which it is rather than assuming: `git rm` on an untracked file fails the\ncommit, and a plain delete on a tracked one leaves the repository asserting the change is\nstill open.\n\nIt is removed only when the change actually closed:\n\n```\nclosed complete      removed\nclosed incomplete    kept, and the record says what was left open\nverify failed        this phase never ran, so it is kept\nreview blocking      same\nabandoned            nothing closed it, so it is kept\n```\n\nThe second row is the one that looks inconsistent and is not. Open work is work somebody may\ncome back to, and a record reading \"three tasks unfinished\" beside no state leaves nothing\nable to resume them. See `skills\u002F_shared\u002Fstate-contract.md`.\n\n## Closing the address file\n\nUnder `pointer`, every phase before this one appended a row to\n`.alfred\u002Fchanges\u002F{change}\u002FREADME.md` as it completed. This phase closes it, from\n`templates\u002Fdocs\u002Faddresses.md`: the remaining rows, and the postmortem key for a bug.\n\nIt is not the description of the change — the record is, and it sits beside this file in\nevery mode. The address file is the index that makes the entries reachable, and it stops\nwhere the record starts. The outcome, the commit and the specifications that changed are\nwritten once, in the record, because two documents carrying the same outcome go out of step\nat the first correction with nothing to say which is current.\n\nBoth are staged together, for the reason the state file is: an index whose record is missing\ndescribes documents nobody can place, and a record with no index under `pointer` names\nnothing that can be fetched.\n\n## Bugs: the postmortem\n\nA bug writes a postmortem to memory rather than to the specifications.\n\n```\nremember(\n  key:   alfred\u002Fpostmortem\u002F{slug}\n  type:  postmortem\n  title: what failed, in the terms someone would search for\n)\n```\n\n```markdown\n**Symptom**: what was observed\n**Root cause**: what actually caused it\n**Fix**: what changed\n**Why it was not caught**: the gap that let it through\n```\n\n`Why it was not caught` is the field that pays. The others explain one bug; this one names\nthe missing test, the unwritten scenario or the wrong assumption that will let the next one\nthrough.\n\n`diagnose` recalls these before investigating, so a class of failure is diagnosed once.\n\nA bug whose fix changed observable behaviour also carries a delta, and that delta is merged\nas above.\n\n## Committing\n\nPer `git` in the configuration:\n\n```\nstage the files reported by apply\nstage the record, the delta spec and the merged master specifications\nstage the removal of the state file, when the change closed complete\none commit for the whole change\nconventional commit message\nno AI attribution of any kind\npush\n```\n\nOne commit, still. The working documents were already removed from the working tree, before\nstaging, so there is nothing to un-stage and no second commit to tidy up after the first.\n\nA removal is staged explicitly. `git.stage: files_changed_by_alfred` names files Alfred\nwrote, and a file Alfred deleted is not one of them: left unstaged, the state file is\ncommitted as though it still existed and comes back on the next checkout.\n\nStaging everything present would sweep in whatever the user left in progress. The file list\ncomes from the subagent reports, which is why `apply` requires it.\n\nState the scope as what is excluded, never as what is included. \"Stage the source and the\ntests\" is read literally by something that has no way to know a locale file, a migration or\na configuration key was part of the work — observed twice in one run, both times leaving the\nchange incomplete in the commit.\n\n```\neverything the change needs, excluding .alfred\u002F and .alfred\u002Fchanges\u002F\n```\n\nThat exclusion scopes the work `apply` produced, which is code. Alfred's own documents are\nnot swept in by it: the record, the delta spec and the merged specifications are staged by\nname, on the line above, and the state file's removal with them. Naming them is what keeps\nthe two rules from cancelling each other — an exclusion broad enough to keep the working\ndocuments out of the commit is broad enough to keep the record out too.\n\n**Compare before committing.** What git reports as changed is compared against the union of\nevery `files_changed` from `apply`, and any file in one and not the other is reported:\n\n```\nchanged and not reported   apply touched a file and did not say so\nreported and not changed   a task reported work it did not do\n```\n\nNeither is fatal and neither is resolved silently. A file changed and not reported is the\ncollision `apply` is built to detect, and the same difference is what `worktree.sh close`\nrefuses on afterwards — by then the commit already exists and the fix is another commit.\nCompared here, it is a question asked while the answer is still cheap.\n\nAlfred's own documents are outside that comparison. `apply` never wrote them, so every one\nof them is \"changed and not reported\" by construction, and including them would report the\nrecord as a collision on every change.\n\nState is staged with the change — its removal when the change closed complete, its current\ncontents otherwise, so a collaborator who clones mid-change can continue. Under `pointer`\nthe address file is staged with it: they answer the same question from two\nsides and neither is useful alone, per `skills\u002F_shared\u002Fphase-protocol.md`. The skill\nregistry is not: it is ignored, per `skills\u002F_shared\u002Fskill-resolver.md`.\n\n```\nfeat(auth): sign in with Google\n\nImplements .alfred\u002Fchanges\u002Flogin-google\u002Frecord.md.\n3 requirements, 7 scenarios, 47 tests.\n```\n\n## The record does not carry its own commit hash\n\nIt cannot. A commit's hash covers the tree it contains, so a file inside that tree can never\nstate the hash — writing it in changes it, and amending to correct it changes it again.\n\nGit already answers the question from both sides, and neither needs a hash in the document:\n\n```\nwhich commit closed this change      git log --oneline -1 -- \u003Cthe record>\nwhich record does this commit close  the commit message names it\n```\n\nThe record's `commit:` field therefore carries the commit's subject line, which is decided\nbefore the hash exists and is stable under amend. A phase that finds itself amending to\nwrite a hash into the tree that produced it has hit the regress, not a step it missed.\n\nThe message names the record rather than the directory. Under `final_only` the directory\nholds the record and the delta and nothing else, and a message pointing at a directory that\nused to hold eight documents reads as though seven went missing.\n\n## Changes in their own worktree\n\nWhen state carries a `worktree`, this phase runs inside it, and the commit lands on\n`branch`.\n\n**The delta is merged inside the worktree**, into the copy of `paths.master_specs` that is\non this branch, and it goes into this change's commit like every other file. Not into the\nmain checkout.\n\nWriting to the main checkout from a worktree is wrong three times over. The merged\nrequirement is not in the commit, so the branch describes behaviour its own specification\ndoes not mention. Two changes archiving close together write the same file with no branch\nbetween them and one silently wins. And the main checkout ends up dirty, which is the state\nthe worktree layout exists to prevent, discovered later by whoever works there next.\n\nMerged on the branch, two changes that touch the same requirement produce a merge conflict\nwhen the branches meet, which is a question git puts to a person rather than a loss nobody\nsees.\n\nUnder `artifacts.committed: false` there is no commit to put them in. The delta is still\nmerged in the worktree, and then this phase copies `paths.master_specs`, `paths.changes`\nand `paths.change_records` back to the main checkout before any close — they are untracked,\nso the worktree is the only place holding them and `close` discards untracked files.\n`worktree.sh close` refuses while the main checkout is missing any of them, and names what\nit found. See `docs\u002Fartifacts.md`.\n\n`paths.change_records` is in that list even though it usually resolves inside\n`paths.changes`, because it does not have to. Pointed somewhere else, the record is the one\ndocument of the change and it would be the one thing `close` discarded.\n\nThis is also where `retain: final_only` and `committed: false` have to be done in the right\norder. The working documents are removed first, in the worktree, and only what remains is\ncopied back. Copying first and deleting afterwards would carry eight documents into the main\ncheckout to delete seven of them there, and a `close` racing that deletion refuses on files\nthe main checkout has and the worktree no longer does.\n\nAfter the push:\n\n```\ngit.worktrees.pull_request: true    open a pull request from branch to base, if the\n                                    tool for it is available; report and continue if not\ngit.worktrees.remove_on_archive     run worktree.sh close --branch \u003Cbranch> --cwd \u003Cmain_checkout>\n```\n\n`close` refuses a worktree with uncommitted changes, which after a correct commit means a\nfile `apply` did not report. Stop and say which files, rather than forcing: a file changed\nand not committed is the collision `apply` is designed to detect. The branch is deleted\nonly when already merged into `base`; otherwise it stays for the pull request. Run `close`\nfrom `main_checkout`, never from inside the worktree being removed.\n\nThe pull request is off by default because opening one is a decision about the team's\nreview flow, and because it needs a tool that is not always logged in. A failed attempt is\nreported in the completion line, never treated as a failed archive.\n\n## Memory conflicts\n\nEvery conflict a phase recorded during the change, per `memory\u002FCONTRACT.md`, is collected\nhere into one list: what disagreed, which key, and which phase raised it.\n\n**Settle the ones that can be settled.** Every phase is given the backend's full tool list,\nso where the backend offers a judgment call this phase makes it, per\n`memory\u002Fadapters\u002Fengram.md`. What reaches the user is what judgment could not decide.\n\nThis is the step that used to be skipped for the wrong reason. A phase without the tool\nreads exactly like a backend that cannot settle anything, so a run recorded six open\nconflicts, then twenty, and reported them as if that were the contract working. It was a\ntool list written before the tool existed.\n\nWhat cannot be settled is reported, not guessed: what disagreed, which key, which phase\nraised it. The user settles those in one pass, or leaves them.\n\nConflicts raised between the artifacts of the same change — a spec that \"contests\" its own\ndesign — are a similarity threshold wanting tuning, not a disagreement. Say so once, with\nthe count, rather than listing each.\n\nA list of conflicts never blocks an archive. What they are about is written down twice\nalready.\n\n## Carrying findings forward\n\n`should fix` and `suggestion` findings from `review` are written to memory against the area\nthey belong to, not discarded.\n\n```\nalfred\u002Farea\u002F{area}\u002Freview-findings\n```\n\nTwo phases read them, and the key exists because for a long time neither did: `review`\nrecalls them so it raises a repeat as a repeat, and `apply` recalls them so the one phase\nthat can fix them is holding the file when it hears about them.\n\nWrite the area, the finding, the change it came from and the date. A finding with no area\ncannot be recalled by the phase that needs it, which is the same failure as not writing it.\n\n## Workspaces\n\nAt repository level this phase completes that repository's part and commits it.\n\nThe workspace change is archived only once every repository in `repos` has passed `verify`\nand `review`. Until then the workspace change stays open and `status` names the repository\nholding it. See `skills\u002F_shared\u002Fworkspace-protocol.md`.\n\n## Completion\n\nFollow `skills\u002F_shared\u002Fphase-protocol.md`: write the merged specifications, index them,\nupdate state to `completed`, notify `feature_completed`.\n\n```\narchived: 3 requirements merged, committed as feat(auth): sign in with Google\n```\n",{"mode":23,"name":5,"next":24,"skippable":19},"auto",[],"main","e68ffe68ac604c91a9738f0ce2acc1c7585f88f2","skills\u002Farchive","https:\u002F\u002Fgithub.com\u002FmarkosAMO\u002FAlfred","https:\u002F\u002Fgithub.com\u002FmarkosAMO","marmoscoso1@gmail.com","Dev","2026-10-13 14:30:03",{"source":7,"skillName":5,"commands":34,"prompt":44,"zipAvailable":45},[35,38,41],{"tool":36,"command":37},"npx","npx skills add markosAMO\u002FAlfred --skill archive",{"tool":39,"command":40},"bunx","bunx skills add markosAMO\u002FAlfred --skill archive",{"tool":42,"command":43},"pnpm","pnpm dlx skills add markosAMO\u002FAlfred --skill archive","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FmarkosAMO\u002FAlfred\u002Fblob\u002Fmain\u002Fskills\u002Farchive\u002FSKILL.md",true,[],[48,54,60,66,72,78],{"skillNo":49,"name":50,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":51,"categories":52,"keywords":53,"publishedAt":18},"01M7CPAPB4796E8W31MQFMTC9N","{phase=null}","https:\u002F\u002Fgithub.com\u002FmarkosAMO\u002FAlfred\u002Fblob\u002Fmain\u002Ftemplates\u002Fworkflow\u002Fskills\u002Fexample\u002FSKILL.md",[],[],{"skillNo":55,"name":56,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":57,"categories":58,"keywords":59,"publishedAt":18},"01M7CPAMS85JH7H8X17G9PM3YB","verify","https:\u002F\u002Fgithub.com\u002FmarkosAMO\u002FAlfred\u002Fblob\u002Fmain\u002Fskills\u002Fverify\u002FSKILL.md",[],[],{"skillNo":61,"name":62,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":63,"categories":64,"keywords":65,"publishedAt":18},"01M7CPAK5CR387ZSMVAH47CRW4","tasks","https:\u002F\u002Fgithub.com\u002FmarkosAMO\u002FAlfred\u002Fblob\u002Fmain\u002Fskills\u002Ftasks\u002FSKILL.md",[],[],{"skillNo":67,"name":68,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":71,"publishedAt":18},"01M7CPAHZ9ZD1DNM3S5PS2RS9E","spec","https:\u002F\u002Fgithub.com\u002FmarkosAMO\u002FAlfred\u002Fblob\u002Fmain\u002Fskills\u002Fspec\u002FSKILL.md",[],[],{"skillNo":73,"name":74,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":75,"categories":76,"keywords":77,"publishedAt":18},"01M7CPAGF0MDNQKSCE61F5QJ6C","review","https:\u002F\u002Fgithub.com\u002FmarkosAMO\u002FAlfred\u002Fblob\u002Fmain\u002Fskills\u002Freview\u002FSKILL.md",[],[],{"skillNo":79,"name":80,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":18},"01M7CPAF9ETJMQVXT4Q4TJQ2HN","research","https:\u002F\u002Fgithub.com\u002FmarkosAMO\u002FAlfred\u002Fblob\u002Fmain\u002Fskills\u002Fresearch\u002FSKILL.md",[],[]]