yadflow 3.17.0 → 3.17.1

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/CHANGELOG.md CHANGED
@@ -1,3 +1,5 @@
1
+ ## [3.17.1](https://github.com/abdelrahmannasr/yadflow/compare/v3.17.0...v3.17.1) (2026-09-02)
2
+
1
3
  # [3.17.0](https://github.com/abdelrahmannasr/yadflow/compare/v3.16.3...v3.17.0) (2026-08-12)
2
4
 
3
5
 
package/cli/commit.mjs CHANGED
@@ -38,7 +38,7 @@ export function buildCommitMessage({ type, subject, task, contractChange = false
38
38
  return parts.join('\n');
39
39
  }
40
40
 
41
- // feat/EP-istifta-inquiries-S01-T01-create-inquiry -> EP-istifta-inquiries-S01-T01
41
+ // feat/EP-checkout-S01-T01-create-order -> EP-checkout-S01-T01
42
42
  export function taskFromBranch(branch = '') {
43
43
  const m = branch.match(/(.+-S\d+-T\d+)(?:-|$)/i);
44
44
  return m ? m[1].replace(/^[a-z]+\//i, '') : null;
package/cli/next.mjs CHANGED
@@ -46,7 +46,7 @@ const actionFor = (root, id) => ({
46
46
  lineageKind: epicLineage(root, id).kind,
47
47
  });
48
48
 
49
- // EP-istifta-inquiries-S03 → S03 (the compact lane label for the roll-up). Falls back to the full id.
49
+ // EP-checkout-S03 → S03 (the compact lane label for the roll-up). Falls back to the full id.
50
50
  const shortStory = (s) => (s && s.match(/S\d+$/i)?.[0]) || s || '(story)';
51
51
 
52
52
  // Every per-repo lane across the build, flattened with its story id attached.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yadflow",
3
- "version": "3.17.0",
3
+ "version": "3.17.1",
4
4
  "description": "Yadflow — the gated, team, multi-repo SDLC: author → review → build with a PR-driven review gate and a zero-dependency `yad` CLI (setup, gate, commit, open-pr, ship, repo, thread, reconcile). A BMAD module + 38 yad-* skills.",
5
5
  "type": "module",
6
6
  "author": "AbdelRahman Nasr",
@@ -94,7 +94,7 @@ build:
94
94
  spec_layout: speckit # follow Spec Kit's native spec/plan/tasks layout
95
95
  speckit_ceremony: [specify, clarify, plan, analyze, checklist, tasks] # heavy run, once per story per repo
96
96
  # Step B (yad-implement) — the light per-task loop. One atomic task = one branch = one PR/MR.
97
- branch_convention: "feat/<story-id>-<task-id>-<short-slug>" # e.g. feat/EP-istifta-inquiries-S01-T01-create-inquiry
97
+ branch_convention: "feat/<story-id>-<task-id>-<short-slug>" # e.g. feat/EP-checkout-S01-T01-create-order
98
98
  commit_task_trailer: "Task: <story-id>-<task-id>" # final commit trailer; anchors the spec-link check (Step C)
99
99
  contract_change_trailer: "Contract-Change: yes" # ONLY when the locked contract surface is touched (routes back to architecture gate)
100
100
  # Commit subject + PR/MR title style (Conventional Commits — see CONTRIBUTING.md). PRs are squash-merged,
@@ -62,7 +62,7 @@ roadmap. **Optional & non-blocking:** if there is no discovery, or it has not ye
62
62
 
63
63
  ### Step 3 — Generate the Epic ID (engine-assigned, never by hand)
64
64
  Derive `EP-<slug>` where `slug` is **2–4 lowercase words joined by hyphens**, drawn from the idea
65
- (e.g. `EP-istifta-inquiries`). Lowercase except the fixed `EP` prefix. `EP-discovery` is **reserved**
65
+ (e.g. `EP-checkout`). Lowercase except the fixed `EP` prefix. `EP-discovery` is **reserved**
66
66
  for the project front-zero — never use it for a feature. **The ID is assigned once and
67
67
  never renamed** — renaming breaks every downstream link (build plan §6b). Check
68
68
  `{project-root}/epics/` for collisions; if the slug exists, append a distinguishing word.
@@ -489,15 +489,15 @@ bash checks/commit-message.sh --profile code master
489
489
  # pr-title / pr-template validate the actual PR/MR metadata (in CI they come from the event payload).
490
490
  # By hand, pass the title, and a FILE holding the PR/MR description (the rendered/filled body, not the
491
491
  # template source):
492
- bash checks/pr-title.sh --profile code "feat: add the inquiry endpoint"
492
+ bash checks/pr-title.sh --profile code "feat: add the order endpoint"
493
493
  # save the PR/MR description to a file first (e.g. `gh pr view <n> --json body -q .body > /tmp/pr-body.md`)
494
494
  bash checks/pr-template.sh --profile code /tmp/pr-body.md
495
495
  ```
496
496
 
497
- ## Proven behavior (demo: `demo-repos/backend`, story EP-istifta-inquiries-S01)
497
+ ## Proven behavior (demo: `demo-repos/backend`, story EP-checkout-S01)
498
498
 
499
499
  - **Good PR** (task branch with a `Task:` trailer, no surface change, passing tests) → all three **PASS**.
500
500
  - **Bad PR A** (a code change committed with **no** `Task:` trailer) → spec-link **FAILS**.
501
- - **Bad PR B** (edits `specs/.../contracts/inquiries.md` to widen the surface, with a `Task:` trailer
501
+ - **Bad PR B** (edits `specs/.../contracts/orders.md` to widen the surface, with a `Task:` trailer
502
502
  but **no** `Contract-Change`) → spec-link passes, contract-check **FAILS** and routes back to the
503
503
  architecture gate.
@@ -17,7 +17,7 @@ root, not under any `epics/EP-<slug>/.sdlc/`.
17
17
  "tool": "deeptutor", // deeptutor | <adapter id> | none (harness-native)
18
18
  "provider": "deeptutor-cli", // the concrete CLI: deeptutor-cli | null
19
19
  "version": "1.4.5", // CLI version reported at detect time; null if absent
20
- "kb": "yadflow-istifta", // grounded knowledge-base name; null if not built
20
+ "kb": "yadflow-checkout", // grounded knowledge-base name; null if not built
21
21
  "kb_sources": ["epic.md", "architecture.md", "contract.md", "ui-design.md", "stories/", "code-context/*/code-map.md"],
22
22
  "auth": "user", // ALWAYS the user's own DeepTutor config / LLM keys — never a token
23
23
  "connectedAt": "2026-06-14", // first connect (YYYY-MM-DD)
@@ -36,13 +36,13 @@ without the `{ epic, ships }` wrapper):
36
36
 
37
37
  ```json
38
38
  {
39
- "epic": "EP-istifta-inquiries",
39
+ "epic": "EP-checkout",
40
40
  "ships": [
41
41
  {
42
- "story": "EP-istifta-inquiries-S01",
42
+ "story": "EP-checkout-S01",
43
43
  "task": "T01",
44
44
  "repo": "backend",
45
- "branch": "feat/EP-istifta-inquiries-S01-T01-create-inquiry",
45
+ "branch": "feat/EP-checkout-S01-T01-create-order",
46
46
  "pr": "<url|#|local>",
47
47
  "mergeCommit": "<sha>",
48
48
  "gates": ["spec-link", "contract-check", "build-test-lint"],
@@ -83,7 +83,7 @@ unchanged — do not consume an unapproved roadmap. After seeding the epic, the
83
83
  ### Step 3 — Generate the Epic ID (engine-assigned, never by hand) — analysis-skipped only
84
84
  *(Skip when analysis ran — the ID was already assigned by `yad-analysis`.)*
85
85
  Derive `EP-<slug>` where `slug` is **2–4 lowercase words joined by hyphens**, drawn from the idea
86
- (e.g. `EP-istifta-inquiries`). Lowercase except the fixed `EP` prefix. `EP-discovery` is **reserved**
86
+ (e.g. `EP-checkout`). Lowercase except the fixed `EP` prefix. `EP-discovery` is **reserved**
87
87
  for the project front-zero — never use it for a feature. **The ID is assigned once and
88
88
  never renamed** — renaming breaks every downstream link (build plan §6b).
89
89
  Check `{project-root}/epics/` for collisions; if the slug exists, append a distinguishing word.
@@ -416,7 +416,7 @@ only re-authored steps run. The seeder sets `currentStep` to the first re-author
416
416
  ```json
417
417
  { "id": "architecture", "type": "author", "artifact": "architecture.md",
418
418
  "assistance": "review", "automation": "human_approve", "locked": true,
419
- "status": "done", "inherited": true, "inheritedFrom": "EP-istifta-inquiries",
419
+ "status": "done", "inherited": true, "inheritedFrom": "EP-checkout",
420
420
  "boundHash": "sha256:…", "risk_tags": [] }
421
421
  ```
422
422
 
@@ -432,7 +432,7 @@ only re-authored steps run. The seeder sets `currentStep` to the first re-author
432
432
 
433
433
  ```json
434
434
  { "artifact": "architecture.md", "step": "architecture-review", "status": "inherited",
435
- "from": "EP-istifta-inquiries", "boundHash": "sha256:…", "date": "<YYYY-MM-DD>" }
435
+ "from": "EP-checkout", "boundHash": "sha256:…", "date": "<YYYY-MM-DD>" }
436
436
  ```
437
437
 
438
438
  ## The pointer-lock — `contract-lock.json` in a change-epic
@@ -443,7 +443,7 @@ no `contract.md` in the child to edit, so the surface physically cannot drift.
443
443
 
444
444
  ```json
445
445
  { "artifact": "contract.md", "hash": "sha256:<parent hash, verbatim>", "lockedAt": "<date>",
446
- "inheritedFrom": "EP-istifta-inquiries", "ref": "../../EP-istifta-inquiries/.sdlc/contract-lock.json" }
446
+ "inheritedFrom": "EP-checkout", "ref": "../../EP-checkout/.sdlc/contract-lock.json" }
447
447
  ```
448
448
 
449
449
  Omitting `architecture` from `inherits` (depth `contract-surface`) is what triggers a **real re-lock**:
@@ -455,9 +455,9 @@ architecture gate" with "open a contract-surface change-epic" — one mechanism,
455
455
  Intake + triage record, one per change/defect/hotfix epic (sibling of `approvals.json`).
456
456
 
457
457
  ```json
458
- { "epicId": "EP-istifta-queue-filter", "thread": "EP-istifta-inquiries", "parent": "EP-istifta-inquiries",
458
+ { "epicId": "EP-checkout-queue-filter", "thread": "EP-checkout", "parent": "EP-checkout",
459
459
  "kind": "defect", "depth": "defect-fix", "intakeBy": "alice", "intakeDate": "<YYYY-MM-DD>",
460
- "title": "Pending queue returns answered inquiries", "description": "…",
460
+ "title": "Pending queue returns fulfilled orders", "description": "…",
461
461
  "affectedArtifacts": ["stories", "test-cases"],
462
462
  "reauthors": ["stories", "test-cases"], "inherits": ["epic", "architecture", "contract", "ui-design"],
463
463
  "defect": { "origin": "production", "severity": "sev2", "escape_stage": "test-cases",
@@ -476,7 +476,7 @@ sharing `thread` and read each `change.json`; there is no duplicated thread regi
476
476
  Append-only ledger of hotfix ship-first debt (a hotfix shipped code before its front gates approved).
477
477
 
478
478
  ```json
479
- [ { "thread": "EP-istifta-inquiries", "epicId": "EP-istifta-hotfix-x", "openedDate": "<date>",
479
+ [ { "thread": "EP-checkout", "epicId": "EP-checkout-hotfix-x", "openedDate": "<date>",
480
480
  "reason": "prod outage", "requires": ["artifacts-updated", "regression-test"],
481
481
  "status": "open", "paidDate": null, "paidBy": null,
482
482
  "evidence": { "artifacts": [], "regressionTest": "" } } ]
@@ -23,9 +23,9 @@ declares; it does not redesign, does not widen the contract, and does not pick u
23
23
  - The work happens **inside the code repo** (a separate git repo) at
24
24
  `{project-root}/demo-repos/<repo>/` (`config.yaml` `build.code_repos_root`). Use absolute paths.
25
25
  - **Branch name:** `feat/<story-id>-<task-id>-<short-slug>` (e.g.
26
- `feat/EP-istifta-inquiries-S01-T01-create-inquiry`). Branched off the code repo's default branch.
26
+ `feat/EP-checkout-S01-T01-create-order`). Branched off the code repo's default branch.
27
27
  - **Commit message:** a conventional subject, body describing the change, and a **required `Task:`
28
- trailer** (e.g. `Task: EP-istifta-inquiries-S01-T01`) in the trailer block. Add `Contract-Change: yes`
28
+ trailer** (e.g. `Task: EP-checkout-S01-T01`) in the trailer block. Add `Contract-Change: yes`
29
29
  **only** if the diff touches the locked contract surface (see Step 5), and a per-commit
30
30
  `Co-Authored-By:` for any AI tool that helped author the diff (the human author owns the commit;
31
31
  trailer order `Task:` → `Contract-Change:` → `Co-Authored-By:`). The skill installs a `.gitmessage`
@@ -84,7 +84,7 @@ boundary breach). The same applies to the Step 5 contract-surface stop (`contrac
84
84
  ### Step 5 — Contract-surface check (local pre-flight for Step C)
85
85
  Determine whether the diff touches the **locked contract surface** (the API/event/data-model shapes in
86
86
  `epics/<epic>/contract.md`'s `CONTRACT-SURFACE` block). Normal implementation **consumes** the
87
- contract (e.g. implementing `POST /inquiries` to the agreed shape) — that is **not** a contract change.
87
+ contract (e.g. implementing `POST /orders` to the agreed shape) — that is **not** a contract change.
88
88
  A contract change means the diff alters the agreed cross-repo shape itself.
89
89
 
90
90
  - If the diff does **not** change the surface: proceed; no `Contract-Change` trailer.
@@ -10,11 +10,11 @@ diff back to its task, story, and contract.
10
10
  feat/<story-id>-<task-id>-<short-slug>
11
11
  ```
12
12
 
13
- - `<story-id>` — the permanent story ID, e.g. `EP-istifta-inquiries-S01`.
13
+ - `<story-id>` — the permanent story ID, e.g. `EP-checkout-S01`.
14
14
  - `<task-id>` — the atomic task ID from `tasks.md`, e.g. `T01`.
15
- - `<short-slug>` — 2–4 hyphenated words naming the change, e.g. `create-inquiry`.
15
+ - `<short-slug>` — 2–4 hyphenated words naming the change, e.g. `create-order`.
16
16
 
17
- Example: `feat/EP-istifta-inquiries-S01-T01-create-inquiry`. Branched off the code repo's default
17
+ Example: `feat/EP-checkout-S01-T01-create-order`. Branched off the code repo's default
18
18
  branch. One task = one branch; never reuse a branch for a different task, never fork a second branch
19
19
  for the same task.
20
20
 
@@ -33,9 +33,9 @@ Task: <story-id>-<task-id>
33
33
  - The **`<type>` is lowercase** (`feat`, `fix`, `docs`, `refactor`, `test`, `perf`, `build`, `ci`,
34
34
  `chore`, `revert`) and the **`<subject>` starts lowercase**, is **imperative**, and has **no trailing
35
35
  period** — Conventional Commits (see `CONTRIBUTING.md` and `config.yaml` `build.commit_subject_style`).
36
- Proper nouns/acronyms keep their case (`fix: refresh OAuth token`). e.g. `feat: add POST /inquiries
37
- create path`, not `feat: Add POST /inquiries create path.`
38
- - The **`Task:` trailer is required** (`Task: EP-istifta-inquiries-S01-T01`) — the anchor the spec-link
36
+ Proper nouns/acronyms keep their case (`fix: refresh OAuth token`). e.g. `feat: add POST /orders
37
+ create path`, not `feat: Add POST /orders create path.`
38
+ - The **`Task:` trailer is required** (`Task: EP-checkout-S01-T01`) — the anchor the spec-link
39
39
  check (§C) and the PR (§D) read to connect the diff to its spec and story. It need not be the *last*
40
40
  line: the spec-link gate finds it with git's native trailer parser
41
41
  (`%(trailers:key=Task)`), which is order-independent. All trailers must sit in **one contiguous block**
@@ -85,7 +85,7 @@ The **locked contract surface** is the cross-repo agreement in `epics/<epic>/con
85
85
  `CONTRACT-SURFACE` block, hash-locked at `.sdlc/contract-lock.json`). Distinguish:
86
86
 
87
87
  - **Consuming the contract** (normal) — implementing an endpoint/event/entity to the shape the contract
88
- already agreed (e.g. building `POST /inquiries` to its agreed request/response). **Not** a contract
88
+ already agreed (e.g. building `POST /orders` to its agreed request/response). **Not** a contract
89
89
  change; no trailer.
90
90
  - **Changing the contract** (exceptional) — altering the agreed shape itself (new field crossing repos,
91
91
  changed status enum, new shared endpoint). This is **not** an implementation decision. Stop, go back
@@ -25,7 +25,7 @@ is the same graceful-degradation pattern `yad-ui` uses for Impeccable.
25
25
  - **Code repos are separate git repos**, one `.git` each, under `{project-root}/demo-repos/<repo>/`
26
26
  (`config.yaml` `build.code_repos_root`). All Spec Kit outputs land **inside the code repo**, never
27
27
  in the product repo.
28
- - `{feature-id}` is the **story ID** (e.g. `EP-istifta-inquiries-S01`) — **pinned**, never Spec Kit's
28
+ - `{feature-id}` is the **story ID** (e.g. `EP-checkout-S01`) — **pinned**, never Spec Kit's
29
29
  numbered auto-slug (which is unstable and severs the permanent story link). The spec folder is
30
30
  `specs/<story-id>/`.
31
31
  - Spec Kit output layout (RESEARCH-NOTES §2): `specs/<feature-id>/spec.md` (+ `research.md`,
@@ -48,11 +48,11 @@ comes from the story's acceptance criteria and the **locked contract surface**
48
48
  contract endpoints/entities the story touches.
49
49
  - **`research.md`** — list the decisions and any unknowns; if the story is unambiguous, say so. Note
50
50
  where the contract already settles a question (e.g. status is server-owned).
51
- - **`data-model.md`** — the entities/fields **this repo** implements. Shared entities (e.g. `Inquiry`,
52
- `InquiryStatus`) are **quoted from the contract** and marked as contract-owned; repo-private fields
51
+ - **`data-model.md`** — the entities/fields **this repo** implements. Shared entities (e.g. `Order`,
52
+ `OrderStatus`) are **quoted from the contract** and marked as contract-owned; repo-private fields
53
53
  are marked as local.
54
54
  - **`contracts/`** — the slice of the API/event surface this repo implements, **quoted from the locked
55
- `contract.md`** (e.g. `POST /inquiries` request/response). Add a one-line note that this is a quote of
55
+ `contract.md`** (e.g. `POST /orders` request/response). Add a one-line note that this is a quote of
56
56
  the locked surface, not a new definition.
57
57
  - **`plan.md`** — the technical approach for this repo at story altitude (components, sequence,
58
58
  test approach). No new cross-repo surface.
@@ -38,7 +38,7 @@ Print, in this order:
38
38
  1. **Header:** render the kind noun from `epic.md` frontmatter `kind` — **Change request** (`change`),
39
39
  **Defect** (`defect`), **Hotfix** (`hotfix`), or **Epic** (`feature`, and the default when `kind` is
40
40
  absent) — followed by `epicId`, then `status` from `epic.md` frontmatter, `currentStep`, and `repos`
41
- (the touched domains). Example: `Defect EP-istifta-queue-filter — draft @ stories`. A bug is a defect
41
+ (the touched domains). Example: `Defect EP-checkout-queue-filter — draft @ stories`. A bug is a defect
42
42
  (`kind: defect`) — there is no separate noun. This is presentation only; the artifact is still an epic.
43
43
  2. **Steps table** — for every front step in `steps[]` order (10, or 12 when the optional analysis step
44
44
  was run): `id`, `type`, `status`, `assistance`, `automation`, `locked`, and `risk_tags`. Mark the
@@ -18,7 +18,7 @@ There is **no `sm` agent** (Phase 0 Deviation 1): the `pm` lens breaks down the
18
18
 
19
19
  - `{project-root}` resolves from the project working directory.
20
20
  - Stories live under `{project-root}/epics/EP-<slug>/stories/` (build plan §6).
21
- - Story files are named `EP-<slug>-S0N.md` (zero-padded, e.g. `EP-istifta-inquiries-S01.md`).
21
+ - Story files are named `EP-<slug>-S0N.md` (zero-padded, e.g. `EP-checkout-S01.md`).
22
22
  - Speak in the configured `communication_language`; write documents in `document_output_language`.
23
23
 
24
24
  ## On Activation
@@ -152,7 +152,7 @@ When Step 3b generated or linked automation, write the machine-readable case→t
152
152
  "direction": "generated | linked",
153
153
  "tests": [
154
154
  { "case": "TC-01", "story": "EP-<slug>-S01", "repo": "backend", "level": "e2e",
155
- "path": "tests/inquiry.spec.ts", "url": "<repo url to the test>" }
155
+ "path": "tests/order.spec.ts", "url": "<repo url to the test>" }
156
156
  ],
157
157
  "source": "playwright-mcp"
158
158
  }
@@ -45,7 +45,7 @@ Written by `yad-test-cases` Step 4b. Absent when the step ran artifacts-only (`t
45
45
  "direction": "generated | linked",
46
46
  "tests": [
47
47
  { "case": "TC-01", "story": "EP-<slug>-S01", "repo": "backend", "level": "e2e",
48
- "path": "tests/inquiry.spec.ts", "url": "<repo url to the test>" }
48
+ "path": "tests/order.spec.ts", "url": "<repo url to the test>" }
49
49
  ],
50
50
  "source": "playwright-mcp"
51
51
  }
@@ -160,7 +160,7 @@ When Step 3b generated or linked a design, write the machine-readable screen→f
160
160
  "generatedAt": "<YYYY-MM-DD>",
161
161
  "direction": "generated | linked",
162
162
  "screens": [
163
- { "name": "Submit Inquiry", "platform": "mobile",
163
+ { "name": "Checkout", "platform": "mobile",
164
164
  "nodeId": "123:45", "url": "https://www.figma.com/file/<key>/?node-id=123-45" }
165
165
  ],
166
166
  "source": "figma-mcp"