@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.35 → 0.1.46
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 +3 -11
- package/bin/setup +15 -15
- package/package.json +1 -1
- package/packages/agent-hooks/deploy-profile.json +1 -1
- package/packages/agent-hooks/package.json +1 -1
- package/packages/agent-hooks/src/main.ts +23 -2
- 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 +22 -12
- 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/adl-run-required.ts +11 -5
- package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +18 -5
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +30 -25
- package/packages/agent-hooks/src/rules/impl/git-core.ts +4 -8
- package/packages/agent-hooks/src/rules/impl/git-target.ts +5 -0
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +4 -2
- package/packages/agent-hooks/src/rules/impl/tool-frontend.ts +230 -11
- package/packages/agent-hooks/src/rules/registry.ts +11 -2
- package/packages/agent-hooks/src/rules/shell/git-identity.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/invocation.ts +14 -2
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +10 -7
- package/packages/agent-settings/assets/TARUN-GLOBAL-AGENTS-INSTRUCTIONS.md +2 -2
- package/packages/agent-settings/package.json +1 -1
- package/packages/agent-settings/src/deploy/agents-deploy.ts +19 -1
- package/packages/agent-settings/src/deploy/index.ts +1 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +4 -6
- 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 +150 -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 +90 -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/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 +64 -0
- package/packages/agent-skills/assets/verify-item/SKILL.md +71 -0
- package/packages/agent-skills/assets/wayfinder/SKILL.md +1 -1
- package/packages/agent-skills/assets/workitems-process/SKILL.md +145 -0
- package/packages/agent-skills/assets/workitems-process/references/ado-and-git.md +227 -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 +94 -0
- package/packages/agent-skills/dist/deploy.d.ts +52 -0
- package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
- package/packages/agent-skills/dist/deploy.js +218 -7
- package/packages/agent-skills/dist/deploy.js.map +1 -1
- package/packages/agent-skills/dist/index.d.ts +1 -1
- package/packages/agent-skills/dist/index.d.ts.map +1 -1
- package/packages/agent-skills/dist/index.js +1 -1
- package/packages/agent-skills/dist/index.js.map +1 -1
- package/packages/agent-skills/package.json +1 -1
- package/packages/agent-skills/src/deploy.ts +288 -6
- package/packages/agent-skills/src/index.ts +10 -1
- package/packages/azdo/README.md +13 -4
- package/packages/azdo/bunfig.toml +6 -0
- package/packages/azdo/package.json +1 -1
- 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 +109 -0
- package/packages/azdo/src/azdo-pl.ts +100 -3
- package/packages/azdo/src/azdo-pr.ts +376 -17
- package/packages/azdo/src/azdo-wit.ts +594 -34
- package/packages/azdo/src/cli.ts +119 -12
- package/packages/azdo/src/lib/client.ts +95 -17
- package/packages/azdo/src/lib/validate-pr-metadata.ts +14 -5
- package/packages/azdo/src/mcp-server.ts +121 -8
- package/packages/azdo/src/tool-dispatch.ts +107 -23
- package/packages/azdo/src/workflow-ladder.csv +125 -107
- package/packages/azdo/src/workflow-rules.ts +254 -97
- package/packages/fleet/src/install-adl-package.ts +4 -3
- package/packages/repo-controls/README.md +12 -4
- package/packages/repo-controls/assets/promote.ts +1 -0
- 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/CONTRIBUTING.md +5 -5
- 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/fixtures/okf-profile-untyped/docs/research/no-type.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-experiment.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-research.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-last-update.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +1 -1
- 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/package.json +1 -1
- package/packages/repo-controls/src/config.ts +21 -2
- package/packages/repo-controls/src/doctor.ts +9 -14
- package/packages/repo-controls/src/findings-ratchet.ts +12 -0
- package/packages/repo-controls/src/hook.ts +61 -4
|
@@ -4,53 +4,58 @@
|
|
|
4
4
|
// Custom.Reviewpassed, Custom.Testspassing, Custom.Docsupdated,
|
|
5
5
|
// Custom.Mergedtointegration) with ordered item states; the flags were
|
|
6
6
|
// removed from the process at the cutover and nothing here reads or writes
|
|
7
|
-
// them. The routes below implement the owner's final state model
|
|
8
|
-
//
|
|
7
|
+
// them. The routes below implement the owner's final state model: PBIs
|
|
8
|
+
// walk the item ladder; Bugs walk their own shorter ladder (F9 — never
|
|
9
|
+
// planned, reproducing before fixing); both are carried as
|
|
10
|
+
// src/workflow-ladder.csv next to this file; the
|
|
9
11
|
// unit test tests/workflow-rules.test.ts asserts the embedded table agrees
|
|
10
12
|
// with that CSV on every type × from × to triple, so the compiled binary
|
|
11
13
|
// needs no file access at runtime. Features and Epics walk no item ladder
|
|
12
14
|
// and are exempt: evaluateWorkflowTransition returns no violations for
|
|
13
|
-
// them.
|
|
15
|
+
// them (the Feature ladder lives in evaluateFeatureTransition).
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
|
-
* The
|
|
17
|
-
* model, plus
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* The fifteen recognized states: the twelve active states of the final
|
|
19
|
+
* model, plus In Reproduction and In Fixing (Bug-only ladder states, F9),
|
|
20
|
+
* plus Committed — retired (UI-hidden, no route references it) but still
|
|
21
|
+
* recognized so a transition touching it is refused with the retired note
|
|
22
|
+
* instead of passing through silently.
|
|
20
23
|
*/
|
|
21
24
|
export const WORKFLOW_STATES = [
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
25
|
+
"New",
|
|
26
|
+
"In Planning",
|
|
27
|
+
"Awaiting Approval",
|
|
28
|
+
"Approved",
|
|
29
|
+
"Design Validation",
|
|
30
|
+
"In Implementation",
|
|
31
|
+
"In Reproduction",
|
|
32
|
+
"In Fixing",
|
|
33
|
+
"In Testing",
|
|
34
|
+
"In Review",
|
|
35
|
+
"Updating Docs",
|
|
36
|
+
"Done",
|
|
37
|
+
"Parked for Removal",
|
|
38
|
+
"Removed",
|
|
39
|
+
"Committed",
|
|
35
40
|
] as const;
|
|
36
41
|
export type WorkflowState = (typeof WORKFLOW_STATES)[number];
|
|
37
42
|
|
|
38
|
-
const GATED_TYPES = [
|
|
43
|
+
const GATED_TYPES = ["Product Backlog Item", "Bug"] as const;
|
|
39
44
|
|
|
40
45
|
/**
|
|
41
46
|
* The main line, in route order — forward only. PBI and Bug share it (no
|
|
42
47
|
* type deltas in the final model).
|
|
43
48
|
*/
|
|
44
49
|
const MAIN_LINE: readonly WorkflowState[] = [
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
"New",
|
|
51
|
+
"In Planning",
|
|
52
|
+
"Awaiting Approval",
|
|
53
|
+
"Approved",
|
|
54
|
+
"Design Validation",
|
|
55
|
+
"In Implementation",
|
|
56
|
+
"In Testing",
|
|
57
|
+
"In Review",
|
|
58
|
+
"Updating Docs",
|
|
54
59
|
];
|
|
55
60
|
const MAIN_LINE_INDEX = new Map<string, number>(MAIN_LINE.map((state, index) => [state, index]));
|
|
56
61
|
|
|
@@ -60,27 +65,82 @@ const LADDER_EDGES: readonly (readonly [WorkflowState, WorkflowState])[] = MAIN_
|
|
|
60
65
|
);
|
|
61
66
|
|
|
62
67
|
/**
|
|
63
|
-
* The
|
|
64
|
-
*
|
|
65
|
-
* In
|
|
68
|
+
* The non-linear loop (F1): every ordered pair among these four states is
|
|
69
|
+
* allowed, in either direction and with skips — the implementation lead
|
|
70
|
+
* moves items around the loop freely. In Implementation → Design Validation
|
|
71
|
+
* (DRIFT_EDGE) is the one sanctioned exit backward out of the loop, on
|
|
72
|
+
* mid-loop drift.
|
|
66
73
|
*/
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
const LOOP_STATES: ReadonlySet<WorkflowState> = new Set([
|
|
75
|
+
"In Implementation",
|
|
76
|
+
"In Testing",
|
|
77
|
+
"In Review",
|
|
78
|
+
"Updating Docs",
|
|
79
|
+
]);
|
|
80
|
+
/**
|
|
81
|
+
* The drift loop-back: mid-loop drift returns through Design Validation.
|
|
82
|
+
* (PBI only — Bugs have no Design Validation, F9.)
|
|
83
|
+
*/
|
|
84
|
+
const DRIFT_EDGE: readonly [WorkflowState, WorkflowState] = ["In Implementation", "Design Validation"];
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The Bug ladder (F9): Bugs no longer share the PBI ladder. A Bug is never
|
|
88
|
+
* planned — no In Planning, Awaiting Approval or Design Validation — and
|
|
89
|
+
* reproduces before it is fixed. Allowed agent moves: New → Parked for
|
|
90
|
+
* Removal; Approved → In Reproduction; In Reproduction → In Fixing;
|
|
91
|
+
* In Reproduction → Parked for Removal (won't reproduce); the non-linear
|
|
92
|
+
* loop over In Fixing ↔ In Testing ↔ In Review ↔ Updating Docs (every
|
|
93
|
+
* ordered pair); and parking from any non-terminal Bug state. Everything
|
|
94
|
+
* else is refused, including targets of Awaiting Approval, In Planning and
|
|
95
|
+
* Design Validation. The human-only targets (Approved, Done, Removed, the
|
|
96
|
+
* parked revive) and the terminals are handled by the shared front matter
|
|
97
|
+
* of evaluateWorkflowTransition.
|
|
98
|
+
*/
|
|
99
|
+
const BUG_LOOP_STATES: ReadonlySet<WorkflowState> = new Set(["In Fixing", "In Testing", "In Review", "Updating Docs"]);
|
|
100
|
+
/** Any non-terminal Bug state may park (New and Approved included, to park a duplicate). */
|
|
101
|
+
const BUG_PARKING_SOURCES: ReadonlySet<WorkflowState> = new Set([
|
|
102
|
+
"New",
|
|
103
|
+
"Approved",
|
|
104
|
+
"In Reproduction",
|
|
105
|
+
"In Fixing",
|
|
106
|
+
"In Testing",
|
|
107
|
+
"In Review",
|
|
108
|
+
"Updating Docs",
|
|
78
109
|
]);
|
|
79
110
|
|
|
80
|
-
/** The
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
111
|
+
/** The Bug transition table itself, after the shared human-only/terminal front matter. */
|
|
112
|
+
function evaluateBugTransition(from: WorkflowState, to: WorkflowState): WorkflowViolation[] {
|
|
113
|
+
if (from === "Parked for Removal") {
|
|
114
|
+
// to New (human-only revive) and to Removed (G3) were handled by the
|
|
115
|
+
// shared front matter; every other exit keeps the parked note.
|
|
116
|
+
return [{ kind: "no-transition", fromState: from, toState: to, note: PARKED_EXIT_NOTE }];
|
|
117
|
+
}
|
|
118
|
+
if (to === "Parked for Removal") {
|
|
119
|
+
return BUG_PARKING_SOURCES.has(from)
|
|
120
|
+
? []
|
|
121
|
+
: [{ kind: "no-transition", fromState: from, toState: to, note: PARKED_EXIT_NOTE }];
|
|
122
|
+
}
|
|
123
|
+
if (from === "Approved" && to === "In Reproduction") return [];
|
|
124
|
+
if (from === "In Reproduction" && to === "In Fixing") return [];
|
|
125
|
+
if (BUG_LOOP_STATES.has(from) && BUG_LOOP_STATES.has(to)) return [];
|
|
126
|
+
return [{ kind: "no-transition", fromState: from, toState: to }];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* The states that may move back to New for a re-plan — any active state.
|
|
131
|
+
* Parked for Removal is deliberately absent: its → New revive is human-only
|
|
132
|
+
* (F10). Done and Removed are terminal (F10) and absent too.
|
|
133
|
+
*/
|
|
134
|
+
const REPLAN_SOURCES: ReadonlySet<WorkflowState> = new Set([
|
|
135
|
+
"In Planning",
|
|
136
|
+
"Awaiting Approval",
|
|
137
|
+
"Approved",
|
|
138
|
+
"Design Validation",
|
|
139
|
+
"In Implementation",
|
|
140
|
+
"In Testing",
|
|
141
|
+
"In Review",
|
|
142
|
+
"Updating Docs",
|
|
143
|
+
]);
|
|
84
144
|
|
|
85
145
|
/**
|
|
86
146
|
* Targets no agent may set, with the owner named in the refusal: Approved is
|
|
@@ -88,46 +148,68 @@ const RECOVERY_EDGE: readonly [WorkflowState, WorkflowState] = ['Done', 'In Plan
|
|
|
88
148
|
* removal, taken from Parked for Removal), Done is entered only by PR merge
|
|
89
149
|
* automation into integration (from Updating Docs).
|
|
90
150
|
*/
|
|
91
|
-
export const WORKFLOW_HUMAN_ONLY_TARGETS: Readonly<Record<
|
|
92
|
-
Approved:
|
|
93
|
-
Done:
|
|
94
|
-
Removed:
|
|
151
|
+
export const WORKFLOW_HUMAN_ONLY_TARGETS: Readonly<Record<"Approved" | "Done" | "Removed", string>> = {
|
|
152
|
+
Approved: "G1 — human approval only; agents cannot move items to Approved",
|
|
153
|
+
Done: "entered only by PR merge automation into integration",
|
|
154
|
+
Removed: "G3 — human removal only; agents cannot move items to Removed",
|
|
95
155
|
};
|
|
96
156
|
|
|
97
|
-
const RETIRED_COMMITTED_NOTE =
|
|
98
|
-
const PARKED_EXIT_NOTE =
|
|
157
|
+
const RETIRED_COMMITTED_NOTE = "Committed is a retired state (UI-hidden; no route references it)";
|
|
158
|
+
const PARKED_EXIT_NOTE = "Parked for Removal exits only to New (human-only revive) or Removed (G3 human)";
|
|
159
|
+
/** F10: the parked revive is Tarun's alone, like the G3 removal it precedes. */
|
|
160
|
+
export const PARKED_REVIVE_OWNER = "human revive only; agents cannot move items from Parked for Removal back to New";
|
|
99
161
|
|
|
100
162
|
export type WorkflowViolation =
|
|
101
|
-
| { kind:
|
|
102
|
-
| { kind:
|
|
103
|
-
| { kind:
|
|
163
|
+
| { kind: "skipped-gate"; fromState: WorkflowState; toState: WorkflowState; skippedState: WorkflowState }
|
|
164
|
+
| { kind: "human-only"; fromState: WorkflowState; toState: WorkflowState; owner: string }
|
|
165
|
+
| { kind: "no-transition"; fromState: WorkflowState; toState: WorkflowState; note?: string };
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* The Feature ladder's violation shape (F3). Mirrors WorkflowViolation but uses
|
|
169
|
+
* FeatureState literals so `evaluateFeatureTransition`'s output is honest about
|
|
170
|
+
* what states it carries, instead of casting every Feature-state literal to
|
|
171
|
+
* WorkflowState at the function boundary.
|
|
172
|
+
*/
|
|
173
|
+
export type FeatureViolation =
|
|
174
|
+
| { kind: "skipped-gate"; fromState: FeatureState; toState: FeatureState; skippedState: FeatureState }
|
|
175
|
+
| { kind: "human-only"; fromState: FeatureState; toState: FeatureState; owner: string }
|
|
176
|
+
| { kind: "no-transition"; fromState: FeatureState; toState: FeatureState; note?: string };
|
|
104
177
|
|
|
105
178
|
/**
|
|
106
179
|
* Evaluate a state TRANSITION (from-state → to-state) against the final
|
|
107
180
|
* state model. One violation per refusal class:
|
|
108
181
|
*
|
|
109
182
|
* - `human-only` — the target is owned by G1 approval, PR merge automation
|
|
110
|
-
* or G3 human removal; agents never set it.
|
|
183
|
+
* or G3 human removal; agents never set it. Checked before the
|
|
184
|
+
* from-state recognition (F2), so an off-ladder from-state cannot smuggle
|
|
185
|
+
* an agent into a human-owned target. Parked for Removal → New is a
|
|
186
|
+
* human-only revive (F10) with its own owner text.
|
|
111
187
|
* - `skipped-gate` — a forward jump over main-line states; one violation per
|
|
112
188
|
* skipped state, in route order, so the refusal names every gate
|
|
113
189
|
* bypassed. Approved is annotated "(G1: human approval)".
|
|
114
190
|
* - `no-transition` — anything off the model. Committed is retired: any
|
|
115
|
-
* transition touching it names the retired state.
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
191
|
+
* transition touching it names the retired state. Done and Removed are
|
|
192
|
+
* terminal for agents (F10): every exit is refused with the terminal
|
|
193
|
+
* note. Parked for Removal is enterable from anywhere and exits only to
|
|
194
|
+
* New (human-only revive) or Removed (G3).
|
|
195
|
+
*
|
|
196
|
+
* The loop is non-linear (F1): every ordered pair among In Implementation,
|
|
197
|
+
* In Testing, In Review and Updating Docs is allowed, and In
|
|
198
|
+
* Implementation → Design Validation is the drift loop-back. Backward
|
|
199
|
+
* moves outside the loop are refused flat — no special-casing.
|
|
200
|
+
*
|
|
201
|
+
* F9: Bugs walk their own ladder — New → Approved (G1, human-only) →
|
|
202
|
+
* In Reproduction → In Fixing, then the same non-linear loop with
|
|
203
|
+
* In Fixing in place of In Implementation; parking from any non-terminal
|
|
204
|
+
* Bug state; never In Planning, Awaiting Approval or Design Validation.
|
|
120
205
|
*
|
|
121
206
|
* Allowed to writers: identity writes (from === to, never gated); the
|
|
122
207
|
* adjacent main-line forward moves; parking to Parked for Removal from any
|
|
123
|
-
* state; re-plan moves to New from any active state
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* terminal"). A state outside the thirteen recognized states yields none —
|
|
129
|
-
* the ADO process template enforces server-side. Exempt types
|
|
130
|
-
* (Feature/Epic) yield none.
|
|
208
|
+
* state; re-plan moves to New from any active state; the 12 loop pairs and
|
|
209
|
+
* the drift loop-back. A state outside the thirteen recognized states
|
|
210
|
+
* yields none — except the human-only targets, refused first (F2) — the
|
|
211
|
+
* ADO process template enforces server-side. Exempt types (Feature/Epic)
|
|
212
|
+
* yield none.
|
|
131
213
|
*/
|
|
132
214
|
export function evaluateWorkflowTransition(
|
|
133
215
|
workItemType: string,
|
|
@@ -135,60 +217,135 @@ export function evaluateWorkflowTransition(
|
|
|
135
217
|
toState: string,
|
|
136
218
|
): WorkflowViolation[] {
|
|
137
219
|
if (!(GATED_TYPES as readonly string[]).includes(workItemType)) return [];
|
|
220
|
+
if (fromState === toState) return [];
|
|
221
|
+
if (fromState === "Committed" || toState === "Committed") {
|
|
222
|
+
return [
|
|
223
|
+
{
|
|
224
|
+
kind: "no-transition",
|
|
225
|
+
fromState: fromState as WorkflowState,
|
|
226
|
+
toState: toState as WorkflowState,
|
|
227
|
+
note: RETIRED_COMMITTED_NOTE,
|
|
228
|
+
},
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
// F2: the human-only targets are refused BEFORE the from-state
|
|
232
|
+
// recognition, so an off-ladder from-state cannot smuggle an agent into
|
|
233
|
+
// a human-owned target.
|
|
234
|
+
const owner = (WORKFLOW_HUMAN_ONLY_TARGETS as Partial<Record<string, string>>)[toState];
|
|
235
|
+
if (owner !== undefined) {
|
|
236
|
+
return [
|
|
237
|
+
{ kind: "human-only", fromState: fromState as WorkflowState, toState: toState as WorkflowState, owner },
|
|
238
|
+
];
|
|
239
|
+
}
|
|
138
240
|
if (!(WORKFLOW_STATES as readonly string[]).includes(fromState)) return [];
|
|
139
241
|
if (!(WORKFLOW_STATES as readonly string[]).includes(toState)) return [];
|
|
140
242
|
const from = fromState as WorkflowState;
|
|
141
243
|
const to = toState as WorkflowState;
|
|
142
|
-
if (from === to)
|
|
143
|
-
|
|
144
|
-
return [{ kind: 'no-transition', fromState: from, toState: to, note: RETIRED_COMMITTED_NOTE }];
|
|
244
|
+
if (from === "Parked for Removal" && to === "New") {
|
|
245
|
+
return [{ kind: "human-only", fromState: from, toState: to, owner: PARKED_REVIVE_OWNER }];
|
|
145
246
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (to === 'Parked for Removal') return [];
|
|
149
|
-
if (to === 'New' && REPLAN_SOURCES.has(from)) return [];
|
|
150
|
-
if (from === REJECTION_EDGE[0] && to === REJECTION_EDGE[1]) return [];
|
|
151
|
-
if (from === RECOVERY_EDGE[0] && to === RECOVERY_EDGE[1]) return [];
|
|
152
|
-
if (from === 'Done' || from === 'Removed') {
|
|
153
|
-
return [{ kind: 'no-transition', fromState: from, toState: to, note: terminalSourceNote(from) }];
|
|
247
|
+
if (from === "Done" || from === "Removed") {
|
|
248
|
+
return [{ kind: "no-transition", fromState: from, toState: to, note: terminalSourceNote(from) }];
|
|
154
249
|
}
|
|
155
|
-
|
|
156
|
-
|
|
250
|
+
// F9: Bugs walk their own ladder from here on.
|
|
251
|
+
if (workItemType === "Bug") return evaluateBugTransition(from, to);
|
|
252
|
+
if (to === "Parked for Removal") return [];
|
|
253
|
+
if (to === "New" && REPLAN_SOURCES.has(from)) return [];
|
|
254
|
+
if (LOOP_STATES.has(from) && LOOP_STATES.has(to)) return [];
|
|
255
|
+
if (from === DRIFT_EDGE[0] && to === DRIFT_EDGE[1]) return [];
|
|
256
|
+
if (from === "Parked for Removal") {
|
|
257
|
+
return [{ kind: "no-transition", fromState: from, toState: to, note: PARKED_EXIT_NOTE }];
|
|
157
258
|
}
|
|
158
259
|
if (LADDER_EDGES.some(([edgeFrom, edgeTo]) => edgeFrom === from && edgeTo === to)) return [];
|
|
159
260
|
const fromIndex = MAIN_LINE_INDEX.get(from)!;
|
|
160
261
|
const toIndex = MAIN_LINE_INDEX.get(to)!;
|
|
161
262
|
if (toIndex > fromIndex) {
|
|
162
263
|
return MAIN_LINE.slice(fromIndex + 1, toIndex).map((skippedState) => ({
|
|
163
|
-
kind:
|
|
264
|
+
kind: "skipped-gate",
|
|
164
265
|
fromState: from,
|
|
165
266
|
toState: to,
|
|
166
267
|
skippedState,
|
|
167
268
|
}));
|
|
168
269
|
}
|
|
169
|
-
return [{ kind:
|
|
270
|
+
return [{ kind: "no-transition", fromState: from, toState: to }];
|
|
170
271
|
}
|
|
171
272
|
|
|
172
|
-
/** from is Done or Removed here; identity, parking and
|
|
273
|
+
/** from is Done or Removed here; identity, parking and human-only targets were handled by the caller. */
|
|
173
274
|
function terminalSourceNote(from: WorkflowState): string {
|
|
174
|
-
return from ===
|
|
175
|
-
? 'completed items stay Done; a G2 rejection gets its own linked item'
|
|
176
|
-
: 'Removed is terminal';
|
|
275
|
+
return from === "Done" ? "completed items stay Done; a G2 rejection gets its own linked item" : "Removed is terminal";
|
|
177
276
|
}
|
|
178
277
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
278
|
+
/** A printable violation: either WorkflowViolation or FeatureViolation. Both shapes carry
|
|
279
|
+
* the same {kind, fromState, toState} skeleton so the formatter can render either. */
|
|
280
|
+
export type AnyWorkflowViolation = WorkflowViolation | FeatureViolation;
|
|
281
|
+
|
|
282
|
+
export function formatWorkflowViolation(violation: AnyWorkflowViolation): string {
|
|
283
|
+
if (violation.kind === "skipped-gate") {
|
|
284
|
+
const g1 = violation.skippedState === "Approved" ? " (G1: human approval)" : "";
|
|
182
285
|
return `fenced by state ladder: '${violation.fromState}' → '${violation.toState}' skips '${violation.skippedState}'${g1}`;
|
|
183
286
|
}
|
|
184
|
-
if (violation.kind ===
|
|
287
|
+
if (violation.kind === "human-only") {
|
|
185
288
|
return `fenced by state ladder: '${violation.fromState}' → '${violation.toState}' is ${violation.owner}`;
|
|
186
289
|
}
|
|
187
|
-
const note = violation.note === undefined ?
|
|
290
|
+
const note = violation.note === undefined ? "" : ` (${violation.note})`;
|
|
188
291
|
return `fenced by state ladder: no ladder transition '${violation.fromState}' → '${violation.toState}'${note}`;
|
|
189
292
|
}
|
|
190
293
|
|
|
191
294
|
/** One refusal line per violation, joined for a loud multi-line error. */
|
|
192
|
-
export function formatWorkflowRefusal(violations:
|
|
193
|
-
return violations.map(formatWorkflowViolation).join(
|
|
295
|
+
export function formatWorkflowRefusal(violations: readonly AnyWorkflowViolation[]): string {
|
|
296
|
+
return violations.map(formatWorkflowViolation).join("\n");
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* The Feature ladder (F3): linear, one step at a time, never backward —
|
|
301
|
+
* New → In Progress → Awaiting Release → Done. Only a human moves a
|
|
302
|
+
* Feature to Removed (G3). 'Awaiting Release' exists only on Features, so
|
|
303
|
+
* this table is deliberately separate from evaluateWorkflowTransition,
|
|
304
|
+
* which stays pure on the item-ladder vocabulary; the Feature
|
|
305
|
+
* preconditions against children live in azdo-wit.ts (F4).
|
|
306
|
+
*/
|
|
307
|
+
const FEATURE_STATES = ["New", "In Progress", "Awaiting Release", "Done", "Removed"] as const;
|
|
308
|
+
type FeatureState = (typeof FEATURE_STATES)[number];
|
|
309
|
+
|
|
310
|
+
const FEATURE_MAIN_LINE: readonly FeatureState[] = ["New", "In Progress", "Awaiting Release", "Done"];
|
|
311
|
+
const FEATURE_MAIN_LINE_INDEX = new Map<string, number>(FEATURE_MAIN_LINE.map((state, index) => [state, index]));
|
|
312
|
+
const FEATURE_LADDER_EDGES: readonly (readonly [FeatureState, FeatureState])[] = FEATURE_MAIN_LINE.slice(1).map(
|
|
313
|
+
(state, index) => [FEATURE_MAIN_LINE[index]!, state] as const,
|
|
314
|
+
);
|
|
315
|
+
const FEATURE_REMOVED_OWNER = "G3 — human removal only; agents cannot move Features to Removed";
|
|
316
|
+
const FEATURE_BACKWARD_NOTE = "the Feature ladder is linear: never backward";
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Evaluate a Feature state TRANSITION against the Feature ladder. Like the
|
|
320
|
+
* item fence: identity writes are never gated; the human-only target
|
|
321
|
+
* (Removed) is refused before the from-state recognition; unknown states
|
|
322
|
+
* stay silent (the ADO process enforces server-side); forward skips name
|
|
323
|
+
* every skipped state; backward moves refuse flat.
|
|
324
|
+
*/
|
|
325
|
+
export function evaluateFeatureTransition(fromState: string, toState: string): FeatureViolation[] {
|
|
326
|
+
if (fromState === toState) return [];
|
|
327
|
+
if (toState === "Removed") {
|
|
328
|
+
// An off-ladder fromState still trips the human-only refusal here (the
|
|
329
|
+
// Removed check fires before from-state recognition, see comment at
|
|
330
|
+
// the function head). We normalize fromState to "Removed" so the
|
|
331
|
+
// violation shape stays in FeatureState terms; the human-only owner
|
|
332
|
+
// note names Removed at the G3 boundary.
|
|
333
|
+
return [{ kind: "human-only", fromState: "Removed", toState: "Removed", owner: FEATURE_REMOVED_OWNER }];
|
|
334
|
+
}
|
|
335
|
+
if (!(FEATURE_STATES as readonly string[]).includes(fromState)) return [];
|
|
336
|
+
if (!(FEATURE_STATES as readonly string[]).includes(toState)) return [];
|
|
337
|
+
const from = fromState as FeatureState;
|
|
338
|
+
const to = toState as FeatureState;
|
|
339
|
+
if (FEATURE_LADDER_EDGES.some(([edgeFrom, edgeTo]) => edgeFrom === from && edgeTo === to)) return [];
|
|
340
|
+
const fromIndex = FEATURE_MAIN_LINE_INDEX.get(from)!;
|
|
341
|
+
const toIndex = FEATURE_MAIN_LINE_INDEX.get(to)!;
|
|
342
|
+
if (toIndex > fromIndex) {
|
|
343
|
+
return FEATURE_MAIN_LINE.slice(fromIndex + 1, toIndex).map((skippedState) => ({
|
|
344
|
+
kind: "skipped-gate",
|
|
345
|
+
fromState: from,
|
|
346
|
+
toState: to,
|
|
347
|
+
skippedState,
|
|
348
|
+
}));
|
|
349
|
+
}
|
|
350
|
+
return [{ kind: "no-transition", fromState: from, toState: to, note: FEATURE_BACKWARD_NOTE }];
|
|
194
351
|
}
|
|
@@ -19,15 +19,16 @@ import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'
|
|
|
19
19
|
// import cross-package by relative path — a package added to those imports
|
|
20
20
|
// but not here breaks every managed repo's git hooks with "Cannot find module"
|
|
21
21
|
// the next time reconcile projects this payload.
|
|
22
|
-
// Every package apps/cli reads from /usr/local/libexec/adl (hooks.ts,
|
|
22
|
+
// Every package apps/cli reads from /usr/local/libexec/adl (hooks.ts, settings.ts,
|
|
23
23
|
// repo-controls.ts: DEFAULT_LIBEXEC_DIR) plus azdo, which they import by relative path.
|
|
24
|
+
// skills.ts dropped its libexec fallback for agent-skills as part of az697
|
|
25
|
+
// (fleet does not install skills; every skill comes from `adl skills deploy`).
|
|
24
26
|
// install-adl-package.test.ts pins both against the real sources.
|
|
25
|
-
export const payloadDirectories = ['packages/
|
|
27
|
+
export const payloadDirectories = ['packages/repo-controls', 'packages/agent-hooks', 'packages/agent-settings', 'packages/azdo']
|
|
26
28
|
const payloadScripts = ['bin/git', 'bin/git-ado']
|
|
27
29
|
const requiredFiles = [
|
|
28
30
|
'bin/reconcile',
|
|
29
31
|
'packages/fleet/manifest.json',
|
|
30
|
-
'packages/agent-skills/dist/index.js',
|
|
31
32
|
'packages/repo-controls/bin/adl-repo-controls.ts',
|
|
32
33
|
'packages/agent-hooks/src/log/writer.ts',
|
|
33
34
|
'packages/agent-settings/deploy-profile.json',
|
|
@@ -538,7 +538,10 @@ doctor report and never repairs or stages the managed surface: run
|
|
|
538
538
|
Armed from the first commit with NO ratchet baseline for existing violations, so an
|
|
539
539
|
existing repository reports its violations as guidance. Measured on a fresh install
|
|
540
540
|
(see "Fresh-install result" below), the one gate this package's own install leaves
|
|
541
|
-
failing is `repository.license-declared` (REP-001: no `license` declared)
|
|
541
|
+
failing is `repository.license-declared` (REP-001: no `license` declared), and
|
|
542
|
+
`docs.okf-profile`, `docs.filename` and `docs.directory-size` are could-not-run until
|
|
543
|
+
the first real docs page lands — the fresh scaffold's `docs/` holds only
|
|
544
|
+
`AGENTS.md`/`CLAUDE.md`/`decisions/index.md`, all outside their scope. An existing `enabled` key, even `[]`, is never rewritten, and
|
|
542
545
|
switching a gate off is the repository's own decision, made by removing its one line
|
|
543
546
|
from `enabled`
|
|
544
547
|
([`#strict-activation-and-switching-a-gate-off`](../../docs/architecture/compliance-controls.md#strict-activation-and-switching-a-gate-off)).
|
|
@@ -598,7 +601,7 @@ truthful. A `uv`-less machine errors out of the grade step, after everything is
|
|
|
598
601
|
|
|
599
602
|
Install bootstraps the minimal skeleton of `docs`, `plans` and `workflows` from the
|
|
600
603
|
package's `assets/scaffold/<tree>/` (Bug 570, Tarun 2026-10-08):
|
|
601
|
-
`docs/{AGENTS.md,CLAUDE.md,
|
|
604
|
+
`docs/{AGENTS.md,CLAUDE.md,decisions/index.md}`,
|
|
602
605
|
`plans/{AGENTS.md,CLAUDE.md,GAPS-AND-FINDINGS.md,LEDGER.md,features/.gitkeep}`, and
|
|
603
606
|
`workflows/{AGENTS.md,CLAUDE.md,pipelines/.gitkeep,scripts/.gitkeep}`. Rules:
|
|
604
607
|
|
|
@@ -630,8 +633,13 @@ package's `assets/scaffold/<tree>/` (Bug 570, Tarun 2026-10-08):
|
|
|
630
633
|
|
|
631
634
|
The scaffold gates (DOC-001, DOC-002, DOC-004 to DOC-012, LAY-002, LAY-004, LAY-009,
|
|
632
635
|
LAY-011, LAY-014, LAY-016, LFS-001) pass on a fresh install
|
|
633
|
-
(`tests/install-scaffold.test.ts`)
|
|
634
|
-
|
|
636
|
+
(`tests/install-scaffold.test.ts`), except DOC-006, DOC-011 and DOC-012, which are
|
|
637
|
+
could-not-run there: the fresh scaffold's `docs/` holds only
|
|
638
|
+
`AGENTS.md`/`CLAUDE.md`/`decisions/index.md`, all outside their scope, and a scope
|
|
639
|
+
that selects nothing is could-not-run, never a clean pass (Bug 597). They start
|
|
640
|
+
grading with the first real docs page. Of the 29 enabled gates, the package-level
|
|
641
|
+
result of a fresh install is exactly one failing gate, REP-001
|
|
642
|
+
`repository.license-declared`, plus those three could-not-run
|
|
635
643
|
(`tests/install-strict.test.ts`). `adl install` also deploys skills, hooks and plugins into
|
|
636
644
|
the repository, and any of their files with consecutive comment lines fail REP-007
|
|
637
645
|
`repository.no-multiline-comments`; that is a defect of the deployed assets, not an expected
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Managed by adl-repo-controls, do not edit; regenerate with: adl-repo-controls install --repo . (README "Managed workflow scripts").
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
/** Promote one branch to another through an Azure DevOps pull request; see README "Managed workflow scripts". */
|
|
4
5
|
|
|
5
6
|
/** Azure DevOps' `mergeStrategy` by name; see README "Managed workflow scripts". */
|
|
@@ -10,16 +10,16 @@ the way it is.
|
|
|
10
10
|
- Sub-directories group related pages (for example `decisions/` for
|
|
11
11
|
architecture decision records, `research/` for dated investigations). Add one
|
|
12
12
|
only when it has pages to hold.
|
|
13
|
-
-
|
|
14
|
-
|
|
13
|
+
- The agent activity log lives at `.adl/agent-activity.sqlite` (gitignored,
|
|
14
|
+
local only): agents write with `adl activity add "<note>"` and read with
|
|
15
|
+
`adl activity list`.
|
|
15
16
|
|
|
16
17
|
## Conventions
|
|
17
18
|
|
|
18
19
|
- Every page carries YAML frontmatter with at least `type`, `title`,
|
|
19
20
|
`description`, `status` and `last_update` (ISO-8601 UTC,
|
|
20
21
|
`YYYY-MM-DDTHH:MM:SSZ`).
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
characters per line.
|
|
22
|
+
- Activity entries are append-only, oldest first, and the tool fills time
|
|
23
|
+
(UTC), surface, agent identity and repo — only the note is caller-supplied.
|
|
24
24
|
- A page that is catalogued in an index stays listed there; add the entry in
|
|
25
25
|
the same change that adds or renames the page.
|
|
@@ -5,19 +5,45 @@ board is the only place status lives; the files here describe the work.
|
|
|
5
5
|
|
|
6
6
|
## Layout
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
```text
|
|
9
|
+
plans/
|
|
10
|
+
LEDGER.md
|
|
11
|
+
features/
|
|
12
|
+
az<feature id>-<slug>/
|
|
13
|
+
intent.md # required — lands with the Feature
|
|
14
|
+
requirements.md # the planning run (approved at G1)
|
|
15
|
+
design.md # optional — the planning run
|
|
16
|
+
file-map-reference.md # optional — the planning run
|
|
17
|
+
items/
|
|
18
|
+
az<item id>-<slug>.md # one PBI or Bug
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
- `plans/features/az<id>-<slug>/intent.md` — the WHY, written by the human
|
|
22
|
+
with the Feature. Frontmatter: `type: intent`, `title`, `status` (the
|
|
23
|
+
Feature's board state), `work_item:` (the Feature's full board URL; its id
|
|
24
|
+
equals the folder id), `last_update`. Sections: `## Why`, `## Outcome`,
|
|
25
|
+
`## Constraints`, `## Non-goals`, optional `## Open questions`.
|
|
26
|
+
- `plans/features/az<id>-<slug>/requirements.md` — the what and why, frozen
|
|
27
|
+
at G1. Frontmatter: `type: feature`, `title`, `status` (the Feature's
|
|
28
|
+
board state), `epic:` (the parent Epic's board URL), `work_item:` (the
|
|
29
|
+
Feature's full board URL), `last_update`, `sources:` listing `intent.md`
|
|
30
|
+
first. Sections: `## Problem`, `## Acceptance criteria` (`AC-1…`, EARS),
|
|
31
|
+
`## Scope`, `## Predecessors`, `## Items` (`Id | Title | Type | Delivers |
|
|
32
|
+
Verification`), `## Open questions for G1`, `## Revision log`.
|
|
33
|
+
- `plans/features/az<id>-<slug>/items/az<item-id>-<slug>.md` — one PBI or
|
|
34
|
+
Bug. Frontmatter: `type: pbi` or `type: bug`, `title`, `status` (the
|
|
35
|
+
item's board state), `work_item:` (the item's full board URL), `feature:`
|
|
36
|
+
(the Feature's full board URL), `last_update`. A PBI carries `## What it
|
|
37
|
+
delivers` and `## Verification` naming its `AC-n`; a Fixes Bug carries the
|
|
38
|
+
bugfix sections (`## Current behaviour`, `## Expected behaviour`,
|
|
39
|
+
`## Behaviour that must not change`, `## Responsible Feature`,
|
|
40
|
+
`## Predecessors`, `## Verification`).
|
|
41
|
+
- `plans/LEDGER.md` — the plan-event ledger: `Date | Id | Area | Event |
|
|
42
|
+
Refs`, newest first, Event ≤ 99 characters. There is no `Next` table;
|
|
43
|
+
Feature order comes from the board's predecessor links.
|
|
44
|
+
|
|
45
|
+
The templates ship with the `adl-workitems-process` skill
|
|
46
|
+
(`references/templates/`); there is no per-repo `plans/templates/`.
|
|
21
47
|
|
|
22
48
|
## Conventions
|
|
23
49
|
|
|
@@ -26,3 +52,6 @@ board is the only place status lives; the files here describe the work.
|
|
|
26
52
|
- An item is allocated on the board first; the file is named `az<id>-<slug>`
|
|
27
53
|
only once that id exists. Files never move between directories.
|
|
28
54
|
- `epic:` and `feature:` are authored by hand, never tool-generated.
|
|
55
|
+
- An item names its `feature:` as the Feature's full board URL.
|
|
56
|
+
- A gap found along the way is filed through `report-bug`, never a register
|
|
57
|
+
file; findings enter only that way.
|
|
@@ -4,10 +4,10 @@ How to contribute to THIS repository. Orientation is in `AGENTS.md`; what must n
|
|
|
4
4
|
|
|
5
5
|
## Plans and work items
|
|
6
6
|
- A plan is a Feature; a backlog item is a PBI or a Bug. One file each; the board is the only place their state lives.
|
|
7
|
-
- Layout: `plans/features/az<feature id>-<slug
|
|
7
|
+
- Layout: `plans/features/az<feature id>-<slug>/` with `intent.md`, `requirements.md` (plan files `design.md`/`file-map-reference.md` optional), items under `items/az<id>-<slug>.md`.
|
|
8
8
|
- The id is the identity: allocate the item on the board first, then name the file. Until then it is a row in the plan's `## Items` table.
|
|
9
|
-
- Nothing moves between directories; the
|
|
10
|
-
-
|
|
9
|
+
- Nothing moves between directories; the plan text is the work item's fields.
|
|
10
|
+
- An item names its `feature:` as the Feature's full board URL; a gap found along the way is filed through `report-bug`, never a register file.
|
|
11
11
|
|
|
12
12
|
## Commits and PRs
|
|
13
13
|
- Each commit is independently green and on one topic. Never `git stash`. Green wins over one topic, and say so.
|
|
@@ -21,8 +21,8 @@ How to contribute to THIS repository. Orientation is in `AGENTS.md`; what must n
|
|
|
21
21
|
- A repository that differs states it under "Release flow of this repository".
|
|
22
22
|
|
|
23
23
|
## Tasks ledger
|
|
24
|
-
- At the start and the end of a task,
|
|
25
|
-
-
|
|
24
|
+
- At the start and the end of a task, log with `adl activity add "<note>"` and read the log with `adl activity list`. The MCP tools `activity_add`/`activity_list` are the same storage; the CLI is the documented fallback.
|
|
25
|
+
- The log is `.adl/agent-activity.sqlite` — gitignored, local only. One ledger per repository; the tool fills time, surface, agent and repo, and only the note is caller-supplied.
|
|
26
26
|
|
|
27
27
|
## Release flow of this repository
|
|
28
28
|
- <!-- Owner: state any difference from the flow above; delete this section if none. -->
|