@1aboveio/skills 0.17.0 → 0.19.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.md +4 -4
- package/package.json +1 -1
- package/runtime/skills/distribution/generated/recipes.json +52 -32
- package/runtime/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +1 -1
- package/runtime/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +23 -1
- package/skills/cicd-pipeline/mergify/references/watch-contract.md +2 -2
- package/skills/cicd-pipeline/mergify/scripts/watch-pr-delivery-core.mjs +48 -4
- package/skills/data-science/airflow/SKILL.md +198 -0
- package/skills/data-science/pyspark/assets/templates/etl.py +1 -0
- package/skills/data-science/pyspark/references/etl-contract.md +3 -0
- package/skills/engineering/engineering-runtime/coherence/workflow.json +65 -15
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +1 -1
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +23 -1
- package/skills/engineering/resolve-issues/SKILL.md +1 -1
- package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +55 -11
- package/skills/engineering/resolve-issues/scripts/run-state.mjs +4 -4
- package/skills/engineering/resolve-release/SKILL.md +2 -1
- package/skills/engineering/resolve-release/agents/openai.yaml +9 -0
- package/skills/engineering/resolve-release/references/related-skills.md +1 -0
- package/skills/engineering/rush-issues/LICENSE +3 -0
- package/skills/engineering/rush-issues/SKILL.md +179 -0
- package/skills/engineering/rush-issues/agents/openai.yaml +9 -0
- package/skills/engineering/rush-issues/evals/evals.json +65 -0
- package/skills/engineering/rush-issues/references/canary.md +45 -0
- package/skills/engineering/rush-issues/references/cicd.md +37 -0
- package/skills/engineering/rush-issues/references/combine.md +51 -0
- package/skills/engineering/rush-issues/references/expire.md +55 -0
- package/skills/engineering/rush-issues/references/exploration.md +53 -0
- package/skills/engineering/rush-issues/references/implementation.md +66 -0
- package/skills/engineering/rush-issues/references/preflight.md +31 -0
- package/skills/engineering/rush-issues/references/profiling.md +78 -0
- package/skills/engineering/rush-issues/references/review.md +48 -0
- package/skills/engineering/rush-issues/references/shared-modules.md +66 -0
- package/skills/engineering/rush-issues/references/task-plan.md +110 -0
- package/skills/engineering/rush-issues/scripts/discover-models.mjs +9 -0
- package/skills/engineering/rush-issues/scripts/model-catalog.mjs +9 -0
- package/skills/engineering/rush-issues/scripts/preflight-models.mjs +466 -0
- package/skills/engineering/rush-release/LICENSE +3 -0
- package/skills/engineering/rush-release/SKILL.md +99 -0
- package/skills/engineering/rush-release/agents/openai.yaml +8 -0
- package/skills/engineering/rush-release/evals/evals.json +44 -0
- package/skills/engineering/rush-release/references/candidate.md +30 -0
- package/skills/engineering/rush-release/references/cut.md +66 -0
- package/skills/engineering/rush-release/references/preflight.md +47 -0
- package/skills/engineering/rush-release/references/publish.md +100 -0
- package/skills/engineering/rush-release/scripts/apply.mjs +185 -0
- package/skills/engineering/rush-release/scripts/green-head.mjs +231 -0
- package/skills/engineering/rush-release/scripts/plan.mjs +264 -0
- package/skills/fullstack/zod-v4/SKILL.md +1 -1
- package/skills/data-science/airflow-dag-develop/SKILL.md +0 -111
- /package/skills/data-science/{airflow-dag-develop → airflow}/LICENSE +0 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: airflow
|
|
3
|
+
description: Airflow DAG architecture and conventions. Use when designing, writing, reviewing, testing, or debugging Airflow DAGs and tasks, including TaskGroups, data intervals, timezone-aware date parameters, CLI validation, environment-based scheduling, and pytest integrity tests.
|
|
4
|
+
user-invocable: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Airflow DAG Development Patterns
|
|
8
|
+
|
|
9
|
+
## 1. Organize Data Pipelines with TaskGroups
|
|
10
|
+
|
|
11
|
+
Use `TaskGroup` to make meaningful pipeline stages visible in the Airflow graph. For data warehouse pipelines, group tasks by warehouse layer such as `stg`, `ods`, `dwd`, `dws`, and `ads`. For other pipelines, use domain-specific groups such as `features`, `exports`, `quality_checks`, or `notifications`.
|
|
12
|
+
|
|
13
|
+
Keep groups aligned with real ownership or dependency boundaries; do not create a group solely to wrap one trivial task. Express dependencies between groups so the graph communicates the pipeline's high-level flow.
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from airflow.decorators import dag
|
|
17
|
+
from airflow.utils.task_group import TaskGroup
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dag(...)
|
|
21
|
+
def customer_metrics():
|
|
22
|
+
with TaskGroup(group_id="stg") as stg:
|
|
23
|
+
load_stg_customers()
|
|
24
|
+
load_stg_orders()
|
|
25
|
+
|
|
26
|
+
with TaskGroup(group_id="dwd") as dwd:
|
|
27
|
+
build_dwd_customers()
|
|
28
|
+
build_dwd_orders()
|
|
29
|
+
|
|
30
|
+
with TaskGroup(group_id="ads") as ads:
|
|
31
|
+
build_ads_customer_metrics()
|
|
32
|
+
|
|
33
|
+
stg >> dwd >> ads
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
customer_metrics()
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 2. Use Timezone-Aware Data Intervals
|
|
40
|
+
|
|
41
|
+
Prefer Airflow's `data_interval_start` and `data_interval_end` as task date-range inputs. They are timezone-aware logical boundaries and behave correctly for scheduled runs, catchup, and daylight-saving transitions. Treat `data_interval_end` as an exclusive boundary.
|
|
42
|
+
|
|
43
|
+
Prepare one shared set of templated date variables for the whole DAG, converting the interval boundaries to the DAG's business timezone. Pass those variables to every task that reads or writes partitioned data. Keep the conversion in Jinja so it happens for each DAG run, not while the scheduler parses the DAG file.
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import pendulum
|
|
47
|
+
from airflow.decorators import dag, task
|
|
48
|
+
from airflow.utils.task_group import TaskGroup
|
|
49
|
+
|
|
50
|
+
LOCAL_TIMEZONE = "Asia/Shanghai"
|
|
51
|
+
|
|
52
|
+
# These values are rendered separately for every DAG run. The end is exclusive.
|
|
53
|
+
DATE_RANGE = {
|
|
54
|
+
"start_date": (
|
|
55
|
+
f"{{{{ data_interval_start.in_timezone('{LOCAL_TIMEZONE}') | ds }}}}"
|
|
56
|
+
),
|
|
57
|
+
"end_date": (
|
|
58
|
+
f"{{{{ data_interval_end.in_timezone('{LOCAL_TIMEZONE}') | ds }}}}"
|
|
59
|
+
),
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dag(
|
|
64
|
+
schedule="0 2 * * *",
|
|
65
|
+
start_date=pendulum.datetime(2024, 1, 1, tz=LOCAL_TIMEZONE),
|
|
66
|
+
catchup=True,
|
|
67
|
+
)
|
|
68
|
+
def daily_warehouse():
|
|
69
|
+
@task
|
|
70
|
+
def load_partition(start_date: str, end_date: str) -> None:
|
|
71
|
+
# Read records in the half-open range [start_date, end_date).
|
|
72
|
+
...
|
|
73
|
+
|
|
74
|
+
with TaskGroup(group_id="stg"):
|
|
75
|
+
load_partition(**DATE_RANGE)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
daily_warehouse()
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Use timestamps instead of dates when a task needs sub-day precision:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
INTERVAL_RANGE = {
|
|
85
|
+
"interval_start": "{{ data_interval_start.in_timezone('Asia/Shanghai').to_iso8601_string() }}",
|
|
86
|
+
"interval_end": "{{ data_interval_end.in_timezone('Asia/Shanghai').to_iso8601_string() }}",
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 3. Operations: Wait for DAG Auto-Reload
|
|
91
|
+
|
|
92
|
+
Airflow periodically scans the DAG directory and automatically reloads changed DAG files. The refresh cadence depends on the deployment's scheduler and DAG-processing configuration, and commonly takes a few minutes.
|
|
93
|
+
|
|
94
|
+
After updating a DAG file, do not restart the Airflow services by default. Watch for the DAG to refresh in the Airflow UI or CLI after the configured scan interval. Investigate import errors or deployment synchronization only if the update does not appear after a reasonable interval.
|
|
95
|
+
|
|
96
|
+
## 4. Quick DAG Validation with Airflow CLI
|
|
97
|
+
|
|
98
|
+
Use these commands for fast feedback during development:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# List import errors (fastest check - catches syntax and import issues)
|
|
102
|
+
airflow dags list-import-errors
|
|
103
|
+
|
|
104
|
+
# Full lint check (comprehensive - catches best practice violations)
|
|
105
|
+
airflow dags lint
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**When to use:**
|
|
109
|
+
- `list-import-errors`: During active development for quick syntax/import validation
|
|
110
|
+
- `lint`: Before commits to catch style and best practice issues
|
|
111
|
+
|
|
112
|
+
## 5. Environment-Based Schedule Override
|
|
113
|
+
|
|
114
|
+
Disable schedules in local development to prevent accidental runs:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
import os
|
|
118
|
+
from datetime import datetime
|
|
119
|
+
from airflow import DAG
|
|
120
|
+
|
|
121
|
+
def get_schedule(production_schedule: str) -> str | None:
|
|
122
|
+
"""Return None for local dev, actual schedule for deployed environments.
|
|
123
|
+
|
|
124
|
+
Set AIRFLOW_ENV=local in .env for local development.
|
|
125
|
+
Cloud Run deployments set AIRFLOW_ENV=dev|staging|prod.
|
|
126
|
+
"""
|
|
127
|
+
env = os.getenv("AIRFLOW_ENV", "local")
|
|
128
|
+
if env == "local":
|
|
129
|
+
return None
|
|
130
|
+
return production_schedule
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Usage in DAG:**
|
|
134
|
+
```python
|
|
135
|
+
with DAG(
|
|
136
|
+
dag_id="my_dag",
|
|
137
|
+
schedule=get_schedule("0 4 * * *"), # Daily 4 AM in prod, None locally
|
|
138
|
+
start_date=datetime(2024, 1, 1),
|
|
139
|
+
catchup=False,
|
|
140
|
+
) as dag:
|
|
141
|
+
...
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Environment setup:**
|
|
145
|
+
- **Local:** Add `AIRFLOW_ENV=local` to `.env`
|
|
146
|
+
- **Cloud Run:** Set via cloudbuild.yaml substitutions (`_AIRFLOW_ENV: dev|staging|prod`)
|
|
147
|
+
|
|
148
|
+
## 6. Pytest DAG Integrity Tests
|
|
149
|
+
|
|
150
|
+
Standard pytest patterns for validating DAG quality:
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
# tests/test_dag_integrity.py
|
|
154
|
+
import pytest
|
|
155
|
+
from airflow.models import DagBag
|
|
156
|
+
|
|
157
|
+
@pytest.fixture(scope="session")
|
|
158
|
+
def dagbag():
|
|
159
|
+
return DagBag(dag_folder="dags/", include_examples=False)
|
|
160
|
+
|
|
161
|
+
def test_no_import_errors(dagbag):
|
|
162
|
+
"""Verify all DAGs load without import errors."""
|
|
163
|
+
assert not dagbag.import_errors, f"DAG import errors: {dagbag.import_errors}"
|
|
164
|
+
|
|
165
|
+
def test_dags_have_tags(dagbag):
|
|
166
|
+
"""Verify all DAGs have at least one tag for organization."""
|
|
167
|
+
for dag_id, dag in dagbag.dags.items():
|
|
168
|
+
assert dag.tags, f"DAG {dag_id} has no tags"
|
|
169
|
+
|
|
170
|
+
def test_dags_have_owner(dagbag):
|
|
171
|
+
"""Verify all DAGs have an owner in default_args."""
|
|
172
|
+
for dag_id, dag in dagbag.dags.items():
|
|
173
|
+
assert dag.default_args.get("owner"), f"DAG {dag_id} missing owner"
|
|
174
|
+
|
|
175
|
+
def test_no_cycles(dagbag):
|
|
176
|
+
"""Verify DAGs don't have circular dependencies."""
|
|
177
|
+
for dag_id, dag in dagbag.dags.items():
|
|
178
|
+
# DagBag already validates this, but explicit test for clarity
|
|
179
|
+
assert dag.topo_sort(), f"DAG {dag_id} has cycles"
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Run tests:**
|
|
183
|
+
```bash
|
|
184
|
+
# Run all DAG tests
|
|
185
|
+
pytest tests/test_dag_integrity.py -v
|
|
186
|
+
|
|
187
|
+
# Run specific test
|
|
188
|
+
pytest tests/test_dag_integrity.py::test_no_import_errors -v
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Quick Reference
|
|
192
|
+
|
|
193
|
+
| Task | Command |
|
|
194
|
+
|------|---------|
|
|
195
|
+
| Check import errors | `airflow dags list-import-errors` |
|
|
196
|
+
| Lint DAGs | `airflow dags lint` |
|
|
197
|
+
| Run integrity tests | `pytest tests/test_dag_integrity.py -v` |
|
|
198
|
+
| Trigger manual run | `airflow dags trigger <dag_id>` |
|
|
@@ -344,6 +344,7 @@ class Etl(ABC):
|
|
|
344
344
|
"hoodie.datasource.write.keygenerator.class": "org.apache.hudi.keygen.ComplexKeyGenerator",
|
|
345
345
|
"hoodie.datasource.write.precombine.field": self.ts,
|
|
346
346
|
"hoodie.datasource.write.operation": f"{operation}",
|
|
347
|
+
"hoodie.bulkinsert.sort.mode": "PARTITION_PATH_REPARTITION_AND_SORT",
|
|
347
348
|
"hoodie.datasource.write.reconcile.schema": True,
|
|
348
349
|
# Do not set hoodie.*.shuffle.parallelism or spark.sql.shuffle.partitions:
|
|
349
350
|
# each shuffle task becomes a tiny Hudi file.
|
|
@@ -98,6 +98,9 @@ belong before the writer in the job process.
|
|
|
98
98
|
`hoodie.bulkinsert.shuffle.parallelism`. A raised shuffle partition count
|
|
99
99
|
becomes one small file per task on the write path. Size files with
|
|
100
100
|
`HudiLayout` (default one ~128MB file per partition), not shuffle parallelism.
|
|
101
|
+
- Keep bulk inserts physically grouped and sorted by partition with
|
|
102
|
+
`hoodie.bulkinsert.sort.mode=PARTITION_PATH_REPARTITION_AND_SORT`; override it
|
|
103
|
+
through `extra_hudi_options` only when the job contract requires another layout.
|
|
101
104
|
|
|
102
105
|
### Repair small files
|
|
103
106
|
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
"e2e-test",
|
|
6
6
|
"ensure-coverage",
|
|
7
7
|
"implement-and-pr",
|
|
8
|
+
"rush-issues",
|
|
8
9
|
"resolve-issues",
|
|
10
|
+
"rush-release",
|
|
9
11
|
"resolve-release",
|
|
10
12
|
"review-pr",
|
|
11
13
|
"smoke",
|
|
@@ -44,6 +46,18 @@
|
|
|
44
46
|
}
|
|
45
47
|
],
|
|
46
48
|
"dependencyClosures": [
|
|
49
|
+
{
|
|
50
|
+
"invokedSkill": "rush-issues",
|
|
51
|
+
"members": [
|
|
52
|
+
"code-review",
|
|
53
|
+
"harness-runtime",
|
|
54
|
+
"e2e-test",
|
|
55
|
+
"rush-issues",
|
|
56
|
+
"smoke",
|
|
57
|
+
"engineering-runtime"
|
|
58
|
+
],
|
|
59
|
+
"generatedIdentities": []
|
|
60
|
+
},
|
|
47
61
|
{
|
|
48
62
|
"invokedSkill": "resolve-issues",
|
|
49
63
|
"members": [
|
|
@@ -64,6 +78,14 @@
|
|
|
64
78
|
}
|
|
65
79
|
]
|
|
66
80
|
},
|
|
81
|
+
{
|
|
82
|
+
"invokedSkill": "rush-release",
|
|
83
|
+
"members": [
|
|
84
|
+
"rush-release",
|
|
85
|
+
"engineering-runtime"
|
|
86
|
+
],
|
|
87
|
+
"generatedIdentities": []
|
|
88
|
+
},
|
|
67
89
|
{
|
|
68
90
|
"invokedSkill": "resolve-release",
|
|
69
91
|
"members": [
|
|
@@ -361,7 +383,7 @@
|
|
|
361
383
|
"id": "first-party",
|
|
362
384
|
"type": "first-party",
|
|
363
385
|
"package": "@1aboveio/skills",
|
|
364
|
-
"version": "0.
|
|
386
|
+
"version": "0.19.0"
|
|
365
387
|
},
|
|
366
388
|
"contentDigest": "eff6c7b5931bce5b2265a619bccddd371a89df6ce7bc2edc74f11d00060a71dd",
|
|
367
389
|
"digestExcludes": []
|
|
@@ -374,7 +396,7 @@
|
|
|
374
396
|
"id": "first-party",
|
|
375
397
|
"type": "first-party",
|
|
376
398
|
"package": "@1aboveio/skills",
|
|
377
|
-
"version": "0.
|
|
399
|
+
"version": "0.19.0"
|
|
378
400
|
},
|
|
379
401
|
"contentDigest": "08230dc57a53d6526692b50138038abbd80abce1a067e01c52ad6acc182caf7e",
|
|
380
402
|
"digestExcludes": []
|
|
@@ -387,7 +409,7 @@
|
|
|
387
409
|
"id": "first-party",
|
|
388
410
|
"type": "first-party",
|
|
389
411
|
"package": "@1aboveio/skills",
|
|
390
|
-
"version": "0.
|
|
412
|
+
"version": "0.19.0"
|
|
391
413
|
},
|
|
392
414
|
"contentDigest": "9eea7bfba348ddaea1b934c9a7fabdd9b101df8a146e1c93e947da4d335f1d98",
|
|
393
415
|
"digestExcludes": []
|
|
@@ -400,11 +422,24 @@
|
|
|
400
422
|
"id": "first-party",
|
|
401
423
|
"type": "first-party",
|
|
402
424
|
"package": "@1aboveio/skills",
|
|
403
|
-
"version": "0.
|
|
425
|
+
"version": "0.19.0"
|
|
404
426
|
},
|
|
405
427
|
"contentDigest": "58b0556228a9271cf9e33727a05fc08a4fdfd29512ec0936b169f0a55d60e6ef",
|
|
406
428
|
"digestExcludes": []
|
|
407
429
|
},
|
|
430
|
+
{
|
|
431
|
+
"installName": "rush-issues",
|
|
432
|
+
"ownership": "owned",
|
|
433
|
+
"sourcePath": "skills/engineering/rush-issues",
|
|
434
|
+
"expectedSource": {
|
|
435
|
+
"id": "first-party",
|
|
436
|
+
"type": "first-party",
|
|
437
|
+
"package": "@1aboveio/skills",
|
|
438
|
+
"version": "0.19.0"
|
|
439
|
+
},
|
|
440
|
+
"contentDigest": "38347c30820ba7e8b10433aeb351b7df4fa457b143e4a109293ab53fda961459",
|
|
441
|
+
"digestExcludes": []
|
|
442
|
+
},
|
|
408
443
|
{
|
|
409
444
|
"installName": "resolve-issues",
|
|
410
445
|
"ownership": "owned",
|
|
@@ -413,9 +448,22 @@
|
|
|
413
448
|
"id": "first-party",
|
|
414
449
|
"type": "first-party",
|
|
415
450
|
"package": "@1aboveio/skills",
|
|
416
|
-
"version": "0.
|
|
451
|
+
"version": "0.19.0"
|
|
452
|
+
},
|
|
453
|
+
"contentDigest": "d32add939c8c673e3bb096dfc95a5aadfa31115c3a854b3a4e0eb3fed1b49794",
|
|
454
|
+
"digestExcludes": []
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
"installName": "rush-release",
|
|
458
|
+
"ownership": "owned",
|
|
459
|
+
"sourcePath": "skills/engineering/rush-release",
|
|
460
|
+
"expectedSource": {
|
|
461
|
+
"id": "first-party",
|
|
462
|
+
"type": "first-party",
|
|
463
|
+
"package": "@1aboveio/skills",
|
|
464
|
+
"version": "0.19.0"
|
|
417
465
|
},
|
|
418
|
-
"contentDigest": "
|
|
466
|
+
"contentDigest": "125318612fe3fd70354ba5393a7019b3e6db5acc14a0d3f653a31f6b06a2e267",
|
|
419
467
|
"digestExcludes": []
|
|
420
468
|
},
|
|
421
469
|
{
|
|
@@ -426,9 +474,9 @@
|
|
|
426
474
|
"id": "first-party",
|
|
427
475
|
"type": "first-party",
|
|
428
476
|
"package": "@1aboveio/skills",
|
|
429
|
-
"version": "0.
|
|
477
|
+
"version": "0.19.0"
|
|
430
478
|
},
|
|
431
|
-
"contentDigest": "
|
|
479
|
+
"contentDigest": "ffba0c83491676794c74721f4c6dbae430f5bc186e5a55f0764e29eaeb13829b",
|
|
432
480
|
"digestExcludes": []
|
|
433
481
|
},
|
|
434
482
|
{
|
|
@@ -439,7 +487,7 @@
|
|
|
439
487
|
"id": "first-party",
|
|
440
488
|
"type": "first-party",
|
|
441
489
|
"package": "@1aboveio/skills",
|
|
442
|
-
"version": "0.
|
|
490
|
+
"version": "0.19.0"
|
|
443
491
|
},
|
|
444
492
|
"contentDigest": "f048fd00c69f2dc666fc7a3096cfeee6dfba73933bfb69602f3f0e26159798cc",
|
|
445
493
|
"digestExcludes": []
|
|
@@ -452,7 +500,7 @@
|
|
|
452
500
|
"id": "first-party",
|
|
453
501
|
"type": "first-party",
|
|
454
502
|
"package": "@1aboveio/skills",
|
|
455
|
-
"version": "0.
|
|
503
|
+
"version": "0.19.0"
|
|
456
504
|
},
|
|
457
505
|
"contentDigest": "90a7c4e1ad6da1e632ea2c5259e4967ffebb84353adccbca8dfc5d6bc50b60c1",
|
|
458
506
|
"digestExcludes": []
|
|
@@ -465,15 +513,15 @@
|
|
|
465
513
|
"id": "first-party",
|
|
466
514
|
"type": "first-party",
|
|
467
515
|
"package": "@1aboveio/skills",
|
|
468
|
-
"version": "0.
|
|
516
|
+
"version": "0.19.0"
|
|
469
517
|
},
|
|
470
|
-
"contentDigest": "
|
|
518
|
+
"contentDigest": "16dcd5bc2b40c8ae7cf6bc41eadd943264b03e70162c3da85624f11a2112bf56",
|
|
471
519
|
"digestExcludes": [
|
|
472
520
|
"coherence/workflow.json"
|
|
473
521
|
]
|
|
474
522
|
}
|
|
475
523
|
],
|
|
476
|
-
"releaseIdentity": "
|
|
524
|
+
"releaseIdentity": "6f89ee339ca1319fbd167658b1dbb66a1357b482463ba829bf22bf7b0c7c28a3",
|
|
477
525
|
"lifecycleAuthority": "native-skills-cli",
|
|
478
526
|
"repairRecipe": {
|
|
479
527
|
"id": "engineering-workflow-dependency-first",
|
|
@@ -531,14 +579,16 @@
|
|
|
531
579
|
"sourceId": "first-party",
|
|
532
580
|
"sourceType": "first-party",
|
|
533
581
|
"package": "@1aboveio/skills",
|
|
534
|
-
"version": "0.
|
|
582
|
+
"version": "0.19.0",
|
|
535
583
|
"installPath": null,
|
|
536
584
|
"members": [
|
|
537
585
|
"harness-runtime",
|
|
538
586
|
"e2e-test",
|
|
539
587
|
"ensure-coverage",
|
|
540
588
|
"implement-and-pr",
|
|
589
|
+
"rush-issues",
|
|
541
590
|
"resolve-issues",
|
|
591
|
+
"rush-release",
|
|
542
592
|
"resolve-release",
|
|
543
593
|
"review-pr",
|
|
544
594
|
"smoke",
|
|
@@ -547,7 +597,7 @@
|
|
|
547
597
|
"commands": [
|
|
548
598
|
{
|
|
549
599
|
"transport": "npm",
|
|
550
|
-
"command": "npx @1aboveio/skills@0.
|
|
600
|
+
"command": "npx @1aboveio/skills@0.19.0 install --group engineering-workflow --yes"
|
|
551
601
|
}
|
|
552
602
|
],
|
|
553
603
|
"onFailure": {
|
|
@@ -288,7 +288,7 @@ function validateManifest(manifest) {
|
|
|
288
288
|
add('digest-algorithm-invalid', 'engineering-runtime', 'The coherence digest algorithm is missing or unsupported.');
|
|
289
289
|
}
|
|
290
290
|
if (JSON.stringify(manifest.ownedMembers) !== JSON.stringify(WORKFLOW_OWNED_MEMBERS)) {
|
|
291
|
-
add('owned-census-invalid', 'engineering-runtime', 'The exact
|
|
291
|
+
add('owned-census-invalid', 'engineering-runtime', 'The exact ten-member Workflow ownership census is missing or malformed.');
|
|
292
292
|
}
|
|
293
293
|
if (JSON.stringify(manifest.dependencies) !== JSON.stringify([
|
|
294
294
|
{ groupId: 'matt-pocock-toolkit', members: MATT_DEPENDENCY_MEMBERS },
|
|
@@ -10,7 +10,9 @@ export const WORKFLOW_OWNED_MEMBERS = deepFreeze([
|
|
|
10
10
|
'e2e-test',
|
|
11
11
|
'ensure-coverage',
|
|
12
12
|
'implement-and-pr',
|
|
13
|
+
'rush-issues',
|
|
13
14
|
'resolve-issues',
|
|
15
|
+
'rush-release',
|
|
14
16
|
'resolve-release',
|
|
15
17
|
'review-pr',
|
|
16
18
|
'smoke',
|
|
@@ -52,6 +54,18 @@ export const WORKFLOW_TRUSTED_INVOCATION_POLICIES = deepFreeze([
|
|
|
52
54
|
]);
|
|
53
55
|
|
|
54
56
|
export const WORKFLOW_TRUSTED_DEPENDENCY_CLOSURES = deepFreeze([
|
|
57
|
+
{
|
|
58
|
+
invokedSkill: 'rush-issues',
|
|
59
|
+
members: [
|
|
60
|
+
'code-review',
|
|
61
|
+
'harness-runtime',
|
|
62
|
+
'e2e-test',
|
|
63
|
+
'rush-issues',
|
|
64
|
+
'smoke',
|
|
65
|
+
'engineering-runtime',
|
|
66
|
+
],
|
|
67
|
+
generatedIdentities: [],
|
|
68
|
+
},
|
|
55
69
|
{
|
|
56
70
|
invokedSkill: 'resolve-issues',
|
|
57
71
|
members: [
|
|
@@ -69,6 +83,14 @@ export const WORKFLOW_TRUSTED_DEPENDENCY_CLOSURES = deepFreeze([
|
|
|
69
83
|
{ member: 'resolve-issues', path: 'generated/workflow-repair-policy.json' },
|
|
70
84
|
],
|
|
71
85
|
},
|
|
86
|
+
{
|
|
87
|
+
invokedSkill: 'rush-release',
|
|
88
|
+
members: [
|
|
89
|
+
'rush-release',
|
|
90
|
+
'engineering-runtime',
|
|
91
|
+
],
|
|
92
|
+
generatedIdentities: [],
|
|
93
|
+
},
|
|
72
94
|
{
|
|
73
95
|
invokedSkill: 'resolve-release',
|
|
74
96
|
members: [
|
|
@@ -97,7 +119,7 @@ export const WORKFLOW_TRUSTED_SOURCES = deepFreeze({
|
|
|
97
119
|
id: 'first-party',
|
|
98
120
|
type: 'first-party',
|
|
99
121
|
package: '@1aboveio/skills',
|
|
100
|
-
version: '0.
|
|
122
|
+
version: '0.19.0',
|
|
101
123
|
},
|
|
102
124
|
matt: {
|
|
103
125
|
id: 'matt-pocock',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: resolve-issues
|
|
3
|
-
description: "Slash-
|
|
3
|
+
description: "Slash/explicit-only (/resolve-issues). Drive GitHub issues (single or epic) to merge-ready PRs: implement → e2e → independent review on a different model ∥ CI → fix, looped until PASS; epics assemble one PR per shippable component. Orchestrates implement-and-pr, e2e-test, ensure-coverage, review-pr, smoke. Do not auto-select — only on explicit user/orchestrator invoke. NOT one implement+PR alone, review alone, rush-issues, or release work (rush-release or resolve-release)."
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
dependencies:
|
|
6
6
|
- implement-and-pr
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
"id": "first-party",
|
|
238
238
|
"type": "first-party",
|
|
239
239
|
"package": "@1aboveio/skills",
|
|
240
|
-
"version": "0.
|
|
240
|
+
"version": "0.19.0"
|
|
241
241
|
}
|
|
242
242
|
},
|
|
243
243
|
{
|
|
@@ -248,7 +248,7 @@
|
|
|
248
248
|
"id": "first-party",
|
|
249
249
|
"type": "first-party",
|
|
250
250
|
"package": "@1aboveio/skills",
|
|
251
|
-
"version": "0.
|
|
251
|
+
"version": "0.19.0"
|
|
252
252
|
}
|
|
253
253
|
},
|
|
254
254
|
{
|
|
@@ -259,7 +259,7 @@
|
|
|
259
259
|
"id": "first-party",
|
|
260
260
|
"type": "first-party",
|
|
261
261
|
"package": "@1aboveio/skills",
|
|
262
|
-
"version": "0.
|
|
262
|
+
"version": "0.19.0"
|
|
263
263
|
}
|
|
264
264
|
},
|
|
265
265
|
{
|
|
@@ -270,7 +270,18 @@
|
|
|
270
270
|
"id": "first-party",
|
|
271
271
|
"type": "first-party",
|
|
272
272
|
"package": "@1aboveio/skills",
|
|
273
|
-
"version": "0.
|
|
273
|
+
"version": "0.19.0"
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"installName": "rush-issues",
|
|
278
|
+
"ownership": "owned",
|
|
279
|
+
"sourcePath": "skills/engineering/rush-issues",
|
|
280
|
+
"expectedSource": {
|
|
281
|
+
"id": "first-party",
|
|
282
|
+
"type": "first-party",
|
|
283
|
+
"package": "@1aboveio/skills",
|
|
284
|
+
"version": "0.19.0"
|
|
274
285
|
}
|
|
275
286
|
},
|
|
276
287
|
{
|
|
@@ -281,7 +292,18 @@
|
|
|
281
292
|
"id": "first-party",
|
|
282
293
|
"type": "first-party",
|
|
283
294
|
"package": "@1aboveio/skills",
|
|
284
|
-
"version": "0.
|
|
295
|
+
"version": "0.19.0"
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
"installName": "rush-release",
|
|
300
|
+
"ownership": "owned",
|
|
301
|
+
"sourcePath": "skills/engineering/rush-release",
|
|
302
|
+
"expectedSource": {
|
|
303
|
+
"id": "first-party",
|
|
304
|
+
"type": "first-party",
|
|
305
|
+
"package": "@1aboveio/skills",
|
|
306
|
+
"version": "0.19.0"
|
|
285
307
|
}
|
|
286
308
|
},
|
|
287
309
|
{
|
|
@@ -292,7 +314,7 @@
|
|
|
292
314
|
"id": "first-party",
|
|
293
315
|
"type": "first-party",
|
|
294
316
|
"package": "@1aboveio/skills",
|
|
295
|
-
"version": "0.
|
|
317
|
+
"version": "0.19.0"
|
|
296
318
|
}
|
|
297
319
|
},
|
|
298
320
|
{
|
|
@@ -303,7 +325,7 @@
|
|
|
303
325
|
"id": "first-party",
|
|
304
326
|
"type": "first-party",
|
|
305
327
|
"package": "@1aboveio/skills",
|
|
306
|
-
"version": "0.
|
|
328
|
+
"version": "0.19.0"
|
|
307
329
|
}
|
|
308
330
|
},
|
|
309
331
|
{
|
|
@@ -314,7 +336,7 @@
|
|
|
314
336
|
"id": "first-party",
|
|
315
337
|
"type": "first-party",
|
|
316
338
|
"package": "@1aboveio/skills",
|
|
317
|
-
"version": "0.
|
|
339
|
+
"version": "0.19.0"
|
|
318
340
|
}
|
|
319
341
|
},
|
|
320
342
|
{
|
|
@@ -325,11 +347,23 @@
|
|
|
325
347
|
"id": "first-party",
|
|
326
348
|
"type": "first-party",
|
|
327
349
|
"package": "@1aboveio/skills",
|
|
328
|
-
"version": "0.
|
|
350
|
+
"version": "0.19.0"
|
|
329
351
|
}
|
|
330
352
|
}
|
|
331
353
|
],
|
|
332
354
|
"dependencyClosures": [
|
|
355
|
+
{
|
|
356
|
+
"invokedSkill": "rush-issues",
|
|
357
|
+
"members": [
|
|
358
|
+
"code-review",
|
|
359
|
+
"harness-runtime",
|
|
360
|
+
"e2e-test",
|
|
361
|
+
"rush-issues",
|
|
362
|
+
"smoke",
|
|
363
|
+
"engineering-runtime"
|
|
364
|
+
],
|
|
365
|
+
"generatedIdentities": []
|
|
366
|
+
},
|
|
333
367
|
{
|
|
334
368
|
"invokedSkill": "resolve-issues",
|
|
335
369
|
"members": [
|
|
@@ -350,6 +384,14 @@
|
|
|
350
384
|
}
|
|
351
385
|
]
|
|
352
386
|
},
|
|
387
|
+
{
|
|
388
|
+
"invokedSkill": "rush-release",
|
|
389
|
+
"members": [
|
|
390
|
+
"rush-release",
|
|
391
|
+
"engineering-runtime"
|
|
392
|
+
],
|
|
393
|
+
"generatedIdentities": []
|
|
394
|
+
},
|
|
353
395
|
{
|
|
354
396
|
"invokedSkill": "resolve-release",
|
|
355
397
|
"members": [
|
|
@@ -426,14 +468,16 @@
|
|
|
426
468
|
"sourceId": "first-party",
|
|
427
469
|
"sourceType": "first-party",
|
|
428
470
|
"package": "@1aboveio/skills",
|
|
429
|
-
"version": "0.
|
|
471
|
+
"version": "0.19.0",
|
|
430
472
|
"installPath": null,
|
|
431
473
|
"members": [
|
|
432
474
|
"harness-runtime",
|
|
433
475
|
"e2e-test",
|
|
434
476
|
"ensure-coverage",
|
|
435
477
|
"implement-and-pr",
|
|
478
|
+
"rush-issues",
|
|
436
479
|
"resolve-issues",
|
|
480
|
+
"rush-release",
|
|
437
481
|
"resolve-release",
|
|
438
482
|
"review-pr",
|
|
439
483
|
"smoke",
|
|
@@ -442,7 +486,7 @@
|
|
|
442
486
|
"commands": [
|
|
443
487
|
{
|
|
444
488
|
"transport": "npm",
|
|
445
|
-
"command": "npx @1aboveio/skills@0.
|
|
489
|
+
"command": "npx @1aboveio/skills@0.19.0 install --group engineering-workflow --yes"
|
|
446
490
|
}
|
|
447
491
|
],
|
|
448
492
|
"onFailure": {
|
|
@@ -3412,7 +3412,7 @@ export const WORKFLOW_PREFLIGHT_COMMANDS = Object.freeze([
|
|
|
3412
3412
|
|
|
3413
3413
|
const WORKFLOW_VERIFIER_URL = new URL('../../engineering-runtime/scripts/workflow-coherence.mjs', import.meta.url)
|
|
3414
3414
|
const WORKFLOW_FALLBACK_POLICY_URL = new URL('../generated/workflow-repair-policy.json', import.meta.url)
|
|
3415
|
-
export const WORKFLOW_TRUSTED_FALLBACK_POLICY_SHA256 = '
|
|
3415
|
+
export const WORKFLOW_TRUSTED_FALLBACK_POLICY_SHA256 = '27d1fb2d0bdf9ca37933dff2f0e1863d95f9f147baecbbce9dd3553a4c71a915'
|
|
3416
3416
|
const WORKFLOW_REPAIR_RECIPE_REFERENCE = Object.freeze({
|
|
3417
3417
|
id: 'engineering-workflow-dependency-first',
|
|
3418
3418
|
generatedFrom: 'skills/distribution/generated/recipes.json',
|
|
@@ -3461,10 +3461,10 @@ const WORKFLOW_MATT_MEMBERS = Object.freeze([
|
|
|
3461
3461
|
'prototype', 'research', 'resolving-merge-conflicts', 'setup-matt-pocock-skills', 'tdd',
|
|
3462
3462
|
'to-spec', 'to-tickets', 'triage', 'wayfinder',
|
|
3463
3463
|
])
|
|
3464
|
-
// Dependency first, then the
|
|
3464
|
+
// Dependency first, then the ten owned members, in the census order the generator emits.
|
|
3465
3465
|
const WORKFLOW_FIRST_PARTY_MEMBERS = Object.freeze([
|
|
3466
|
-
'harness-runtime', 'e2e-test', 'ensure-coverage', 'implement-and-pr', 'resolve-issues',
|
|
3467
|
-
'resolve-release', 'review-pr', 'smoke', 'engineering-runtime',
|
|
3466
|
+
'harness-runtime', 'e2e-test', 'ensure-coverage', 'implement-and-pr', 'rush-issues', 'resolve-issues',
|
|
3467
|
+
'rush-release', 'resolve-release', 'review-pr', 'smoke', 'engineering-runtime',
|
|
3468
3468
|
])
|
|
3469
3469
|
const WORKFLOW_RECIPE_FIELDS = Object.freeze(['id', 'generatedFrom', 'groupId', 'lifecycle', 'renderTarget', 'stopOnFailure', 'steps'])
|
|
3470
3470
|
const WORKFLOW_COMMAND_FIELDS = Object.freeze(['transport', 'command'])
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: resolve-release
|
|
3
|
-
description: "Release-lane orchestrator, from merge authorization to verified-in-production: assemble PRs into a release branch, cut version + CHANGELOG, promotion PR, deploy a candidate at 0% traffic, validate it, shift traffic, verify the live revision, tag and publish notes (or delete the candidate / roll back). Input is resolve-issues' handoff. NOT for driving issues to PRs (resolve-issues), pipeline debugging (cloud-build/cloud-deploy/cloud-debug), or broken production (app-debug)."
|
|
3
|
+
description: "Slash/explicit-only (/resolve-release). Release-lane orchestrator, from merge authorization to verified-in-production: assemble PRs into a release branch, cut version + CHANGELOG, promotion PR, deploy a candidate at 0% traffic, validate it, shift traffic, verify the live revision, tag and publish notes (or delete the candidate / roll back). Do not auto-select. Input is resolve-issues' handoff. NOT for driving issues to PRs (resolve-issues), pipeline debugging (cloud-build/cloud-deploy/cloud-debug), or broken production (app-debug)."
|
|
4
|
+
disable-model-invocation: true
|
|
4
5
|
dependencies:
|
|
5
6
|
- review-pr
|
|
6
7
|
- e2e-test
|