@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.34 → 0.1.37
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/adl +2 -2
- package/bin/reconcile +4 -3
- package/package.json +1 -1
- package/packages/agent-hooks/README.md +14 -0
- package/packages/agent-hooks/assets/opencode-plugin.template.ts +140 -104
- package/packages/agent-hooks/deploy-profile.json +1 -1
- package/packages/agent-hooks/src/deploy/opencode-template.ts +5 -18
- package/packages/agent-hooks/src/deploy/render.ts +12 -3
- package/packages/agent-hooks/src/pre-tool-use/handler.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/adl-build-run-role.ts +116 -0
- package/packages/agent-hooks/src/rules/impl/adl-git-user-override-block.ts +159 -0
- package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +12 -6
- package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +9 -9
- package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +6 -5
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +15 -14
- package/packages/agent-hooks/src/rules/impl/git-core.ts +4 -8
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +8 -7
- package/packages/agent-hooks/src/rules/registry.ts +11 -2
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +9 -5
- package/packages/agent-settings/README.md +10 -4
- package/packages/agent-settings/assets/TARUN-GLOBAL-AGENTS-INSTRUCTIONS.md +40 -0
- package/packages/agent-settings/src/global-agents.ts +43 -8
- package/packages/agent-skills/assets/adl-mechanics/SKILL.md +38 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +1 -1
- package/packages/agent-skills/assets/code-review/SKILL.md +84 -66
- package/packages/agent-skills/assets/diagnosing-bugs/SKILL.md +23 -2
- package/packages/agent-skills/assets/diagnosing-bugs/references/FEEDBACK-LOOP-TACTICS.md +1 -1
- package/packages/agent-skills/assets/explore-codebase/SKILL.md +3 -2
- package/packages/agent-skills/assets/finalize-feature/SKILL.md +63 -0
- package/packages/agent-skills/assets/fix-ci/SKILL.md +58 -0
- package/packages/agent-skills/assets/handoff/SKILL.md +1 -1
- package/packages/agent-skills/assets/implement-feature/SKILL.md +153 -0
- package/packages/agent-skills/assets/implement-feature/references/briefs.md +94 -0
- package/packages/agent-skills/assets/implement-item/SKILL.md +71 -0
- package/packages/agent-skills/assets/mechanics/SKILL.md +38 -0
- package/packages/agent-skills/assets/plan-feature/SKILL.md +141 -0
- package/packages/agent-skills/assets/prepare-promotion/SKILL.md +91 -0
- package/packages/agent-skills/assets/ralplan/SKILL.md +149 -0
- package/packages/agent-skills/assets/refactor-safely/SKILL.md +4 -3
- package/packages/agent-skills/assets/report-bug/SKILL.md +72 -0
- package/packages/agent-skills/assets/review-change/SKILL.md +82 -0
- package/packages/agent-skills/assets/review-plan/SKILL.md +124 -0
- package/packages/agent-skills/assets/to-feature/SKILL.md +1 -1
- package/packages/agent-skills/assets/to-workitems/SKILL.md +1 -1
- package/packages/agent-skills/assets/to-workitems/references/AZURE-DEVOPS-HIERARCHY.md +3 -0
- package/packages/agent-skills/assets/triage-workitems/SKILL.md +99 -0
- package/packages/agent-skills/assets/ultragoal/SKILL.md +77 -0
- package/packages/agent-skills/assets/validate-design/SKILL.md +70 -0
- package/packages/agent-skills/assets/verify-item/SKILL.md +71 -0
- package/packages/agent-skills/assets/workitems-process/SKILL.md +147 -0
- package/packages/agent-skills/assets/workitems-process/references/ado-and-git.md +194 -0
- package/packages/agent-skills/assets/workitems-process/references/evidence.md +74 -0
- package/packages/agent-skills/assets/workitems-process/references/workitem-states.md +92 -0
- package/packages/agent-skills/assets/write-feature/SKILL.md +95 -0
- package/packages/agent-skills/dist/deploy.d.ts +7 -0
- package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
- package/packages/agent-skills/dist/deploy.js +52 -5
- package/packages/agent-skills/dist/deploy.js.map +1 -1
- package/packages/agent-skills/src/deploy.ts +48 -4
- package/packages/azdo/scripts/probe-ado-rules.ts +1 -1
- package/packages/azdo/src/activity-log.ts +118 -0
- package/packages/azdo/src/azdo-attachments.ts +108 -0
- package/packages/azdo/src/azdo-pl.ts +100 -3
- package/packages/azdo/src/azdo-pr.ts +194 -11
- package/packages/azdo/src/azdo-wit.ts +329 -18
- package/packages/azdo/src/cli.ts +42 -2
- package/packages/azdo/src/lib/agent-identity.ts +1 -1
- package/packages/azdo/src/lib/client.ts +7 -1
- package/packages/azdo/src/lib/validate-pr-metadata.ts +14 -5
- package/packages/azdo/src/mcp-server.ts +53 -5
- package/packages/azdo/src/tool-dispatch.ts +53 -4
- package/packages/azdo/src/workflow-ladder.csv +125 -107
- package/packages/azdo/src/workflow-rules.ts +254 -97
- package/packages/repo-controls/README.md +24 -11
- package/packages/repo-controls/assets/scaffold/docs/AGENTS.md +5 -5
- package/packages/repo-controls/assets/scaffold/plans/AGENTS.md +42 -13
- package/packages/repo-controls/assets/scaffold/root/AGENTS.md +60 -11
- package/packages/repo-controls/assets/scaffold/root/CONTRIBUTING.md +28 -0
- package/packages/repo-controls/assets/scaffold/root/INVARIANTS.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +0 -11
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +4 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +1 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +3 -22
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +39 -182
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/fixtures/open-work-cap-clean/plans/features/az601-clean/intent.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +90 -321
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plan_metadata.py +31 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/check.py +282 -54
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/design.md +35 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/file-map-reference.md +19 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/intent.md +25 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/items/az351-restore-entrypoint.md +25 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/requirements.md +44 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-violation/plans/features/az347-test-coverage/requirements.md +44 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +646 -53
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +3 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +1 -12
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +1 -1
- package/packages/repo-controls/src/cli.ts +23 -5
- package/packages/repo-controls/src/constants.ts +2 -15
- package/packages/repo-controls/src/install.ts +15 -6
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Run reports and evidence
|
|
2
|
+
|
|
3
|
+
Part of [`workitems-process`](../SKILL.md). Tags: **[pending X]** = change row `X`, not built.
|
|
4
|
+
|
|
5
|
+
## Principle
|
|
6
|
+
|
|
7
|
+
- **The dispatcher parses nothing and writes nothing.** Whether a target is done is decided from the board and the PR (the target's done proof), not from a comment.
|
|
8
|
+
- Evidence is for humans, for the next sub-agent, and for a resumed run. It binds to what it ran against: the head SHA, or plan revision N. A later commit voids earlier test and review evidence for what it touches; the Feature-final check at the final head is what the merge relies on.
|
|
9
|
+
- **Evidence is the item comment plus the PR.** The run-level report is the run's last comment: on the Feature for a planning or implementation run, on the Bug for a per-Bug run, never on a PBI. Its first line is one machine line, `adl-evidence v1 <run> <verdict> <head_sha>` (e.g. `adl-evidence v1 implementation MERGED 3f9c2ab`), then the report.
|
|
10
|
+
|
|
11
|
+
## Where evidence lives
|
|
12
|
+
|
|
13
|
+
| Record | Written by | Where |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| Sub-agent report | the sub-agent returns it; the **lead** posts it | item comment (Feature comment for the Feature-final and finalize lanes) |
|
|
16
|
+
| Run report, planning and implementation | the lead (`planner`, `lead`) | one comment as its last action: on the Feature, or on the Bug in a per-Bug run |
|
|
17
|
+
| Run report, `workitem-triage` | `triager` | the activity log (`adl activity add`, pending A1) plus one comment on each touched item |
|
|
18
|
+
| PR body | the lead; on an implementation PR the text comes from `writer` | the PR, five sections ([`ado-and-git.md` § Git](ado-and-git.md#7-git)) |
|
|
19
|
+
| Plan snapshot, implementation report | content from the lead; attached by `pr_create_or_update` | Feature attachments ([`ado-and-git.md` § Plan files](ado-and-git.md#4-plan-files)) |
|
|
20
|
+
| Review findings | review sub-agents via the lead | item comments and the implementation report; never PR threads or votes |
|
|
21
|
+
|
|
22
|
+
- Reading earlier comments needs **T1 (pending)**. A resumed run that cannot read them works from the board states, `git log` and the PR, and re-runs any verify or review whose head is not the current head.
|
|
23
|
+
- Evidence never holds secrets: links, repo-relative paths, commands with exit codes, run ids, SHAs.
|
|
24
|
+
|
|
25
|
+
## Sub-agent report (the common shape)
|
|
26
|
+
|
|
27
|
+
````yaml
|
|
28
|
+
lane: validate | design-update | implement | fix-ci | verify | verify-final | review-code | review-architecture | finalize | review-plan-architect | review-plan-critic
|
|
29
|
+
target: <item id | feature id>
|
|
30
|
+
base_sha: <origin/integration sha>
|
|
31
|
+
head_sha: <worktree HEAD the report applies to; plan reviews name revision N>
|
|
32
|
+
verdict: <set per lane, below>
|
|
33
|
+
findings: # required for every non-pass verdict
|
|
34
|
+
- id: F1
|
|
35
|
+
severity: critical | high | medium | low
|
|
36
|
+
where: path:line
|
|
37
|
+
what: "<issue and risk>"
|
|
38
|
+
fix: "<concrete change>"
|
|
39
|
+
artifacts: # files reviewed, commands with exit codes, run ids, AC-n -> test map, commit SHAs
|
|
40
|
+
- ...
|
|
41
|
+
````
|
|
42
|
+
|
|
43
|
+
A negative verdict with empty `findings`, or a finding without `where` and `fix`, is invalid. `REQUEST_CHANGES` and `BLOCK` send the item back into the loop; `WATCH` and medium or low findings are recorded, not blocking. The Critic's verdict for revision N counts only after the Architect's review of the same revision.
|
|
44
|
+
|
|
45
|
+
## Verdicts by lane and by run
|
|
46
|
+
|
|
47
|
+
| Lane or run | Verdicts |
|
|
48
|
+
|---|---|
|
|
49
|
+
| plan review, architect and critic | `APPROVE` · `ITERATE` · `REJECT` |
|
|
50
|
+
| validate (`design.md` and its `file-map-reference.md`) | `FRESH` · `DRIFT` (exact delta) |
|
|
51
|
+
| design update (planner sub-agent) | `UPDATED` |
|
|
52
|
+
| implement | `DONE` · `DRIFT` · `PARK` |
|
|
53
|
+
| verify, verify-final | `PASS` · `FAIL` |
|
|
54
|
+
| review, code | `APPROVE` · `REQUEST_CHANGES` |
|
|
55
|
+
| review, architecture | `CLEAR` · `WATCH` · `BLOCK` |
|
|
56
|
+
| finalize | `DONE` · `REWORK` (finding `docs-missing`) |
|
|
57
|
+
| fix-ci | `FIXED` · `INFRA` |
|
|
58
|
+
| run: workitem-triage | `TRIAGED` |
|
|
59
|
+
| run: planning | `DONE` (every in-scope item at Awaiting Approval and the planning PR raised; the report names the critic outcome, `APPROVE` or the cap) · `PARK` (the work is obsolete: the planner moved the in-scope items to Parked for Removal, each with a reason comment; G3 decides) |
|
|
60
|
+
| run: implementation | `MERGED` · `PR_OPEN` (CI unfinished at session end; the next dispatch resumes) |
|
|
61
|
+
|
|
62
|
+
No lane or run has a `BLOCKED` verdict. A failed precondition, a tool refusal or a cap follows its path in [No block](../SKILL.md#no-block).
|
|
63
|
+
|
|
64
|
+
## Run report content
|
|
65
|
+
|
|
66
|
+
Posted by the lead as its last action, then the one-line handoff `<target> <verdict> <key kind> <id> @ <sha>`.
|
|
67
|
+
|
|
68
|
+
| Target | The report holds |
|
|
69
|
+
|---|---|
|
|
70
|
+
| workitem-triage | per swept item: applied, proposed (comment posted, item unchanged) or unchanged, with reasoning and evidence (`file:line`, commit, test output); split-off ids; rolled-up Feature ids; Bugs filed through `report-bug`; Features at New with no plan yet (informational); base SHA |
|
|
71
|
+
| planning | revision N, baseline SHA, plan hash, review rounds, critic outcome, open findings, planning PR URL, allocated item ids |
|
|
72
|
+
| implementation | per item: final state, commits (`AB#` ids), sub-agent verdicts and head SHAs; design updates; Feature-final result at the final head; CI rounds; PR link; verdict |
|
|
73
|
+
|
|
74
|
+
Every negative result names `where` and `fix`.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Work item states, moves and links
|
|
2
|
+
|
|
3
|
+
Part of [`workitems-process`](../SKILL.md). Tags: **[live]** = enforced today; **[pending X]** = change row `X`, not built. Never act as if a pending change is live.
|
|
4
|
+
|
|
5
|
+
## 1. PBI states
|
|
6
|
+
|
|
7
|
+
| State | Owner | Entered when | Exit |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| New | planning run | the item is allocated under its Feature | → In Planning |
|
|
10
|
+
| In Planning | planning run | the planner moves it, after allocating any new PBIs and before writing the files | → Awaiting Approval |
|
|
11
|
+
| Awaiting Approval | Tarun (**G1**) | the planning PR is raised | → Approved, In Planning (rework) or New (requeue) |
|
|
12
|
+
| Approved | implementation run | Tarun approves the plan revision | → Design Validation |
|
|
13
|
+
| Design Validation | implementation run | the lead's first act; re-entered from In Implementation on drift | → In Implementation |
|
|
14
|
+
| In Implementation, In Testing, In Review | implementation run | the loop | the loop |
|
|
15
|
+
| Updating Docs | implementation run | the loop; the implementation PR is raised | the loop, or → Done |
|
|
16
|
+
| Done | — | the Feature's implementation PR, linked to the item, merges into `integration` | terminal |
|
|
17
|
+
| Parked for Removal | Tarun (**G3**) | a lead parks the item with a reason | → Removed, or → New (revive) |
|
|
18
|
+
| Removed | — | Tarun confirms the removal | terminal |
|
|
19
|
+
|
|
20
|
+
- Up to Design Validation the order is strict.
|
|
21
|
+
- **The loop is non-linear.** After Design Validation, In Implementation, In Testing, In Review and Updating Docs are free moves in either direction, per PBI. The usual order is In Testing before In Review, so a reviewer sees green code; a default, not a rule.
|
|
22
|
+
- **Fence today [live]:** among the loop states the fence allows only In Review → In Implementation (`workflow-rules.ts:81`). Every other loop move (In Testing → In Implementation, Updating Docs → In Implementation or In Review, the skips) is **[pending F1]**, as is the drift loop-back In Implementation → Design Validation (ADO allows it, the fence does not yet). On a refusal: post the exact text as an item comment and take the path the refusal names; do not work around it.
|
|
23
|
+
- **Drift loops back; it never leaves the run.** In Implementation → Design Validation; the lead re-validates `design.md`; a drifted `design.md` is fixed in the run by a planner sub-agent. Items never go to New or In Planning for drift. Drift that would need an approved `AC-n` changed follows [No block](../SKILL.md#no-block).
|
|
24
|
+
- Later commits void earlier test and review evidence, so the Feature-final check at the final head is what the merge relies on.
|
|
25
|
+
|
|
26
|
+
## 2. Who moves what
|
|
27
|
+
|
|
28
|
+
| Move | Who | Status |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| New → In Planning | planning lead: after allocating any new PBIs, it moves every in-scope PBI (existing and new), then writes the files; all are at In Planning before the planning PR is raised | live |
|
|
31
|
+
| In Planning → Awaiting Approval | `pr_create_or_update`, when it raises the planning PR | pending P2 |
|
|
32
|
+
| Awaiting Approval → Approved / In Planning (rework) / New (requeue) | Tarun (G1) | live |
|
|
33
|
+
| Approved → Design Validation | implementation lead, first act | live |
|
|
34
|
+
| Design Validation → In Implementation | implementation lead, when an item's build starts | live |
|
|
35
|
+
| Free moves among the four loop states | implementation lead | pending F1 |
|
|
36
|
+
| In Implementation → Design Validation | implementation lead, on mid-loop drift | pending F1 |
|
|
37
|
+
| Loop → Updating Docs | `pr_create_or_update`, when it raises the implementation PR | pending P2 |
|
|
38
|
+
| Updating Docs → Done | ADO completion of the linked implementation PR (`transitionWorkItems`) | pending P1, P2, V2 |
|
|
39
|
+
| Any non-terminal → Parked for Removal | any lead, with a reason | live |
|
|
40
|
+
| Parked for Removal → Removed | Tarun (G3) | live |
|
|
41
|
+
| Parked for Removal → New (revive) | Tarun | human-only; the fence lets agents make it today, and agents never do |
|
|
42
|
+
|
|
43
|
+
- Both G1 rejection paths force a new G1 pass.
|
|
44
|
+
- **Agents never set Done, Approved or Removed.** Done follows the merge of the implementation PR, which `pr_create_or_update` links to the items ([`ado-and-git.md` § PR wiring](ado-and-git.md#6-pr-wiring)). A planning PR's merge never moves items.
|
|
45
|
+
- **Agents pass nothing for the PR-time moves** and make none of them.
|
|
46
|
+
- Feature roll-ups are `workitem-triage`'s (§3).
|
|
47
|
+
|
|
48
|
+
## 3. Feature states
|
|
49
|
+
|
|
50
|
+
`New → In Progress → Awaiting Release → Done`, plus `Removed`. Linear, one step at a time, never backward; Done only from Awaiting Release **[pending F3, F4]**.
|
|
51
|
+
|
|
52
|
+
| State | Entered when | Moved by |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| New | the Feature is created, only at New | — |
|
|
55
|
+
| In Progress | at least one child has left New | `workitem-triage` roll-up |
|
|
56
|
+
| Awaiting Release | every child is Done or Removed (its implementation PR merged into `integration`) | `workitem-triage` roll-up |
|
|
57
|
+
| Done | the `integration → main` PR carrying the children is merged (G2) | `workitem-triage` roll-up |
|
|
58
|
+
| Removed | Tarun removes the Feature | Tarun, human-only |
|
|
59
|
+
|
|
60
|
+
- **"Closed" = Awaiting Release or later.** No child may be added to a closed Feature **[pending L1]**; work found later goes into a new Feature or a Fixes Bug.
|
|
61
|
+
- **`Fixes to closed Features`** (one per Epic, 548–554) stays **In Progress** permanently; agents may not move it **[pending F5]**. It is exempt from the predecessor rule and the roll-ups.
|
|
62
|
+
|
|
63
|
+
## 4. Links
|
|
64
|
+
|
|
65
|
+
- **Parent:** a PBI or Bug's parent is its Feature; a Feature's parent is an Epic. In an item file, `feature:` is the Feature's full board URL.
|
|
66
|
+
- **Predecessors live on Features only:** at least 1, except the very first Feature. Soft warning first, hard refusal later **[pending L2]**. A Feature is **ready** when every predecessor is at Awaiting Release or Done.
|
|
67
|
+
- **PBIs carry no predecessors** **[pending L3]**; item order inside a Feature is the implementation lead's choice.
|
|
68
|
+
- **Fixes Bugs are the one exception:** a Bug under `Fixes to closed Features` has a predecessor (another Bug there) and a **Related** link to the Responsible Feature, in any state (a red pipeline's Responsible Feature can be open) **[pending L4]**. The first Bug in a Fixes Feature has no predecessor, and none is accepted; every later Bug needs one.
|
|
69
|
+
- **Findings go through `report-bug`:** a defect in an open Feature (before Awaiting Release) updates that Feature's PBIs and creates no Bug; a defect in a closed Feature creates a Bug under that Epic's `Fixes to closed Features`.
|
|
70
|
+
|
|
71
|
+
## 5. Bug states
|
|
72
|
+
|
|
73
|
+
Every Bug is a Fixes Bug under a `Fixes to closed Features` Feature. **Never planned:** no In Planning, Awaiting Approval or Design Validation, no plan hash, no `requirements.md`, `design.md` or `file-map-reference.md`.
|
|
74
|
+
|
|
75
|
+
`New → Approved → In Reproduction → In Fixing ↔ In Testing ↔ In Review ↔ Updating Docs → Done`, plus `Parked for Removal → Removed` and `Parked for Removal → New`.
|
|
76
|
+
|
|
77
|
+
| Move | Who |
|
|
78
|
+
|---|---|
|
|
79
|
+
| created at New | `report-bug`, on the board only; its Description holds the bugfix shape ([`ado-and-git.md` § Item files](ado-and-git.md#5-item-files)) |
|
|
80
|
+
| New → Approved | Tarun (**G1**), approving that Description; human-only |
|
|
81
|
+
| Approved → In Reproduction | implementation lead, first act of the per-Bug run **[pending L5, X2]** |
|
|
82
|
+
| In Reproduction → In Fixing | implementation lead, once the executor (reproduce mode) has committed the item file and the regression test marked as an expected failure (the framework's xfail or `test.fails` form), with its unmarked run red on the base posted on the Bug as evidence; the reproduce commit stays green, and the fix commit removes the mark |
|
|
83
|
+
| Free moves among In Fixing, In Testing, In Review, Updating Docs | implementation lead (the PBI loop with In Fixing in place of In Implementation) |
|
|
84
|
+
| Loop → Updating Docs | `pr_create_or_update`, when it raises the Bug's implementation PR |
|
|
85
|
+
| Updating Docs → Done | ADO completion of the linked implementation PR; agents never move to Done |
|
|
86
|
+
| In Reproduction → Parked for Removal | implementation lead, when the Bug won't reproduce: it posts what was tried as a comment on the Bug |
|
|
87
|
+
| Any non-terminal → Parked for Removal | any lead, with a reason (New and Approved included, to park a duplicate) |
|
|
88
|
+
| Parked for Removal → Removed | Tarun (**G3**), human-only |
|
|
89
|
+
| Parked for Removal → New (revive) | Tarun, human-only |
|
|
90
|
+
|
|
91
|
+
- **Per-Bug run:** branch `fix/az<bug id>-<slug>`. The executor's first commit is the Bug's item file (the Description's sections plus `## Predecessors` mirroring the board link), with its LEDGER row `az<id>-bug`; then the regression test. **The reproduce commit stays green.** The executor runs the regression test unmarked on the base and proves it red; that run output goes into a comment on the Bug as evidence (the executor returns it, the lead posts it). It commits the test marked as an expected failure (the framework's xfail or `test.fails` form), so lint, typecheck, build and the suite pass. The fix commit removes the expected-failure mark, so the same test now passes normally. Every commit stays independently green, with no exception. The lead writes no files.
|
|
92
|
+
- Every other Bug move is refused. The fence's Bug table is **[pending F9]**.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: write-feature
|
|
3
|
+
description: Live, human-attended session that creates a Feature on the ADO board, parent Epic chosen by the human and at least one predecessor Feature unless it is the very first, and writes its intent.md in the human's own words, then lands it through a docs branch and PR. Use when Tarun asks to start, create or write up a new Feature or its intent. Never dispatched.
|
|
4
|
+
metadata:
|
|
5
|
+
step: "live"
|
|
6
|
+
role: "session agent with the human"
|
|
7
|
+
states: "Feature:New"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Write Feature (live session)
|
|
11
|
+
|
|
12
|
+
Load `workitems-process` first. This card adds only what the live Feature session does.
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
|
|
16
|
+
- The human starts a new Feature in a session they attend. This is stage 1 of the Feature flow.
|
|
17
|
+
- **Never dispatched.** No dispatch record, no worktree from the dispatcher, no run report. If you were started by the dispatcher, stop: this skill is wrong for the run.
|
|
18
|
+
- Not for planning (`plan-feature`) and not for a Bug (`report-bug`).
|
|
19
|
+
|
|
20
|
+
## Inputs (all from the human)
|
|
21
|
+
|
|
22
|
+
| Input | Rule |
|
|
23
|
+
|---|---|
|
|
24
|
+
| The Feature in their words | Why, Outcome, Constraints, Non-goals; Open questions optional |
|
|
25
|
+
| Parent Epic | **The human chooses.** Never guess, never create |
|
|
26
|
+
| Predecessor Features | At least 1, unless the human says this is the very first Feature |
|
|
27
|
+
| Title and slug | Human confirms both |
|
|
28
|
+
|
|
29
|
+
## Preconditions
|
|
30
|
+
|
|
31
|
+
1. `adl id whoami` reports `agent-tarun`. Mismatch → stop and say so.
|
|
32
|
+
2. You are in a checkout of the repo that will hold the plan, `origin/integration` fetched, clean tree.
|
|
33
|
+
3. The human gave an Epic id. Confirm it parents a Feature: a wrong-typed parent is refused by name at create. Do not read or edit the Epic.
|
|
34
|
+
|
|
35
|
+
## Procedure
|
|
36
|
+
|
|
37
|
+
Ask **one question at a time**. Lead with what you already know.
|
|
38
|
+
|
|
39
|
+
1. **Listen.** Take the human's words. Do not rewrite, extend or "improve" them. Do not add a solution.
|
|
40
|
+
2. **Fill gaps, not prose.** For each required section the human left empty (`## Why`, `## Outcome`, `## Constraints`, `## Non-goals`), ask for it. `## Open questions` is optional; add it only if the human has some.
|
|
41
|
+
3. **Predecessors.** List candidate Features (`workitem_list_or_get --type Feature`) and let the human pick. A Feature needs at least 1 predecessor Feature; only the very first has none. The human says which case applies; you do not infer it. Enforcement is soft then hard: pending L2 in adl-agent-control.
|
|
42
|
+
4. **Allocate the Feature on the board first.** `workitem_create_or_update --type Feature --title "<title>" --parent-id <epic> --predecessors <ids> --description "<Why, Outcome, Constraints, Non-goals>"`. State stays New (the tool refuses any other create state: pending F3). Read it back: type Feature, state New, parent = the Epic, predecessors present. A refusal is the answer: report the exact text, stop, create nothing.
|
|
43
|
+
- **Description = copy of `intent.md`.** Pass the human's own `## Why`, `## Outcome`, `## Constraints`, `## Non-goals` text, verbatim and identical to what step 5 writes, as `--description` at create. Written once, here. Agents never edit it afterwards, the same as `intent.md`. The approved plan lives in the `plan-r<N>-<sha7>.md` attachment, not in the Description.
|
|
44
|
+
- Do not touch Features 548-554 ("Fixes to closed Features"); their description is already set.
|
|
45
|
+
- Never create an Epic. Never set `epic:` from tool output; it is the human's value.
|
|
46
|
+
5. **Write `plans/features/az<id>-<slug>/intent.md`.** The id is allocated before the file exists. Layout below. No other file in the folder.
|
|
47
|
+
6. **Read it back to the human.** Commit only after an explicit yes. After that, agents never edit `intent.md`; only the human does.
|
|
48
|
+
7. **Land it.** An ordinary docs change. You create the branch `docs/az<id>-<slug>` from `origin/integration`: the one exception to "agents never create a branch" ([ado-and-git.md](../workitems-process/references/ado-and-git.md#7-git)). Add the `plans/LEDGER.md` row `az<id>-intent` ([LEDGER](../workitems-process/references/ado-and-git.md#4-plan-files)). Commit `docs(plans): add intent for az<id> <slug>`. Push with plain `git`. Open the PR to `integration` with `pr_create_or_update`, with the five PR body sections ([ado-and-git.md](../workitems-process/references/ado-and-git.md#7-git)); `## Test plan` and `## Security impact considered` say "none (docs-only)". The branch has no `-plan` suffix and the Feature has no item at Approved or later (PBIs the human already made sit at New), so this is an ordinary PR: the tool links nothing, moves nothing, attaches nothing, and it needs no implementation report ([PR wiring](../workitems-process/references/ado-and-git.md#6-pr-wiring)). Never rebase or force-push. No reviewer, no vote ([Human gates](../workitems-process/SKILL.md#human-gates)).
|
|
49
|
+
8. **Stop.** Report: Feature URL, branch, PR URL. Say the Feature is at New and the planning trigger ([Targets and triggers](../workitems-process/SKILL.md#targets-and-triggers)) fires on it once the PR has merged. Do not start planning.
|
|
50
|
+
|
|
51
|
+
## `intent.md` layout
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
---
|
|
55
|
+
type: intent
|
|
56
|
+
title: <Feature title>
|
|
57
|
+
status: New
|
|
58
|
+
work_item: https://dev.azure.com/<org>/<project>/_workitems/edit/<feature id>
|
|
59
|
+
last_update: <YYYY-MM-DDTHH:MM:SSZ>
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Why
|
|
63
|
+
- <the human's words>
|
|
64
|
+
|
|
65
|
+
## Outcome
|
|
66
|
+
- <what is true when it is done>
|
|
67
|
+
|
|
68
|
+
## Constraints
|
|
69
|
+
- <...>
|
|
70
|
+
|
|
71
|
+
## Non-goals
|
|
72
|
+
- <...>
|
|
73
|
+
|
|
74
|
+
## Open questions
|
|
75
|
+
- <optional; omit the section if empty>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- Required sections: Why, Outcome, Constraints, Non-goals. Short bullets, the human's own wording.
|
|
79
|
+
- `status` mirrors the Feature's board state (New). `work_item` URL id equals the folder id. Optional `sources:` only if the human names documents.
|
|
80
|
+
- The check for these sections is pending R4; the Feature-state `status` values are pending R1.
|
|
81
|
+
- Owner of the layout: [ado-and-git.md](../workitems-process/references/ado-and-git.md#4-plan-files).
|
|
82
|
+
|
|
83
|
+
## Stop rules
|
|
84
|
+
|
|
85
|
+
- Epic not given, or the human cannot say whether a predecessor exists → stop and ask; never default.
|
|
86
|
+
- A refused create or a failed read-back → stop with the exact error; no file before the id.
|
|
87
|
+
- Same command fails twice for the same reason → stop and report.
|
|
88
|
+
|
|
89
|
+
## Never
|
|
90
|
+
|
|
91
|
+
- Never write, extend or paraphrase the human's intent for them.
|
|
92
|
+
- Never choose the Epic or a predecessor.
|
|
93
|
+
- Never create PBIs here; planning creates them. PBIs the human already made stay at New and planning reads them.
|
|
94
|
+
- Never move a state, never plan, never post a run report.
|
|
95
|
+
- Never edit `intent.md` after the human approved it.
|
|
@@ -27,5 +27,12 @@ export interface DeploySkillsResult {
|
|
|
27
27
|
*/
|
|
28
28
|
readonly retiredRemovals: readonly string[];
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* True when `skillDirAbs` holds exactly the asset skill's files — same
|
|
32
|
+
* relative paths, same bytes, nothing extra. Such a folder carries no user
|
|
33
|
+
* content, so deploy may adopt it (Tarun, 2026-10-01).
|
|
34
|
+
*/
|
|
35
|
+
export declare function folderIdenticalToAsset(skillDirAbs: string, assetDirAbs: string, sourceFiles: readonly string[]): boolean;
|
|
36
|
+
export declare function removeEmptyParents(root: string, dir: string): void;
|
|
30
37
|
export declare function deploySkills(options: DeploySkillsOptions): DeploySkillsResult;
|
|
31
38
|
//# sourceMappingURL=deploy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"AAiCA,OAAO,EAAE,KAAK,aAAa,EAA+B,MAAM,cAAc,CAAC;AAI/E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,6KAA6K;IAC7K,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC,+JAA+J;IAC/J,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;IAC7C,8JAA8J;IAC9J,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CASxH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAWlE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CA2M7E"}
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
* When `profile.legacyLock` names a lock the OLD repo-controls engine
|
|
18
18
|
* left behind, a same-name folder it fully wrote (per legacy-lock.ts) is
|
|
19
19
|
* taken over on sight rather than reported as a conflict — see
|
|
20
|
-
* legacy-lock.ts for the exact ownership rule and lock rewrite.
|
|
20
|
+
* legacy-lock.ts for the exact ownership rule and lock rewrite. A legacy
|
|
21
|
+
* folder whose skill retired from assets/ is removed under the same
|
|
22
|
+
* ownership rule (never a hand-modified folder).
|
|
21
23
|
*
|
|
22
24
|
* Fails loud: assets/target validation, an invalid deploy profile, an
|
|
23
25
|
* invalid adl-config.toml subset, or an unwritable target all throw. There
|
|
@@ -37,7 +39,7 @@ import { listSourceSkillNames } from "./skill-meta.js";
|
|
|
37
39
|
* relative paths, same bytes, nothing extra. Such a folder carries no user
|
|
38
40
|
* content, so deploy may adopt it (Tarun, 2026-10-01).
|
|
39
41
|
*/
|
|
40
|
-
function folderIdenticalToAsset(skillDirAbs, assetDirAbs, sourceFiles) {
|
|
42
|
+
export function folderIdenticalToAsset(skillDirAbs, assetDirAbs, sourceFiles) {
|
|
41
43
|
let targetFiles;
|
|
42
44
|
try {
|
|
43
45
|
targetFiles = walkFiles(skillDirAbs);
|
|
@@ -49,7 +51,7 @@ function folderIdenticalToAsset(skillDirAbs, assetDirAbs, sourceFiles) {
|
|
|
49
51
|
return false;
|
|
50
52
|
return sourceFiles.every((file) => Buffer.compare(readFileSync(join(skillDirAbs, file)), readFileSync(join(assetDirAbs, file))) === 0);
|
|
51
53
|
}
|
|
52
|
-
function removeEmptyParents(root, dir) {
|
|
54
|
+
export function removeEmptyParents(root, dir) {
|
|
53
55
|
let current = dir;
|
|
54
56
|
while (current !== root && current.startsWith(root)) {
|
|
55
57
|
if (!existsSync(current)) {
|
|
@@ -91,7 +93,45 @@ export function deploySkills(options) {
|
|
|
91
93
|
// conflict, with a reason naming what disqualified it.
|
|
92
94
|
const takeoverFiles = new Set();
|
|
93
95
|
const takeoverConflictReasons = new Map();
|
|
96
|
+
/** `${folder}/${skill}` in a retired folder that the legacy lock wrote and assets/ retired — removed by the retired-folder cleanup below. */
|
|
97
|
+
const legacyRetiredInRetired = new Set();
|
|
94
98
|
if (legacyLock !== null) {
|
|
99
|
+
// Legacy retirement: a folder the old engine fully wrote (per the
|
|
100
|
+
// lock) whose skill no longer ships in assets/ is folded into
|
|
101
|
+
// takeoverFiles so the removal pass below deletes it — the header's
|
|
102
|
+
// "dropped from assets/ is removed" promise extended to old-engine
|
|
103
|
+
// folders. A repo-subset exclusion keeps the folder (the subset only
|
|
104
|
+
// limits what THIS deploy writes, it does not retract skills assets
|
|
105
|
+
// still ships). A folder failing the ownership check (hand-modified,
|
|
106
|
+
// extra file) is left untouched: it is becoming user-owned, the same
|
|
107
|
+
// disposition as the takeover conflict case. In retired folders there
|
|
108
|
+
// is no takeover pass: the folder is only recorded, and the
|
|
109
|
+
// retired-folder cleanup removes it under the same conditions.
|
|
110
|
+
const legacyRetired = (folder, foldIntoTakeover) => {
|
|
111
|
+
const prefix = `${folder}/`;
|
|
112
|
+
for (const skill of new Set([...legacyLock.files.keys()]
|
|
113
|
+
.filter((relPath) => relPath.startsWith(prefix))
|
|
114
|
+
.map((relPath) => relPath.slice(prefix.length).split("/", 1)[0]))) {
|
|
115
|
+
if (availableSkills.includes(skill))
|
|
116
|
+
continue; // still shipped — selected or subset path owns it
|
|
117
|
+
const skillDirRel = `${folder}/${skill}`;
|
|
118
|
+
const skillDirAbs = join(targetRepo, skillDirRel);
|
|
119
|
+
if (!existsSync(skillDirAbs))
|
|
120
|
+
continue;
|
|
121
|
+
if (manifest.files.some((file) => file.startsWith(`${skillDirRel}/`)))
|
|
122
|
+
continue; // already ours
|
|
123
|
+
const check = checkLegacyOwnership(legacyLock, targetRepo, skillDirRel, skillDirAbs);
|
|
124
|
+
if (!check.owned)
|
|
125
|
+
continue;
|
|
126
|
+
if (foldIntoTakeover) {
|
|
127
|
+
for (const relFile of walkFiles(skillDirAbs))
|
|
128
|
+
takeoverFiles.add(`${skillDirRel}/${relFile}`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
legacyRetiredInRetired.add(skillDirRel);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
95
135
|
for (const surface of profile.surfaces) {
|
|
96
136
|
for (const skill of selectedSkills) {
|
|
97
137
|
const skillDirRel = `${surface.folder}/${skill}`;
|
|
@@ -109,7 +149,10 @@ export function deploySkills(options) {
|
|
|
109
149
|
takeoverConflictReasons.set(skillDirRel, check.reason);
|
|
110
150
|
}
|
|
111
151
|
}
|
|
152
|
+
legacyRetired(surface.folder, true);
|
|
112
153
|
}
|
|
154
|
+
for (const folder of retiredFolders(profile))
|
|
155
|
+
legacyRetired(folder, false);
|
|
113
156
|
}
|
|
114
157
|
const manifestFiles = new Set([...manifest.files, ...takeoverFiles]);
|
|
115
158
|
const adopted = [];
|
|
@@ -195,8 +238,12 @@ export function deploySkills(options) {
|
|
|
195
238
|
if (!existsSync(folderAbs))
|
|
196
239
|
continue;
|
|
197
240
|
for (const name of directoryNames(folderAbs)) {
|
|
198
|
-
|
|
199
|
-
|
|
241
|
+
// Ours to remove when the skill still ships in assets/ (a stale
|
|
242
|
+
// duplicate of a live skill) or the legacy lock proves the old
|
|
243
|
+
// engine wrote this copy of a now-retired skill. Anything else was
|
|
244
|
+
// never this package's to manage — left byte-for-byte.
|
|
245
|
+
if (!availableSkillSet.has(name) && !legacyRetiredInRetired.has(`${folder}/${name}`))
|
|
246
|
+
continue;
|
|
200
247
|
if (!dryRun)
|
|
201
248
|
removeDirRecursive(join(folderAbs, name));
|
|
202
249
|
retiredRemovals.push(`${folder}/${name}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
* When `profile.legacyLock` names a lock the OLD repo-controls engine
|
|
18
18
|
* left behind, a same-name folder it fully wrote (per legacy-lock.ts) is
|
|
19
19
|
* taken over on sight rather than reported as a conflict — see
|
|
20
|
-
* legacy-lock.ts for the exact ownership rule and lock rewrite.
|
|
20
|
+
* legacy-lock.ts for the exact ownership rule and lock rewrite. A legacy
|
|
21
|
+
* folder whose skill retired from assets/ is removed under the same
|
|
22
|
+
* ownership rule (never a hand-modified folder).
|
|
21
23
|
*
|
|
22
24
|
* Fails loud: assets/target validation, an invalid deploy profile, an
|
|
23
25
|
* invalid adl-config.toml subset, or an unwritable target all throw. There
|
|
@@ -69,7 +71,7 @@ export interface DeploySkillsResult {
|
|
|
69
71
|
* relative paths, same bytes, nothing extra. Such a folder carries no user
|
|
70
72
|
* content, so deploy may adopt it (Tarun, 2026-10-01).
|
|
71
73
|
*/
|
|
72
|
-
function folderIdenticalToAsset(skillDirAbs: string, assetDirAbs: string, sourceFiles: readonly string[]): boolean {
|
|
74
|
+
export function folderIdenticalToAsset(skillDirAbs: string, assetDirAbs: string, sourceFiles: readonly string[]): boolean {
|
|
73
75
|
let targetFiles: readonly string[];
|
|
74
76
|
try {
|
|
75
77
|
targetFiles = walkFiles(skillDirAbs);
|
|
@@ -80,7 +82,7 @@ function folderIdenticalToAsset(skillDirAbs: string, assetDirAbs: string, source
|
|
|
80
82
|
return sourceFiles.every((file) => Buffer.compare(readFileSync(join(skillDirAbs, file)), readFileSync(join(assetDirAbs, file))) === 0);
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
function removeEmptyParents(root: string, dir: string): void {
|
|
85
|
+
export function removeEmptyParents(root: string, dir: string): void {
|
|
84
86
|
let current = dir;
|
|
85
87
|
while (current !== root && current.startsWith(root)) {
|
|
86
88
|
if (!existsSync(current)) {
|
|
@@ -125,7 +127,42 @@ export function deploySkills(options: DeploySkillsOptions): DeploySkillsResult {
|
|
|
125
127
|
// conflict, with a reason naming what disqualified it.
|
|
126
128
|
const takeoverFiles = new Set<string>();
|
|
127
129
|
const takeoverConflictReasons = new Map<string, string>();
|
|
130
|
+
/** `${folder}/${skill}` in a retired folder that the legacy lock wrote and assets/ retired — removed by the retired-folder cleanup below. */
|
|
131
|
+
const legacyRetiredInRetired = new Set<string>();
|
|
128
132
|
if (legacyLock !== null) {
|
|
133
|
+
// Legacy retirement: a folder the old engine fully wrote (per the
|
|
134
|
+
// lock) whose skill no longer ships in assets/ is folded into
|
|
135
|
+
// takeoverFiles so the removal pass below deletes it — the header's
|
|
136
|
+
// "dropped from assets/ is removed" promise extended to old-engine
|
|
137
|
+
// folders. A repo-subset exclusion keeps the folder (the subset only
|
|
138
|
+
// limits what THIS deploy writes, it does not retract skills assets
|
|
139
|
+
// still ships). A folder failing the ownership check (hand-modified,
|
|
140
|
+
// extra file) is left untouched: it is becoming user-owned, the same
|
|
141
|
+
// disposition as the takeover conflict case. In retired folders there
|
|
142
|
+
// is no takeover pass: the folder is only recorded, and the
|
|
143
|
+
// retired-folder cleanup removes it under the same conditions.
|
|
144
|
+
const legacyRetired = (folder: string, foldIntoTakeover: boolean) => {
|
|
145
|
+
const prefix = `${folder}/`;
|
|
146
|
+
for (const skill of new Set(
|
|
147
|
+
[...legacyLock!.files.keys()]
|
|
148
|
+
.filter((relPath) => relPath.startsWith(prefix))
|
|
149
|
+
.map((relPath) => relPath.slice(prefix.length).split("/", 1)[0]!),
|
|
150
|
+
)) {
|
|
151
|
+
if (availableSkills.includes(skill)) continue; // still shipped — selected or subset path owns it
|
|
152
|
+
const skillDirRel = `${folder}/${skill}`;
|
|
153
|
+
const skillDirAbs = join(targetRepo, skillDirRel);
|
|
154
|
+
if (!existsSync(skillDirAbs)) continue;
|
|
155
|
+
if (manifest.files.some((file) => file.startsWith(`${skillDirRel}/`))) continue; // already ours
|
|
156
|
+
|
|
157
|
+
const check = checkLegacyOwnership(legacyLock!, targetRepo, skillDirRel, skillDirAbs);
|
|
158
|
+
if (!check.owned) continue;
|
|
159
|
+
if (foldIntoTakeover) {
|
|
160
|
+
for (const relFile of walkFiles(skillDirAbs)) takeoverFiles.add(`${skillDirRel}/${relFile}`);
|
|
161
|
+
} else {
|
|
162
|
+
legacyRetiredInRetired.add(skillDirRel);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
129
166
|
for (const surface of profile.surfaces) {
|
|
130
167
|
for (const skill of selectedSkills) {
|
|
131
168
|
const skillDirRel = `${surface.folder}/${skill}`;
|
|
@@ -140,7 +177,10 @@ export function deploySkills(options: DeploySkillsOptions): DeploySkillsResult {
|
|
|
140
177
|
takeoverConflictReasons.set(skillDirRel, check.reason!);
|
|
141
178
|
}
|
|
142
179
|
}
|
|
180
|
+
|
|
181
|
+
legacyRetired(surface.folder, true);
|
|
143
182
|
}
|
|
183
|
+
for (const folder of retiredFolders(profile)) legacyRetired(folder, false);
|
|
144
184
|
}
|
|
145
185
|
|
|
146
186
|
const manifestFiles = new Set([...manifest.files, ...takeoverFiles]);
|
|
@@ -234,7 +274,11 @@ export function deploySkills(options: DeploySkillsOptions): DeploySkillsResult {
|
|
|
234
274
|
if (!existsSync(folderAbs)) continue;
|
|
235
275
|
|
|
236
276
|
for (const name of directoryNames(folderAbs)) {
|
|
237
|
-
|
|
277
|
+
// Ours to remove when the skill still ships in assets/ (a stale
|
|
278
|
+
// duplicate of a live skill) or the legacy lock proves the old
|
|
279
|
+
// engine wrote this copy of a now-retired skill. Anything else was
|
|
280
|
+
// never this package's to manage — left byte-for-byte.
|
|
281
|
+
if (!availableSkillSet.has(name) && !legacyRetiredInRetired.has(`${folder}/${name}`)) continue;
|
|
238
282
|
if (!dryRun) removeDirRecursive(join(folderAbs, name));
|
|
239
283
|
retiredRemovals.push(`${folder}/${name}`);
|
|
240
284
|
}
|