takt-marp 0.2.1 → 0.4.0
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/README.ja.md +18 -18
- package/README.md +18 -18
- package/fixtures/marp-slide-workflow/_workflow-smoke/brief.md +100 -14
- package/fixtures/marp-slide-workflow/_workflow-smoke/research/research-brief.md +12 -0
- package/package.json +9 -6
- package/scripts/lib/takt-marp-cli.mjs +90 -44
- package/scripts/lib/takt-marp-errors.mjs +11 -0
- package/scripts/lib/takt-marp-project-eject.mjs +136 -0
- package/scripts/lib/takt-marp-project-templates.mjs +108 -1
- package/scripts/lib/takt-marp-runtime-context.mjs +1 -0
- package/scripts/lib/takt-marp-slide-artifact-target.mjs +70 -0
- package/scripts/lib/takt-marp-slide-workflow.mjs +177 -43
- package/scripts/takt-marp-build-slide-artifact.mjs +9 -69
- package/scripts/takt-marp-preview-slide.mjs +91 -0
- package/scripts/takt-marp-run-slide-workflow.mjs +106 -16
- package/scripts/takt-marp-sync-project-templates.mjs +5 -16
- package/scripts/takt-marp-validate-global-install.mjs +426 -99
- package/scripts/takt-marp-validate-installer-ci-entrypoint.mjs +96 -0
- package/scripts/takt-marp-validate-package-boundary.mjs +19 -8
- package/scripts/takt-marp-validate-slide-workflow-foundation.mjs +2920 -50
- package/scripts/takt-marp-validate-slide-workflow-smoke.mjs +1052 -78
- package/templates/project/facets/instructions/takt-marp-adapt-research.md +35 -0
- package/templates/project/facets/instructions/takt-marp-ai-antipattern-fix.md +3 -3
- package/templates/project/facets/instructions/takt-marp-analyze-reference-deck.md +40 -0
- package/templates/project/facets/instructions/takt-marp-assemble-slides.md +36 -0
- package/templates/project/facets/instructions/takt-marp-compose-fix.md +2 -2
- package/templates/project/facets/instructions/takt-marp-compose-review.md +7 -6
- package/templates/project/facets/instructions/takt-marp-compose-sections.md +31 -0
- package/templates/project/facets/instructions/takt-marp-compose-work-summary.md +6 -3
- package/templates/project/facets/instructions/takt-marp-deliver-build.md +1 -1
- package/templates/project/facets/instructions/takt-marp-design-system.md +6 -4
- package/templates/project/facets/instructions/takt-marp-normalize-brief.md +8 -2
- package/templates/project/facets/instructions/takt-marp-plan-fix.md +4 -3
- package/templates/project/facets/instructions/takt-marp-plan-review.md +20 -4
- package/templates/project/facets/instructions/takt-marp-plan-work-summary.md +12 -5
- package/templates/project/facets/instructions/takt-marp-plan.md +30 -8
- package/templates/project/facets/instructions/takt-marp-polish-fix.md +2 -2
- package/templates/project/facets/instructions/takt-marp-polish-inspect.md +1 -1
- package/templates/project/facets/instructions/takt-marp-supervise-research.md +23 -0
- package/templates/project/facets/instructions/takt-marp-visual-generate.md +15 -15
- package/templates/project/facets/knowledge/takt-marp-repo-conventions.md +26 -4
- package/templates/project/facets/output-contracts/takt-marp-normalized-brief.md +19 -1
- package/templates/project/facets/output-contracts/takt-marp-open-questions.md +48 -0
- package/templates/project/facets/output-contracts/takt-marp-reference-analysis.md +52 -0
- package/templates/project/facets/output-contracts/takt-marp-research-claims.md +50 -0
- package/templates/project/facets/output-contracts/takt-marp-research-sources.md +50 -0
- package/templates/project/facets/output-contracts/takt-marp-research-supervision.md +49 -0
- package/templates/project/facets/output-contracts/takt-marp-section-compose.md +36 -0
- package/templates/project/facets/output-contracts/takt-marp-slide-blueprint.md +44 -0
- package/templates/project/facets/output-contracts/takt-marp-slide-plan.md +30 -2
- package/templates/project/facets/policies/takt-marp-general-slide-quality.md +1 -1
- package/templates/project/facets/policies/takt-marp-slide-quality.md +6 -4
- package/templates/project/facets/policies/takt-marp-visual-composition.md +87 -0
- package/templates/project/workflows/takt-marp-slide-compose.yaml +37 -18
- package/templates/project/workflows/takt-marp-slide-plan.yaml +32 -4
- package/templates/project/workflows/takt-marp-slide-polish.yaml +5 -5
- package/templates/project/workflows/takt-marp-slide-research.yaml +81 -0
- package/scripts/lib/takt-marp-project-init.mjs +0 -81
- package/templates/project/facets/instructions/takt-marp-compose-slides.md +0 -35
- package/templates/project/facets/policies/takt-marp-svg-first-visual.md +0 -68
package/README.ja.md
CHANGED
|
@@ -6,7 +6,7 @@ Marpスライドデッキと、半自動でデッキを生成するためのTAKT
|
|
|
6
6
|
|
|
7
7
|
## TAKT Marp workflow
|
|
8
8
|
|
|
9
|
-
このworkflowは `slides/<deck>/brief.md` を起点に、`plan`、`compose`、`polish`、`deliver`
|
|
9
|
+
このworkflowは `slides/<deck>/brief.md` を起点に、`plan`、`compose`、`polish`、`deliver` の状態へ進めます。外部調査が必要な deck だけ、任意で先に `research` を実行します。
|
|
10
10
|
|
|
11
11
|
詳細なworkflow contract: [docs/marp-slide-workflow.md](docs/marp-slide-workflow.md)
|
|
12
12
|
|
|
@@ -34,21 +34,23 @@ Output Requirementsの例:
|
|
|
34
34
|
### 2. workflowを実行する
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
takt-marp research "slides/<deck>"
|
|
38
|
+
takt-marp plan "slides/<deck>"
|
|
39
|
+
takt-marp approve "slides/<deck>" plan --by <name>
|
|
40
|
+
takt-marp compose "slides/<deck>"
|
|
41
|
+
takt-marp approve "slides/<deck>" compose --by <name>
|
|
42
|
+
takt-marp polish "slides/<deck>"
|
|
43
|
+
takt-marp deliver "slides/<deck>"
|
|
43
44
|
```
|
|
44
45
|
|
|
45
46
|
targetは `slides/<deck>` を指定します。
|
|
46
47
|
|
|
47
48
|
```bash
|
|
48
|
-
|
|
49
|
+
takt-marp plan "slides/<deck>"
|
|
49
50
|
```
|
|
50
51
|
|
|
51
|
-
人間承認は `plan` と `compose` に対してのみ `
|
|
52
|
+
人間承認は `plan` と `compose` に対してのみ `takt-marp approve` で記録します。`review`、`revise`、`qa`、`build-qa` はworkflow内部の責務であり、トップレベルコマンドではありません。
|
|
53
|
+
`research` は `slides/<deck>/research/research-brief.md` を読み、`plan` の必須前提ではありません。
|
|
52
54
|
|
|
53
55
|
### 3. 生成されるファイル
|
|
54
56
|
|
|
@@ -59,6 +61,7 @@ slides/<deck>/
|
|
|
59
61
|
design-system.md
|
|
60
62
|
SLIDES.md
|
|
61
63
|
images/*.svg
|
|
64
|
+
research/*.md
|
|
62
65
|
review/*.md
|
|
63
66
|
```
|
|
64
67
|
|
|
@@ -75,24 +78,21 @@ slides/<deck>/
|
|
|
75
78
|
- spatial balance: 上寄り、左寄り、大きな意図しない余白、視覚重心
|
|
76
79
|
- design-system usage: token化されたCSS、スライドごとのstyle drift防止
|
|
77
80
|
|
|
78
|
-
`deliver`
|
|
81
|
+
`deliver` は要求された成果物を生成し、delivery verification と supervision まで行います。
|
|
82
|
+
単純なローカル生成や確認だけなら、workflow state を変更しない utility command を使います。
|
|
79
83
|
|
|
80
84
|
```bash
|
|
81
|
-
|
|
85
|
+
takt-marp build:html <deck>
|
|
86
|
+
takt-marp build:pdf <deck>
|
|
87
|
+
takt-marp preview <deck>
|
|
82
88
|
```
|
|
83
89
|
|
|
84
90
|
### 5. 検証
|
|
85
91
|
|
|
86
|
-
軽量なローカル確認には foundation validation を使います。
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
npm test
|
|
90
|
-
```
|
|
91
|
-
|
|
92
92
|
workflow routing、state gate、render evidence、delivery verification、approval handling を変更した場合は smoke validation を実行します。
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
-
|
|
95
|
+
takt-marp smoke --keep
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
smoke validation は fixture から一時的な `_workflow-smoke` deck を作成し、invalid target、approval failure path、`plan` -> `compose` -> `polish` -> `deliver` の一連の実行、render evidence metadata、delivery artifact、rerun/force behavior を検証します。`--keep` を付けると、生成された deck と report を `slides/_workflow-smoke/` に残して確認できます。
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Marp slide decks and a TAKT workflow for semi-automated deck generation.
|
|
|
6
6
|
|
|
7
7
|
## TAKT Marp workflow
|
|
8
8
|
|
|
9
|
-
The workflow starts from `slides/<deck>/brief.md` and moves through `plan`, `compose`, `polish`, and `deliver`.
|
|
9
|
+
The workflow starts from `slides/<deck>/brief.md` and moves through `plan`, `compose`, `polish`, and `deliver`. Use optional `research` first only when a deck needs external research context.
|
|
10
10
|
|
|
11
11
|
Detailed workflow contract: [docs/marp-slide-workflow.md](docs/marp-slide-workflow.md)
|
|
12
12
|
|
|
@@ -34,21 +34,23 @@ Example output requirement:
|
|
|
34
34
|
### 2. Run the workflows
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
takt-marp research "slides/<deck>"
|
|
38
|
+
takt-marp plan "slides/<deck>"
|
|
39
|
+
takt-marp approve "slides/<deck>" plan --by <name>
|
|
40
|
+
takt-marp compose "slides/<deck>"
|
|
41
|
+
takt-marp approve "slides/<deck>" compose --by <name>
|
|
42
|
+
takt-marp polish "slides/<deck>"
|
|
43
|
+
takt-marp deliver "slides/<deck>"
|
|
43
44
|
```
|
|
44
45
|
|
|
45
46
|
Use `slides/<deck>` as the target:
|
|
46
47
|
|
|
47
48
|
```bash
|
|
48
|
-
|
|
49
|
+
takt-marp plan "slides/<deck>"
|
|
49
50
|
```
|
|
50
51
|
|
|
51
|
-
Human approval is recorded by `
|
|
52
|
+
Human approval is recorded by `takt-marp approve` for `plan` and `compose` only. `review`, `revise`, `qa`, and `build-qa` are internal workflow responsibilities, not top-level commands.
|
|
53
|
+
`research` reads `slides/<deck>/research/research-brief.md` and is not required before `plan`.
|
|
52
54
|
|
|
53
55
|
### 3. Generated files
|
|
54
56
|
|
|
@@ -59,6 +61,7 @@ slides/<deck>/
|
|
|
59
61
|
design-system.md
|
|
60
62
|
SLIDES.md
|
|
61
63
|
images/*.svg
|
|
64
|
+
research/*.md
|
|
62
65
|
review/*.md
|
|
63
66
|
```
|
|
64
67
|
|
|
@@ -75,24 +78,21 @@ slides/<deck>/
|
|
|
75
78
|
- spatial balance: top/left bias, large unintended blank areas, visual center of gravity
|
|
76
79
|
- design-system usage: tokenized CSS, no per-slide style drift
|
|
77
80
|
|
|
78
|
-
`deliver` is responsible for requested artifacts
|
|
81
|
+
`deliver` is responsible for requested artifacts, delivery verification, and final supervision.
|
|
82
|
+
For simple local generation or inspection, use utility commands that do not change workflow state:
|
|
79
83
|
|
|
80
84
|
```bash
|
|
81
|
-
|
|
85
|
+
takt-marp build:html <deck>
|
|
86
|
+
takt-marp build:pdf <deck>
|
|
87
|
+
takt-marp preview <deck>
|
|
82
88
|
```
|
|
83
89
|
|
|
84
90
|
### 5. Validation
|
|
85
91
|
|
|
86
|
-
Use the foundation validation for fast local checks:
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
npm test
|
|
90
|
-
```
|
|
91
|
-
|
|
92
92
|
Use the smoke validation when changing workflow routing, state gates, render evidence, delivery verification, or approval handling:
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
-
|
|
95
|
+
takt-marp smoke --keep
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
The smoke validation creates a temporary `_workflow-smoke` deck from the fixture, exercises invalid target and approval failure paths, runs the `plan` -> `compose` -> `polish` -> `deliver` sequence, verifies render evidence metadata, checks delivery artifacts, and covers rerun/force behavior. `--keep` leaves the generated deck and reports under `slides/_workflow-smoke/` for inspection.
|
|
@@ -1,26 +1,65 @@
|
|
|
1
|
-
# Brief
|
|
1
|
+
# Workflow Smoke Deck Brief
|
|
2
2
|
|
|
3
3
|
## Event
|
|
4
|
-
- Name:
|
|
5
|
-
- Date:
|
|
6
|
-
- Duration:
|
|
7
|
-
- Venue:
|
|
8
|
-
-
|
|
4
|
+
- Name: 架空研修ラボ ドメインモデリング講座
|
|
5
|
+
- Date: 2031年4月17日(木)10:00〜16:30
|
|
6
|
+
- Duration: 360 minutes
|
|
7
|
+
- Venue: ミラージュホール A / サンプル配信スタジオ
|
|
8
|
+
- Organizer: サンプル研修ラボ株式会社
|
|
9
|
+
- Audience: メンテナとワークフロー検証者
|
|
9
10
|
|
|
10
11
|
## Goal
|
|
11
|
-
Marp slide TAKT workflow
|
|
12
|
+
Marp slide TAKT workflow が、情報量の多い講義ブリーフから normalized brief、reference analysis、coverage matrix、slide blueprint、section source、HTML/CSS visual、SVG visual、review、build QA まで接続できることを確認する。
|
|
13
|
+
|
|
14
|
+
## Critical Constraints
|
|
15
|
+
- Official Title: 変更に強いドメインモデリングの実践ワークショップ
|
|
16
|
+
- Speaker Name: 山田 サンプル
|
|
17
|
+
- Speaker Affiliation: サンプルデザイン合同会社
|
|
18
|
+
- Design: 白基調だが白黒ではない。カラー印刷を前提に、青・緑・橙・赤を意味づけて使う。
|
|
19
|
+
- Information Density: 投影だけでなく印刷配布テキストとして読める密度を許容する。
|
|
20
|
+
|
|
21
|
+
### Fixed Outline
|
|
22
|
+
1. 入力を正にする
|
|
23
|
+
(1)briefを保全する
|
|
24
|
+
a. 正式タイトル、講師名、所属を落とさない
|
|
25
|
+
b. 禁止語と避けるべき表現を保持する
|
|
26
|
+
(2)事実を棚卸しする
|
|
27
|
+
a. 架空の日時、主催、形式、対象、場所をFact Inventoryに残す
|
|
28
|
+
b. Target slide countと要求密度の矛盾をfindingにする
|
|
29
|
+
2. 設計をplanへ渡す
|
|
30
|
+
(1)coverage matrixを作る
|
|
31
|
+
a. 固定アウトラインの全leaf項目をslide IDへ対応させる
|
|
32
|
+
b. 未対応項目はneeds_inputではなくPlan Findingsへ残す
|
|
33
|
+
(2)visual strategyを決める
|
|
34
|
+
a. カード、比較、表、軽量フローはhtml:で構成する
|
|
35
|
+
b. 座標制御や複雑な矢印だけsvg:またはinline-svg:にする
|
|
36
|
+
3. section sourceからassembleする
|
|
37
|
+
(1)blueprintを分ける
|
|
38
|
+
a. slide-blueprint.mdにcontent atomsとsection manifestを残す
|
|
39
|
+
b. sections/*.mdからSLIDES.mdへassembleする
|
|
40
|
+
(2)deliveryを検証する
|
|
41
|
+
a. HTMLとPDFをbuildできることを確認する
|
|
42
|
+
b. generated artifactをsource artifactへ混ぜない
|
|
12
43
|
|
|
13
44
|
## Core Message
|
|
14
|
-
半自動のMarp生成workflow
|
|
45
|
+
半自動のMarp生成workflowは、入力、coverage、blueprint、section source、visual、レビュー、QAを分離すると安定する。
|
|
15
46
|
|
|
16
47
|
## Audience Context
|
|
17
48
|
聴衆はこのリポジトリのメンテナであり、TAKTとMarpの基本を理解している。
|
|
18
49
|
|
|
19
50
|
## Required Topics
|
|
20
|
-
- brief
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
51
|
+
- 1. 入力を正にする > (1)briefを保全する > a. 正式タイトル、講師名、所属を落とさない
|
|
52
|
+
- 1. 入力を正にする > (1)briefを保全する > b. 禁止語と避けるべき表現を保持する
|
|
53
|
+
- 1. 入力を正にする > (2)事実を棚卸しする > a. 架空の日時、主催、形式、対象、場所をFact Inventoryに残す
|
|
54
|
+
- 1. 入力を正にする > (2)事実を棚卸しする > b. Target slide countと要求密度の矛盾をfindingにする
|
|
55
|
+
- 2. 設計をplanへ渡す > (1)coverage matrixを作る > a. 固定アウトラインの全leaf項目をslide IDへ対応させる
|
|
56
|
+
- 2. 設計をplanへ渡す > (1)coverage matrixを作る > b. 未対応項目はneeds_inputではなくPlan Findingsへ残す
|
|
57
|
+
- 2. 設計をplanへ渡す > (2)visual strategyを決める > a. カード、比較、表、軽量フローはhtml:で構成する
|
|
58
|
+
- 2. 設計をplanへ渡す > (2)visual strategyを決める > b. 座標制御や複雑な矢印だけsvg:またはinline-svg:にする
|
|
59
|
+
- 3. section sourceからassembleする > (1)blueprintを分ける > a. slide-blueprint.mdにcontent atomsとsection manifestを残す
|
|
60
|
+
- 3. section sourceからassembleする > (1)blueprintを分ける > b. sections/*.mdからSLIDES.mdへassembleする
|
|
61
|
+
- 3. section sourceからassembleする > (2)deliveryを検証する > a. HTMLとPDFをbuildできることを確認する
|
|
62
|
+
- 3. section sourceからassembleする > (2)deliveryを検証する > b. generated artifactをsource artifactへ混ぜない
|
|
24
63
|
|
|
25
64
|
## Optional Topics
|
|
26
65
|
- appendixは必要な場合だけ作る
|
|
@@ -29,16 +68,63 @@ Marp slide TAKT workflow が brief から plan、draft、SVG、review、build QA
|
|
|
29
68
|
- Web画像の自動取得
|
|
30
69
|
- 他deck画像の自動流用
|
|
31
70
|
- 長い本文をスライドに詰め込むこと
|
|
71
|
+
- SVG-firstという方針に戻すこと
|
|
72
|
+
- htmlで十分なカード、比較、表、軽量フローをSVG化すること
|
|
73
|
+
- サンプル主催名、架空日付、架空場所を実在情報に置き換えること
|
|
32
74
|
|
|
33
75
|
## Source Materials
|
|
34
76
|
- docs/marp-slide-workflow.md
|
|
77
|
+
- _workflow-smoke internal synthetic brief only
|
|
35
78
|
|
|
36
79
|
## Speaker Notes
|
|
37
|
-
短い確認用deckなので、各スライドのnotesは2-3文でよい。
|
|
80
|
+
短い確認用deckなので、各スライドのnotesは2-3文でよい。Durationが分単位で指定されているため、notesには尺マーカーを付ける。
|
|
38
81
|
|
|
39
82
|
## Output Requirements
|
|
40
83
|
- Format: Marp
|
|
41
84
|
- Language: Japanese
|
|
42
85
|
- Target slide count: 5
|
|
86
|
+
- Deck Mode: overview
|
|
43
87
|
- Deliverables: html, pdf
|
|
44
|
-
-
|
|
88
|
+
- Slide Count Consistency Scenario: Target slide count: 5 は概要版として扱う。講義本体を要求する場合は100〜140または期待値相当へ修正する必要がある、というPlan Findingを作れること。
|
|
89
|
+
- Visual scope: html: cards/comparison/table/light-flow を優先し、座標制御が必要な1箇所だけ inline-svg: を使う。未使用SVG placeholderを計画しない。
|
|
90
|
+
|
|
91
|
+
## Fact Inventory
|
|
92
|
+
- 主催: サンプル研修ラボ株式会社
|
|
93
|
+
- 形式: ミラージュホール A / サンプル配信スタジオ
|
|
94
|
+
- 日時: 2031年4月17日(木)10:00〜16:30
|
|
95
|
+
- 対象: メンテナとワークフロー検証者
|
|
96
|
+
- 場所: ミラージュホール A
|
|
97
|
+
- 講師所属: サンプルデザイン合同会社
|
|
98
|
+
|
|
99
|
+
## Terminology Policy
|
|
100
|
+
- Domain-Driven Design はドメイン駆動設計と表記する。
|
|
101
|
+
- Workflow は workflow と英字表記で統一する。
|
|
102
|
+
- Fixed Outline の語句は言い換えない。
|
|
103
|
+
|
|
104
|
+
## Example Policy
|
|
105
|
+
- 共通題材は「備品購入申請・承認」とし、章をまたいで一貫利用する。
|
|
106
|
+
|
|
107
|
+
## Code Example Policy
|
|
108
|
+
- Java風の疑似コードでBefore / Afterを示す。
|
|
109
|
+
- 業務の意味がコード構造へ表れることを示す。
|
|
110
|
+
- フレームワーク固有APIへ寄せすぎない。
|
|
111
|
+
|
|
112
|
+
## Exercise Policy
|
|
113
|
+
- 短時間の個人演習にする。
|
|
114
|
+
- 模範回答または解説を巻末またはnotesに残す。
|
|
115
|
+
|
|
116
|
+
## Appendix Requirements
|
|
117
|
+
- 用語集
|
|
118
|
+
- 実践チェックリスト
|
|
119
|
+
- 演習模範回答
|
|
120
|
+
|
|
121
|
+
## Quality Checklist
|
|
122
|
+
- 正式タイトル完全一致
|
|
123
|
+
- 講師所属がサンプルデザイン合同会社
|
|
124
|
+
- 禁止語を使わない
|
|
125
|
+
- 固定アウトラインを変更しない
|
|
126
|
+
- 白基調だが白黒ではない
|
|
127
|
+
- coverage matrixに全leaf項目がある
|
|
128
|
+
- html: visual と svg:/inline-svg: visual の責務が分かれている
|
|
129
|
+
- sections/*.mdからSLIDES.mdへassembleできる
|
|
130
|
+
- build:html / build:pdf が成功する
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Workflow Smoke Research Brief
|
|
2
|
+
|
|
3
|
+
## Research Goal
|
|
4
|
+
Validate that the optional research command can synchronize built-in deep research output into deck-local research artifacts before planning.
|
|
5
|
+
|
|
6
|
+
## Scope
|
|
7
|
+
- Use only deterministic mock research content.
|
|
8
|
+
- Preserve missing source URL, retrieval time, confidence, and claim-source mapping as absent information.
|
|
9
|
+
- Do not infer or supplement facts that are not present in the built-in research report.
|
|
10
|
+
|
|
11
|
+
## Expected Consumer
|
|
12
|
+
The subsequent plan command may read the generated research artifacts as optional context, while still using `brief.md` as the primary input.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "takt-marp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "takt-marp",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"node": ">=24"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
|
+
"slide:research": "node scripts/takt-marp-run-slide-workflow.mjs research",
|
|
23
24
|
"slide:plan": "node scripts/takt-marp-run-slide-workflow.mjs plan",
|
|
24
25
|
"slide:compose": "node scripts/takt-marp-run-slide-workflow.mjs compose",
|
|
25
26
|
"slide:polish": "node scripts/takt-marp-run-slide-workflow.mjs polish",
|
|
@@ -29,12 +30,14 @@
|
|
|
29
30
|
"slide:render-evidence": "node scripts/takt-marp-render-slide-workflow-evidence.mjs",
|
|
30
31
|
"slide:validate-foundation": "node scripts/takt-marp-validate-slide-workflow-foundation.mjs",
|
|
31
32
|
"slide:smoke": "node scripts/takt-marp-validate-slide-workflow-smoke.mjs",
|
|
32
|
-
"test": "npm run slide:validate-foundation",
|
|
33
|
+
"test": "npm run slide:validate-foundation && npm run slide:smoke -- --provider mock",
|
|
33
34
|
"build": "npm run build:html && npm run build:pdf",
|
|
34
|
-
"build:html": "
|
|
35
|
-
"build:pptx": "
|
|
36
|
-
"build:pdf": "
|
|
37
|
-
"preview": "
|
|
35
|
+
"build:html": "node scripts/takt-marp-build-slide-artifact.mjs html",
|
|
36
|
+
"build:pptx": "node scripts/takt-marp-build-slide-artifact.mjs pptx",
|
|
37
|
+
"build:pdf": "node scripts/takt-marp-build-slide-artifact.mjs pdf",
|
|
38
|
+
"preview": "node scripts/takt-marp-preview-slide.mjs takt-sdd",
|
|
39
|
+
"installer:ci": "npm run slide:validate-foundation && npm run installer:check-templates && npm run installer:check-package && npm run installer:validate && npm run slide:smoke -- --provider mock",
|
|
40
|
+
"installer:check-ci": "node scripts/takt-marp-validate-installer-ci-entrypoint.mjs",
|
|
38
41
|
"installer:sync-templates": "node scripts/takt-marp-sync-project-templates.mjs --write",
|
|
39
42
|
"installer:check-templates": "node scripts/takt-marp-sync-project-templates.mjs",
|
|
40
43
|
"installer:check-package": "node scripts/takt-marp-validate-package-boundary.mjs",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
import { statSync } from "node:fs";
|
|
3
2
|
import { mkdtemp } from "node:fs/promises";
|
|
4
3
|
import os from "node:os";
|
|
5
4
|
import path from "node:path";
|
|
6
5
|
import { parseArgs } from "node:util";
|
|
7
|
-
import {
|
|
6
|
+
import { ejectProject } from "./takt-marp-project-eject.mjs";
|
|
7
|
+
import { resolveTemplateSource, workflowFilePath } from "./takt-marp-project-templates.mjs";
|
|
8
8
|
import { packageScriptPath } from "./takt-marp-runtime-context.mjs";
|
|
9
9
|
import {
|
|
10
10
|
APPROVAL_COMMANDS,
|
|
@@ -12,19 +12,29 @@ import {
|
|
|
12
12
|
SlideWorkflowError,
|
|
13
13
|
} from "./takt-marp-slide-workflow.mjs";
|
|
14
14
|
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const RESEARCH_COMMANDS = ["research"];
|
|
16
|
+
const WORKFLOW_COMMANDS = [...RESEARCH_COMMANDS, "plan", "compose", "polish", "deliver"];
|
|
17
|
+
const BUILD_COMMANDS = Object.freeze({
|
|
18
|
+
"build:html": "html",
|
|
19
|
+
"build:pdf": "pdf",
|
|
20
|
+
"build:pptx": "pptx",
|
|
21
|
+
});
|
|
22
|
+
const UTILITY_COMMANDS = [...Object.keys(BUILD_COMMANDS), "preview"];
|
|
23
|
+
const VALID_COMMANDS = ["eject", ...WORKFLOW_COMMANDS, "approve", "smoke", ...UTILITY_COMMANDS];
|
|
17
24
|
const RUNNER_SCRIPT = "scripts/takt-marp-run-slide-workflow.mjs";
|
|
18
25
|
const APPROVE_SCRIPT = "scripts/takt-marp-approve-slide-workflow-state.mjs";
|
|
19
26
|
const SMOKE_SCRIPT = "scripts/takt-marp-validate-slide-workflow-smoke.mjs";
|
|
20
|
-
const
|
|
27
|
+
const BUILD_SCRIPT = "scripts/takt-marp-build-slide-artifact.mjs";
|
|
28
|
+
const PREVIEW_SCRIPT = "scripts/takt-marp-preview-slide.mjs";
|
|
29
|
+
const FORWARDED_SIGNALS = new Set(["SIGINT", "SIGTERM"]);
|
|
21
30
|
|
|
22
31
|
function usage() {
|
|
23
32
|
return [
|
|
24
33
|
"Usage: takt-marp <command> [arguments]",
|
|
25
34
|
"",
|
|
26
35
|
"Commands:",
|
|
27
|
-
"
|
|
36
|
+
" eject [dir] [--force|--overwrite] Copy .takt/workflows and .takt/facets templates into <dir> (default: .)",
|
|
37
|
+
" research <slides/deck> [options] Optional pre-research command before slide planning",
|
|
28
38
|
" plan <slides/deck> [options] Run the plan workflow for a deck in the current project",
|
|
29
39
|
" compose <slides/deck> [options] Run the compose workflow for a deck in the current project",
|
|
30
40
|
" polish <slides/deck> [options] Run the polish workflow for a deck in the current project",
|
|
@@ -32,6 +42,14 @@ function usage() {
|
|
|
32
42
|
" approve <slides/deck> <command> --by <name> [--force]",
|
|
33
43
|
" Approve a workflow state (command: plan or compose)",
|
|
34
44
|
" smoke [--provider <name>] Run smoke validation in a temporary project (default provider: mock)",
|
|
45
|
+
" build:html [deck|slides/<deck>|slides/<deck>/SLIDES.md]",
|
|
46
|
+
" Build HTML artifact without changing workflow state",
|
|
47
|
+
" build:pdf [deck|slides/<deck>|slides/<deck>/SLIDES.md]",
|
|
48
|
+
" Build PDF artifact without changing workflow state",
|
|
49
|
+
" build:pptx [deck|slides/<deck>|slides/<deck>/SLIDES.md]",
|
|
50
|
+
" Build PPTX artifact without changing workflow state",
|
|
51
|
+
" preview <deck|slides/<deck>|slides/<deck>/SLIDES.md>",
|
|
52
|
+
" Start Marp server mode without changing workflow state",
|
|
35
53
|
"",
|
|
36
54
|
"Workflow options (passed through to the workflow runner unchanged):",
|
|
37
55
|
" --force Invalidate an already-successful state and rerun",
|
|
@@ -39,11 +57,11 @@ function usage() {
|
|
|
39
57
|
].join("\n");
|
|
40
58
|
}
|
|
41
59
|
|
|
42
|
-
function
|
|
60
|
+
function ejectUsage() {
|
|
43
61
|
return [
|
|
44
|
-
"Usage: takt-marp
|
|
62
|
+
"Usage: takt-marp eject [dir] [--force|--overwrite]",
|
|
45
63
|
"",
|
|
46
|
-
"
|
|
64
|
+
"Copies .takt/workflows/** and .takt/facets/** templates into <dir> (default: current directory).",
|
|
47
65
|
"",
|
|
48
66
|
"Options:",
|
|
49
67
|
" --force Overwrite existing template-owned files",
|
|
@@ -52,43 +70,61 @@ function initUsage() {
|
|
|
52
70
|
].join("\n");
|
|
53
71
|
}
|
|
54
72
|
|
|
55
|
-
function isDirectory(candidatePath) {
|
|
56
|
-
const stats = statSync(candidatePath, { throwIfNoEntry: false });
|
|
57
|
-
return stats !== undefined && stats.isDirectory();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function assertProjectInitialized() {
|
|
61
|
-
const cwd = process.cwd();
|
|
62
|
-
const missing = REQUIRED_PROJECT_DIRS.filter(
|
|
63
|
-
(relative) => !isDirectory(path.join(cwd, ...relative.split("/"))),
|
|
64
|
-
);
|
|
65
|
-
if (missing.length > 0) {
|
|
66
|
-
throw new SlideWorkflowError(
|
|
67
|
-
`Target project is not initialized: missing ${missing.join(" and ")} in ${cwd}. Run 'takt-marp init .' first.`,
|
|
68
|
-
"PROJECT_NOT_INITIALIZED",
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
73
|
function runPackageScript(relativeScriptPath, args, options = {}) {
|
|
74
74
|
return new Promise((resolve, reject) => {
|
|
75
|
+
let stopping = false;
|
|
75
76
|
const child = spawn(process.execPath, [packageScriptPath(relativeScriptPath), ...args], {
|
|
76
77
|
cwd: options.cwd ?? process.cwd(),
|
|
77
78
|
stdio: "inherit",
|
|
78
79
|
});
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
const signalHandlers = [];
|
|
81
|
+
if (options.successOnSignal) {
|
|
82
|
+
for (const signal of FORWARDED_SIGNALS) {
|
|
83
|
+
const handler = () => {
|
|
84
|
+
stopping = true;
|
|
85
|
+
if (!child.killed) {
|
|
86
|
+
child.kill(signal);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
process.once(signal, handler);
|
|
90
|
+
signalHandlers.push([signal, handler]);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const cleanup = () => {
|
|
94
|
+
for (const [signal, handler] of signalHandlers) {
|
|
95
|
+
process.off(signal, handler);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
child.on("error", (error) => {
|
|
99
|
+
cleanup();
|
|
100
|
+
reject(error);
|
|
101
|
+
});
|
|
102
|
+
child.on("close", (code, signal) => {
|
|
103
|
+
cleanup();
|
|
104
|
+
if (options.successOnSignal && (stopping || FORWARDED_SIGNALS.has(signal))) {
|
|
105
|
+
resolve(0);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
81
108
|
resolve(code ?? 1);
|
|
82
109
|
});
|
|
83
110
|
});
|
|
84
111
|
}
|
|
85
112
|
|
|
86
113
|
async function runWorkflowCommand(command, args) {
|
|
87
|
-
|
|
88
|
-
|
|
114
|
+
const source = resolveTemplateSource({ projectRoot: process.cwd() });
|
|
115
|
+
const selectedWorkflowFilePath = workflowFilePath(source, command);
|
|
116
|
+
return runPackageScript(RUNNER_SCRIPT, [command, ...args, "--workflow-file", selectedWorkflowFilePath]);
|
|
89
117
|
}
|
|
90
118
|
|
|
91
|
-
async function
|
|
119
|
+
async function runBuildCommand(command, args) {
|
|
120
|
+
return runPackageScript(BUILD_SCRIPT, [BUILD_COMMANDS[command], ...args]);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function runPreview(args) {
|
|
124
|
+
return runPackageScript(PREVIEW_SCRIPT, args, { successOnSignal: true });
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async function runEject(args) {
|
|
92
128
|
let parsed;
|
|
93
129
|
try {
|
|
94
130
|
parsed = parseArgs({
|
|
@@ -102,26 +138,26 @@ async function runInit(args) {
|
|
|
102
138
|
});
|
|
103
139
|
} catch (error) {
|
|
104
140
|
throw new SlideWorkflowError(
|
|
105
|
-
`Invalid
|
|
141
|
+
`Invalid eject arguments: ${error.message}. Run 'takt-marp eject --help' for usage.`,
|
|
106
142
|
"INVALID_ARGS",
|
|
107
143
|
);
|
|
108
144
|
}
|
|
109
145
|
if (parsed.values.help) {
|
|
110
|
-
console.log(
|
|
146
|
+
console.log(ejectUsage());
|
|
111
147
|
return 0;
|
|
112
148
|
}
|
|
113
149
|
if (parsed.positionals.length > 1) {
|
|
114
150
|
throw new SlideWorkflowError(
|
|
115
|
-
`Unexpected extra
|
|
151
|
+
`Unexpected extra eject arguments: ${parsed.positionals.slice(1).join(" ")}. Run 'takt-marp eject --help' for usage.`,
|
|
116
152
|
"INVALID_ARGS",
|
|
117
153
|
);
|
|
118
154
|
}
|
|
119
155
|
|
|
120
156
|
const targetDir = path.resolve(process.cwd(), parsed.positionals[0] ?? ".");
|
|
121
157
|
const force = parsed.values.force || parsed.values.overwrite;
|
|
122
|
-
const { created, overwritten } = await
|
|
158
|
+
const { created, overwritten } = await ejectProject({ targetDir, force });
|
|
123
159
|
|
|
124
|
-
const lines = [`
|
|
160
|
+
const lines = [`Ejected takt-marp templates in ${targetDir}`];
|
|
125
161
|
lines.push(`Created ${created.length} file(s)${created.length > 0 ? ":" : "."}`);
|
|
126
162
|
for (const relativePath of created) {
|
|
127
163
|
lines.push(` ${relativePath}`);
|
|
@@ -137,7 +173,7 @@ async function runInit(args) {
|
|
|
137
173
|
"Next steps:",
|
|
138
174
|
" - Provider configuration stays under your ownership: takt-marp does not create or modify",
|
|
139
175
|
" TAKT provider settings, API keys, or credentials.",
|
|
140
|
-
" -
|
|
176
|
+
" - Edit ejected workflow/facet templates only when you need project-local customization.",
|
|
141
177
|
` - Run a workflow from the project root, e.g.: takt-marp plan slides/<deck>`,
|
|
142
178
|
);
|
|
143
179
|
console.log(lines.join("\n"));
|
|
@@ -146,8 +182,8 @@ async function runInit(args) {
|
|
|
146
182
|
|
|
147
183
|
async function runSmoke(args) {
|
|
148
184
|
// Smoke runs in a freshly created temporary project so the user's current
|
|
149
|
-
// project is never touched.
|
|
150
|
-
// the
|
|
185
|
+
// project is never touched. Template source selection stays no-copy by
|
|
186
|
+
// default; only the smoke validator may create smoke deck artifacts.
|
|
151
187
|
let tempProject;
|
|
152
188
|
try {
|
|
153
189
|
tempProject = await mkdtemp(path.join(os.tmpdir(), "takt-marp-smoke-"));
|
|
@@ -157,7 +193,6 @@ async function runSmoke(args) {
|
|
|
157
193
|
"SMOKE_PREPARE_FAILED",
|
|
158
194
|
);
|
|
159
195
|
}
|
|
160
|
-
await initializeProject({ targetDir: tempProject, force: false });
|
|
161
196
|
console.log(`Temporary smoke project: ${tempProject}`);
|
|
162
197
|
|
|
163
198
|
// Pass argv through unchanged: provider selection (--provider) and the
|
|
@@ -213,7 +248,6 @@ async function runApprove(args) {
|
|
|
213
248
|
console.log(approveUsage());
|
|
214
249
|
return 0;
|
|
215
250
|
}
|
|
216
|
-
assertProjectInitialized();
|
|
217
251
|
if (parsed.positionals.length !== 2) {
|
|
218
252
|
throw new SlideWorkflowError(
|
|
219
253
|
`Expected <slides/deck> and <command>. Run 'takt-marp approve --help' for usage.`,
|
|
@@ -242,14 +276,20 @@ export async function runCli(argv) {
|
|
|
242
276
|
}
|
|
243
277
|
|
|
244
278
|
try {
|
|
279
|
+
if (command === "init") {
|
|
280
|
+
throw new SlideWorkflowError(
|
|
281
|
+
"`init` has been removed. Use `takt-marp eject .` to copy template assets.",
|
|
282
|
+
"COMMAND_REMOVED",
|
|
283
|
+
);
|
|
284
|
+
}
|
|
245
285
|
if (!VALID_COMMANDS.includes(command)) {
|
|
246
286
|
throw new SlideWorkflowError(
|
|
247
287
|
`'${command}' is not a takt-marp command. Valid commands: ${VALID_COMMANDS.join(", ")}. Run 'takt-marp --help' for usage.`,
|
|
248
288
|
"UNKNOWN_COMMAND",
|
|
249
289
|
);
|
|
250
290
|
}
|
|
251
|
-
if (command === "
|
|
252
|
-
return await
|
|
291
|
+
if (command === "eject") {
|
|
292
|
+
return await runEject(rest);
|
|
253
293
|
}
|
|
254
294
|
if (command === "approve") {
|
|
255
295
|
return await runApprove(rest);
|
|
@@ -257,6 +297,12 @@ export async function runCli(argv) {
|
|
|
257
297
|
if (command === "smoke") {
|
|
258
298
|
return await runSmoke(rest);
|
|
259
299
|
}
|
|
300
|
+
if (Object.hasOwn(BUILD_COMMANDS, command)) {
|
|
301
|
+
return await runBuildCommand(command, rest);
|
|
302
|
+
}
|
|
303
|
+
if (command === "preview") {
|
|
304
|
+
return await runPreview(rest);
|
|
305
|
+
}
|
|
260
306
|
return await runWorkflowCommand(command, rest);
|
|
261
307
|
} catch (error) {
|
|
262
308
|
console.error(formatError(error));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export class SlideWorkflowError extends Error {
|
|
2
|
+
constructor(message, code = "SLIDE_WORKFLOW_ERROR") {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = "SlideWorkflowError";
|
|
5
|
+
this.code = code;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function formatError(error) {
|
|
10
|
+
return error instanceof SlideWorkflowError ? `${error.code}: ${error.message}` : String(error?.stack ?? error);
|
|
11
|
+
}
|