ultimate-pi 0.19.0 → 0.20.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/.agents/skills/web-retrieval/SKILL.md +163 -0
- package/.agents/skills/wiki-autoresearch/SKILL.md +6 -6
- package/.pi/SYSTEM.md +30 -12
- package/.pi/agents/harness/planning/implementation-researcher.md +1 -1
- package/.pi/agents/harness/planning/stack-researcher.md +5 -1
- package/.pi/agents/harness/running/executor.md +42 -1
- package/.pi/agents/harness/web-retrieval/web-answerer.md +35 -0
- package/.pi/agents/harness/web-retrieval/web-criteria-verifier.md +28 -0
- package/.pi/agents/harness/web-retrieval/web-gap-analyzer.md +31 -0
- package/.pi/agents/harness/web-retrieval/web-query-expander-fast.md +34 -0
- package/.pi/agents/harness/web-retrieval/web-query-expander.md +60 -0
- package/.pi/agents/harness/web-retrieval/web-summarizer.md +18 -0
- package/.pi/extensions/harness-anchored-edit.ts +141 -0
- package/.pi/extensions/harness-web-guard.ts +2 -1
- package/.pi/extensions/harness-web-tools.ts +689 -51
- package/.pi/harness/agents.manifest.json +30 -6
- package/.pi/harness/agents.policy.yaml +37 -4
- package/.pi/harness/docs/adrs/0050-agentic-web-retrieval-stack.md +46 -0
- package/.pi/harness/docs/adrs/0051-hash-anchored-executor-edits.md +41 -0
- package/.pi/harness/docs/adrs/README.md +2 -0
- package/.pi/harness/docs/harness-web-search.md +97 -0
- package/.pi/harness/docs/practice-map.md +11 -0
- package/.pi/harness/env.harness.template +9 -1
- package/.pi/harness/examples/web-heuristic-angles.project.yaml +22 -0
- package/.pi/harness/web-heuristic-angles.json +278 -0
- package/.pi/harness/web-heuristic-angles.yaml +182 -0
- package/.pi/lib/agents-policy.d.mts +4 -0
- package/.pi/lib/agents-policy.mjs +49 -1
- package/.pi/lib/agents-policy.ts +1 -0
- package/.pi/lib/harness-anchored-edit/.hash_anchors +1721 -0
- package/.pi/lib/harness-anchored-edit/anchor-state.ts +320 -0
- package/.pi/lib/harness-anchored-edit/apply-anchored-edits.ts +161 -0
- package/.pi/lib/harness-anchored-edit/edit-executor.ts +146 -0
- package/.pi/lib/harness-anchored-edit/index.ts +9 -0
- package/.pi/lib/harness-anchored-edit/line-protocol.ts +38 -0
- package/.pi/lib/harness-anchored-edit/settings.ts +1 -0
- package/.pi/lib/harness-anchored-edit/task-id.ts +8 -0
- package/.pi/lib/harness-anchored-edit/types.ts +19 -0
- package/.pi/lib/harness-lens/clients/anchored-edit-autopatch.ts +158 -0
- package/.pi/lib/harness-lens/index.ts +24 -7
- package/.pi/lib/harness-subagent-auth.ts +39 -9
- package/.pi/lib/harness-subagents-bridge.ts +24 -1
- package/.pi/lib/harness-web/artifacts.ts +200 -0
- package/.pi/lib/harness-web/cache.ts +369 -0
- package/.pi/lib/harness-web/run-cli.ts +42 -2
- package/.pi/prompts/harness-plan.md +1 -0
- package/.pi/prompts/harness-setup.md +3 -1
- package/.pi/prompts/harness-steer.md +1 -1
- package/.pi/scripts/gen-web-heuristic-angles-json.mjs +24 -0
- package/.pi/scripts/harness-anchored-edit-smoke.mjs +45 -0
- package/.pi/scripts/harness-cli-verify.sh +5 -0
- package/.pi/scripts/harness-verify.mjs +145 -0
- package/.pi/scripts/harness-web-policy-guard.mjs +1 -1
- package/.pi/scripts/harness-web.py +218 -15
- package/.pi/scripts/harness_web/deep_search.py +55 -0
- package/.pi/scripts/harness_web/evidence_bundle.py +47 -0
- package/.pi/scripts/harness_web/find_similar.py +88 -0
- package/.pi/scripts/harness_web/heuristic_angles_shipped.py +85 -0
- package/.pi/scripts/harness_web/heuristic_config.py +251 -0
- package/.pi/scripts/harness_web/highlights.py +47 -0
- package/.pi/scripts/harness_web/multi_search.py +59 -0
- package/.pi/scripts/harness_web/output.py +24 -0
- package/.pi/scripts/harness_web/query_angles.py +116 -0
- package/.pi/scripts/harness_web/rank.py +163 -0
- package/.pi/scripts/harness_web/scrape.py +30 -0
- package/.pi/scripts/run-tests.mjs +64 -0
- package/.pi/scripts/tests/test_harness_web_heuristic_config.py +132 -0
- package/.pi/scripts/tests/test_harness_web_query_angles.py +45 -0
- package/.pi/scripts/tests/test_harness_web_rank.py +56 -0
- package/AGENTS.md +2 -2
- package/CHANGELOG.md +12 -0
- package/THIRD_PARTY_NOTICES.md +7 -0
- package/package.json +7 -4
- package/vendor/pi-subagents/src/agents.ts +5 -0
- package/vendor/pi-subagents/src/subagents.ts +22 -3
- package/.agents/skills/scrapling-web/SKILL.md +0 -98
- package/.pi/extensions/00-posthog-network-bootstrap.ts +0 -11
- package/.pi/scripts/harness_web/__pycache__/__init__.cpython-314.pyc +0 -0
- package/.pi/scripts/harness_web/__pycache__/config.cpython-314.pyc +0 -0
- package/.pi/scripts/harness_web/__pycache__/output.cpython-314.pyc +0 -0
- package/.pi/scripts/harness_web/__pycache__/scrape.cpython-314.pyc +0 -0
- package/.pi/scripts/harness_web/__pycache__/search.cpython-314.pyc +0 -0
- package/.pi/scripts/harness_web/__pycache__/search_ddg.cpython-314.pyc +0 -0
- package/.pi/scripts/harness_web/__pycache__/search_searxng.cpython-314.pyc +0 -0
- package/.pi/scripts/release.sh +0 -338
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: scrapling-web
|
|
3
|
-
description: |
|
|
4
|
-
Harness web search and scrape via pi tools web_search and web_fetch (harness-web.py).
|
|
5
|
-
Use for any non-API web task: search, scrape URLs, map site links, bulk research fetches.
|
|
6
|
-
Replaces Firecrawl in ultimate-pi harness agents. Triggers on: search the web,
|
|
7
|
-
scrape URL, fetch page, research online, web_search, web_fetch, .web/ artifacts.
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# scrapling-web (harness-web)
|
|
11
|
-
|
|
12
|
-
Local web layer for harness agents — **no API keys** for default search/scrape.
|
|
13
|
-
Pi registers **`web_search`** and **`web_fetch`** (wrap `harness-web.py` with Scrapling bootstrap).
|
|
14
|
-
Optional **self-hosted SearXNG** — see `/harness-setup` Step 4.0b.
|
|
15
|
-
|
|
16
|
-
## Agent tools (preferred)
|
|
17
|
-
|
|
18
|
-
| Task | Tool |
|
|
19
|
-
|------|------|
|
|
20
|
-
| Search (SERP) | `web_search` with `query` |
|
|
21
|
-
| Search + multi-scrape | `web_search` with `bulk: true` |
|
|
22
|
-
| Scrape URL | `web_fetch` with `url` (default mode `scrape`) |
|
|
23
|
-
| Map same-host links | `web_fetch` with `mode: map` |
|
|
24
|
-
| Static / simple page | `web_fetch` with `fast: true` |
|
|
25
|
-
|
|
26
|
-
**Never before search/fetch:** resolve `UP_PKG`, `ls harness-web.py`, `python3 -c "import scrapling"`, or Firecrawl/curl/wget/scrapling CLI for SERP or page fetch.
|
|
27
|
-
|
|
28
|
-
Full JSON/markdown lives under **`.web/`** (gitignored). Use `read` on `output` paths after tool calls.
|
|
29
|
-
|
|
30
|
-
## Install (once per machine — setup/humans only)
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
command -v uv &>/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
34
|
-
uv tool install "scrapling[fetchers]"
|
|
35
|
-
scrapling install # browser binaries for default stealth scrape
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Verify: `bash "$UP_PKG/.pi/scripts/harness-cli-verify.sh"`
|
|
39
|
-
Config diagnostics: `python3 "$UP_PKG/.pi/scripts/harness-web.py" status` (JSON; setup only)
|
|
40
|
-
|
|
41
|
-
## Bash fallback (if pi tools unavailable)
|
|
42
|
-
|
|
43
|
-
| Task | Command |
|
|
44
|
-
|------|---------|
|
|
45
|
-
| Search | `python3 "$UP_PKG/.pi/scripts/harness-web.py" search "query" -o .web/search.json --limit 5` |
|
|
46
|
-
| Scrape | `python3 "$UP_PKG/.pi/scripts/harness-web.py" scrape "<url>" -o .web/page.md` |
|
|
47
|
-
| Fast/static | add `--fast` |
|
|
48
|
-
| Map | `python3 "$UP_PKG/.pi/scripts/harness-web.py" map "<url>" -o .web/map.json` |
|
|
49
|
-
| Bulk | `python3 "$UP_PKG/.pi/scripts/harness-web.py" bulk-scrape "query" -o .web/bulk/` |
|
|
50
|
-
|
|
51
|
-
## Search JSON shape (Firecrawl-compatible)
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
jq -r '.data.web[].url' .web/search.json
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
Each entry: `url`, `title`, `description`.
|
|
58
|
-
|
|
59
|
-
## Fetch modes
|
|
60
|
-
|
|
61
|
-
| Mode | When |
|
|
62
|
-
|------|------|
|
|
63
|
-
| **stealth** (default) | Arbitrary URLs, JS-heavy sites |
|
|
64
|
-
| **fast** (`fast: true` / `--fast`) | Static docs, example.com, localhost |
|
|
65
|
-
| **auto** (`HARNESS_WEB_FETCH_MODE=auto`) | fast for known-static hosts, else stealth |
|
|
66
|
-
|
|
67
|
-
| Search backend | Behavior |
|
|
68
|
-
|--------------|----------|
|
|
69
|
-
| `ddg_html` (default) | DuckDuckGo HTML SERP |
|
|
70
|
-
| `searxng` | JSON at `HARNESS_WEB_SEARXNG_URL` — bootstrap via `harness-searxng-bootstrap.mjs` |
|
|
71
|
-
|
|
72
|
-
## Environment
|
|
73
|
-
|
|
74
|
-
| Variable | Default | Purpose |
|
|
75
|
-
|----------|---------|---------|
|
|
76
|
-
| `HARNESS_WEB_FETCH_MODE` | `stealth` | `stealth` \| `fast` \| `auto` |
|
|
77
|
-
| `HARNESS_WEB_SEARCH_ENGINE` | `ddg_html` | `ddg_html` \| `searxng` |
|
|
78
|
-
| `HARNESS_WEB_SEARXNG_URL` | (unset) | Required when `SEARCH_ENGINE=searxng` |
|
|
79
|
-
|
|
80
|
-
## Escalation
|
|
81
|
-
|
|
82
|
-
1. `web_search` / `web_fetch`
|
|
83
|
-
2. `web_fetch` with `fast: true` for static hosts
|
|
84
|
-
3. `web_fetch` with `mode: map` then targeted fetches
|
|
85
|
-
4. Site-specific Scrapling only when tools are insufficient (not for routine SERP/fetch)
|
|
86
|
-
|
|
87
|
-
## Gaps vs Firecrawl
|
|
88
|
-
|
|
89
|
-
| Firecrawl | Harness path |
|
|
90
|
-
|-----------|----------------|
|
|
91
|
-
| `interact` | gstack browse or manual browser |
|
|
92
|
-
| `agent` | Agent reasoning + graphify |
|
|
93
|
-
| `parse` (PDF) | pypdf, markitdown |
|
|
94
|
-
| `crawl` | `web_search` bulk or map + multiple `web_fetch` |
|
|
95
|
-
|
|
96
|
-
## Ethics
|
|
97
|
-
|
|
98
|
-
Respect site terms and rate limits. SERP scraping is for dev research, not high-volume harvesting.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Load before other extensions: IPv4-first fetch for *.posthog.com (@posthog/pi uses global fetch).
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { installPostHogFetchPatch } from "../lib/posthog-client.js";
|
|
6
|
-
|
|
7
|
-
installPostHogFetchPatch();
|
|
8
|
-
|
|
9
|
-
export default function posthogNetworkBootstrap() {
|
|
10
|
-
// Side effects run at module load; no hooks required.
|
|
11
|
-
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/.pi/scripts/release.sh
DELETED
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# release.sh — Version bump, changelog, tag, and push
|
|
4
|
-
# Usage: ./.pi/scripts/release.sh [patch|minor|major] [--dry-run]
|
|
5
|
-
#
|
|
6
|
-
set -euo pipefail
|
|
7
|
-
|
|
8
|
-
# ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
9
|
-
warn() { echo "⚠ $*" >&2; }
|
|
10
|
-
abort() { echo "✗ $*" >&2; exit 1; }
|
|
11
|
-
ok() { echo "✓ $*"; }
|
|
12
|
-
|
|
13
|
-
# ─── Step 0 — Parse arguments ─────────────────────────────────────────────────
|
|
14
|
-
BUMP_TYPE=""
|
|
15
|
-
DRY_RUN=false
|
|
16
|
-
|
|
17
|
-
for arg in "$@"; do
|
|
18
|
-
case "$arg" in
|
|
19
|
-
patch|minor|major) BUMP_TYPE="$arg" ;;
|
|
20
|
-
--dry-run) DRY_RUN=true ;;
|
|
21
|
-
*) abort "Unknown argument: $arg" ;;
|
|
22
|
-
esac
|
|
23
|
-
done
|
|
24
|
-
|
|
25
|
-
# ─── Step 1 — Infer bump type from commits if not provided ────────────────────
|
|
26
|
-
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
|
27
|
-
|
|
28
|
-
if [ -z "$BUMP_TYPE" ]; then
|
|
29
|
-
ok "No bump type provided. Scanning commits since last tag…"
|
|
30
|
-
|
|
31
|
-
if [ -z "$LAST_TAG" ]; then
|
|
32
|
-
COMMIT_LOG=$(git log --format="%s" HEAD 2>/dev/null || true)
|
|
33
|
-
else
|
|
34
|
-
COMMIT_LOG=$(git log --format="%s" "${LAST_TAG}..HEAD" 2>/dev/null || true)
|
|
35
|
-
fi
|
|
36
|
-
|
|
37
|
-
if [ -z "$COMMIT_LOG" ]; then
|
|
38
|
-
abort "No commits since last tag. Nothing to release."
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
# Inference rules
|
|
42
|
-
if echo "$COMMIT_LOG" | grep -qE '^feat!:|BREAKING CHANGE'; then
|
|
43
|
-
BUMP_TYPE="major"
|
|
44
|
-
elif echo "$COMMIT_LOG" | grep -qE '^feat:'; then
|
|
45
|
-
BUMP_TYPE="minor"
|
|
46
|
-
else
|
|
47
|
-
BUMP_TYPE="patch"
|
|
48
|
-
fi
|
|
49
|
-
|
|
50
|
-
ok "Inferred bump type: $BUMP_TYPE"
|
|
51
|
-
fi
|
|
52
|
-
|
|
53
|
-
# ─── Step 2 — Read current version and validate semver ────────────────────────
|
|
54
|
-
CURRENT_VERSION=$(node -e "console.log(require('./package.json').version)" 2>/dev/null) \
|
|
55
|
-
|| abort "Failed to read version from package.json"
|
|
56
|
-
|
|
57
|
-
if ! [[ "$CURRENT_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
58
|
-
abort "Invalid semver in package.json: $CURRENT_VERSION"
|
|
59
|
-
fi
|
|
60
|
-
|
|
61
|
-
NEW_VERSION=$(node -e "
|
|
62
|
-
const [maj, min, pat] = '$CURRENT_VERSION'.split('.').map(Number);
|
|
63
|
-
const bump = '$BUMP_TYPE';
|
|
64
|
-
if (bump === 'major') console.log((maj + 1) + '.0.0');
|
|
65
|
-
else if (bump === 'minor') console.log(maj + '.' + (min + 1) + '.0');
|
|
66
|
-
else console.log(maj + '.' + min + '.' + (pat + 1));
|
|
67
|
-
")
|
|
68
|
-
|
|
69
|
-
ok "Version: $CURRENT_VERSION → $NEW_VERSION"
|
|
70
|
-
|
|
71
|
-
# ─── Step 3 — Pre-flight checks ───────────────────────────────────────────────
|
|
72
|
-
|
|
73
|
-
# Must be in a git repo
|
|
74
|
-
git rev-parse --is-inside-work-tree >/dev/null 2>&1 \
|
|
75
|
-
|| abort "Not a git repository."
|
|
76
|
-
|
|
77
|
-
# Must have origin remote
|
|
78
|
-
git remote -v | grep -q origin \
|
|
79
|
-
|| abort "No 'origin' remote configured."
|
|
80
|
-
|
|
81
|
-
# Must be on a branch (not detached HEAD)
|
|
82
|
-
BRANCH=$(git symbolic-ref -q HEAD 2>/dev/null | sed 's|^refs/heads/||') \
|
|
83
|
-
|| abort "Detached HEAD. Switch to a branch first."
|
|
84
|
-
|
|
85
|
-
# Must have clean working tree (warn only in dry-run)
|
|
86
|
-
git diff --quiet && git diff --cached --quiet
|
|
87
|
-
if [ $? -ne 0 ]; then
|
|
88
|
-
if [ "$DRY_RUN" = true ]; then
|
|
89
|
-
warn "Working tree is dirty — actual release would be blocked."
|
|
90
|
-
else
|
|
91
|
-
abort "Working tree is dirty. Commit or stash changes first."
|
|
92
|
-
fi
|
|
93
|
-
fi
|
|
94
|
-
|
|
95
|
-
# No duplicate tag locally or on remote
|
|
96
|
-
if git rev-parse "v$NEW_VERSION" >/dev/null 2>&1; then
|
|
97
|
-
abort "Tag v$NEW_VERSION already exists locally."
|
|
98
|
-
fi
|
|
99
|
-
if git ls-remote --tags origin "refs/tags/v$NEW_VERSION" >/dev/null 2>&1; then
|
|
100
|
-
abort "Tag v$NEW_VERSION already exists on remote."
|
|
101
|
-
fi
|
|
102
|
-
|
|
103
|
-
# ─── Step 4 — Gather commits since last tag ───────────────────────────────────
|
|
104
|
-
if [ -z "$LAST_TAG" ]; then
|
|
105
|
-
COMMITS=$(git log --oneline --no-merges HEAD)
|
|
106
|
-
else
|
|
107
|
-
COMMITS=$(git log --oneline --no-merges "${LAST_TAG}..HEAD")
|
|
108
|
-
fi
|
|
109
|
-
|
|
110
|
-
COMMIT_COUNT=$(echo "$COMMITS" | grep -c '^' || echo 0)
|
|
111
|
-
|
|
112
|
-
if [ "$COMMIT_COUNT" -eq 0 ]; then
|
|
113
|
-
abort "No commits since last tag. Nothing to release."
|
|
114
|
-
fi
|
|
115
|
-
|
|
116
|
-
# ─── Step 5 — Generate changelog entry ────────────────────────────────────────
|
|
117
|
-
|
|
118
|
-
# Map conventional commit prefix → section
|
|
119
|
-
map_prefix() {
|
|
120
|
-
local msg="$1"
|
|
121
|
-
case "$msg" in
|
|
122
|
-
feat!:*|*"BREAKING CHANGE"*) echo "breaking" ;;
|
|
123
|
-
feat:*) echo "features" ;;
|
|
124
|
-
fix:*) echo "fixes" ;;
|
|
125
|
-
perf:*) echo "perf" ;;
|
|
126
|
-
refactor:*) echo "refactor" ;;
|
|
127
|
-
docs:*) echo "docs" ;;
|
|
128
|
-
style:*) echo "style" ;;
|
|
129
|
-
test:*) echo "tests" ;;
|
|
130
|
-
chore:*) echo "chores" ;;
|
|
131
|
-
ci:*) echo "ci" ;;
|
|
132
|
-
build:*) echo "build" ;;
|
|
133
|
-
*) echo "chores" ;;
|
|
134
|
-
esac
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
declare -A SECTIONS=(
|
|
138
|
-
[breaking]="⚠️ Breaking Changes"
|
|
139
|
-
[features]="✨ Features"
|
|
140
|
-
[fixes]="🐛 Fixes"
|
|
141
|
-
[perf]="⚡ Performance"
|
|
142
|
-
[refactor]="♻️ Refactoring"
|
|
143
|
-
[docs]="📖 Documentation"
|
|
144
|
-
[style]="🎨 Style"
|
|
145
|
-
[tests]="✅ Tests"
|
|
146
|
-
[chores]="🔧 Chores"
|
|
147
|
-
[ci]="🔄 CI/CD"
|
|
148
|
-
[build]="📦 Build"
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
# Build per-section entries
|
|
152
|
-
entries_breaking=""
|
|
153
|
-
entries_features=""
|
|
154
|
-
entries_fixes=""
|
|
155
|
-
entries_perf=""
|
|
156
|
-
entries_refactor=""
|
|
157
|
-
entries_docs=""
|
|
158
|
-
entries_style=""
|
|
159
|
-
entries_tests=""
|
|
160
|
-
entries_chores=""
|
|
161
|
-
entries_ci=""
|
|
162
|
-
entries_build=""
|
|
163
|
-
|
|
164
|
-
while IFS= read -r line; do
|
|
165
|
-
[ -z "$line" ] && continue
|
|
166
|
-
# Strip the short sha prefix (first word)
|
|
167
|
-
msg="${line#* }"
|
|
168
|
-
# Strip conventional commit prefix for display
|
|
169
|
-
display="$msg"
|
|
170
|
-
display=$(echo "$display" | sed -E 's/^[a-z]+(\([a-z0-9_-]+\))?!?:\s*//')
|
|
171
|
-
prefix=$(map_prefix "$msg")
|
|
172
|
-
case "$prefix" in
|
|
173
|
-
breaking) entries_breaking="${entries_breaking}- $display
|
|
174
|
-
" ;;
|
|
175
|
-
features) entries_features="${entries_features}- $display
|
|
176
|
-
" ;;
|
|
177
|
-
fixes) entries_fixes="${entries_fixes}- $display
|
|
178
|
-
" ;;
|
|
179
|
-
perf) entries_perf="${entries_perf}- $display
|
|
180
|
-
" ;;
|
|
181
|
-
refactor) entries_refactor="${entries_refactor}- $display
|
|
182
|
-
" ;;
|
|
183
|
-
docs) entries_docs="${entries_docs}- $display
|
|
184
|
-
" ;;
|
|
185
|
-
style) entries_style="${entries_style}- $display
|
|
186
|
-
" ;;
|
|
187
|
-
tests) entries_tests="${entries_tests}- $display
|
|
188
|
-
" ;;
|
|
189
|
-
ci) entries_ci="${entries_ci}- $display
|
|
190
|
-
" ;;
|
|
191
|
-
build) entries_build="${entries_build}- $display
|
|
192
|
-
" ;;
|
|
193
|
-
*) entries_chores="${entries_chores}- $display
|
|
194
|
-
" ;;
|
|
195
|
-
esac
|
|
196
|
-
done <<< "$COMMITS"
|
|
197
|
-
|
|
198
|
-
# Assemble the changelog block
|
|
199
|
-
TODAY=$(date +%Y-%m-%d)
|
|
200
|
-
CHANGELOG_BLOCK="## [v$NEW_VERSION] — $TODAY
|
|
201
|
-
"
|
|
202
|
-
|
|
203
|
-
for key in breaking features fixes perf refactor docs style tests ci build chores; do
|
|
204
|
-
eval "content=\"\$entries_$key\""
|
|
205
|
-
if [ -n "$content" ]; then
|
|
206
|
-
CHANGELOG_BLOCK="${CHANGELOG_BLOCK}
|
|
207
|
-
### ${SECTIONS[$key]}
|
|
208
|
-
|
|
209
|
-
$content"
|
|
210
|
-
fi
|
|
211
|
-
done
|
|
212
|
-
|
|
213
|
-
# ─── Step 6 — Dry run check ───────────────────────────────────────────────────
|
|
214
|
-
if [ "$DRY_RUN" = true ]; then
|
|
215
|
-
echo ""
|
|
216
|
-
echo "═══════════════════════════════════════════════════════════════"
|
|
217
|
-
echo " DRY RUN — no changes made"
|
|
218
|
-
echo "═══════════════════════════════════════════════════════════════"
|
|
219
|
-
echo " Version: $CURRENT_VERSION → $NEW_VERSION"
|
|
220
|
-
echo " Bump: $BUMP_TYPE"
|
|
221
|
-
echo " Commits: $COMMIT_COUNT since ${LAST_TAG:-<none>}"
|
|
222
|
-
echo " Branch: $BRANCH"
|
|
223
|
-
echo ""
|
|
224
|
-
echo " Files that would change:"
|
|
225
|
-
echo " - package.json (version → $NEW_VERSION)"
|
|
226
|
-
echo " - CHANGELOG.md (new entry below)"
|
|
227
|
-
echo ""
|
|
228
|
-
echo " Tag that would be created: v$NEW_VERSION"
|
|
229
|
-
echo ""
|
|
230
|
-
echo " Changelog entry:"
|
|
231
|
-
echo "───────────────────────────────────────────────────────────────"
|
|
232
|
-
echo "$CHANGELOG_BLOCK"
|
|
233
|
-
echo "───────────────────────────────────────────────────────────────"
|
|
234
|
-
exit 0
|
|
235
|
-
fi
|
|
236
|
-
|
|
237
|
-
# ─── Step 7 — Bump version in package.json ────────────────────────────────────
|
|
238
|
-
npm pkg set version="$NEW_VERSION"
|
|
239
|
-
|
|
240
|
-
node -e "
|
|
241
|
-
const v = require('./package.json').version;
|
|
242
|
-
if (v !== '$NEW_VERSION') {
|
|
243
|
-
console.error('✗ version mismatch: expected $NEW_VERSION, got ' + v);
|
|
244
|
-
process.exit(1);
|
|
245
|
-
}
|
|
246
|
-
console.log('✓ version bumped to $NEW_VERSION');
|
|
247
|
-
"
|
|
248
|
-
|
|
249
|
-
# ─── Step 8 — Write CHANGELOG.md ──────────────────────────────────────────────
|
|
250
|
-
if [ -f CHANGELOG.md ]; then
|
|
251
|
-
# Prepend after the first heading line
|
|
252
|
-
{
|
|
253
|
-
head -n 1 CHANGELOG.md
|
|
254
|
-
echo ""
|
|
255
|
-
echo "$CHANGELOG_BLOCK"
|
|
256
|
-
tail -n +2 CHANGELOG.md
|
|
257
|
-
} > CHANGELOG.md.tmp && mv CHANGELOG.md.tmp CHANGELOG.md
|
|
258
|
-
else
|
|
259
|
-
{
|
|
260
|
-
echo "# Changelog"
|
|
261
|
-
echo ""
|
|
262
|
-
echo "All notable changes to this project are documented in this file."
|
|
263
|
-
echo ""
|
|
264
|
-
echo "$CHANGELOG_BLOCK"
|
|
265
|
-
} > CHANGELOG.md
|
|
266
|
-
fi
|
|
267
|
-
|
|
268
|
-
ok "CHANGELOG.md updated"
|
|
269
|
-
|
|
270
|
-
# ─── Step 9 — Read co-author config ───────────────────────────────────────────
|
|
271
|
-
CO_AUTHOR="pi-mono <261679550+pi-mono@users.noreply.github.com>"
|
|
272
|
-
if [ -f .pi/auto-commit.json ]; then
|
|
273
|
-
CO_AUTHOR=$(node -e "
|
|
274
|
-
const fs = require('fs');
|
|
275
|
-
const cfg = JSON.parse(fs.readFileSync('.pi/auto-commit.json', 'utf8'));
|
|
276
|
-
const ca = cfg.coAuthor || {};
|
|
277
|
-
console.log((ca.login || 'pi-mono') + ' <' + (ca.email || '261679550+pi-mono@users.noreply.github.com') + '>');
|
|
278
|
-
" 2>/dev/null) || true
|
|
279
|
-
fi
|
|
280
|
-
|
|
281
|
-
# ─── Step 10 — Commit ─────────────────────────────────────────────────────────
|
|
282
|
-
git add package.json CHANGELOG.md
|
|
283
|
-
|
|
284
|
-
COMMIT_BODY=$(cat <<EOF
|
|
285
|
-
- Bump version in package.json
|
|
286
|
-
- Add changelog entry for v$NEW_VERSION
|
|
287
|
-
|
|
288
|
-
Commits included:
|
|
289
|
-
$(echo "$COMMITS" | sed 's/^/- /')
|
|
290
|
-
EOF
|
|
291
|
-
)
|
|
292
|
-
|
|
293
|
-
git commit -m "chore(release): bump to v$NEW_VERSION" \
|
|
294
|
-
-m "$COMMIT_BODY" \
|
|
295
|
-
-m "Co-authored-by: $CO_AUTHOR"
|
|
296
|
-
|
|
297
|
-
ok "Committed version bump + changelog"
|
|
298
|
-
|
|
299
|
-
# ─── Step 11 — Create and push tag ────────────────────────────────────────────
|
|
300
|
-
TAG_BODY=$(cat <<EOF
|
|
301
|
-
Release v$NEW_VERSION — $BUMP_TYPE bump
|
|
302
|
-
|
|
303
|
-
$COMMITS
|
|
304
|
-
EOF
|
|
305
|
-
)
|
|
306
|
-
|
|
307
|
-
git tag -a "v$NEW_VERSION" -m "$TAG_BODY"
|
|
308
|
-
ok "Created tag v$NEW_VERSION"
|
|
309
|
-
|
|
310
|
-
git push origin "v$NEW_VERSION"
|
|
311
|
-
ok "Pushed tag v$NEW_VERSION to origin"
|
|
312
|
-
|
|
313
|
-
# ─── Step 12 — Optionally push branch commit ──────────────────────────────────
|
|
314
|
-
echo ""
|
|
315
|
-
read -rp "Push the version-bump commit to the current branch ($BRANCH) too? [Y/n] " PUSH_BRANCH
|
|
316
|
-
if [[ "$PUSH_BRANCH" =~ ^[Yy]?$ ]]; then
|
|
317
|
-
git push origin "$BRANCH"
|
|
318
|
-
ok "Pushed commit to $BRANCH"
|
|
319
|
-
else
|
|
320
|
-
echo "Skipped branch push."
|
|
321
|
-
fi
|
|
322
|
-
|
|
323
|
-
# ─── Step 13 — Report ─────────────────────────────────────────────────────────
|
|
324
|
-
echo ""
|
|
325
|
-
echo "═══════════════════════════════════════════════════════════════"
|
|
326
|
-
echo " ✓ Released v$NEW_VERSION ($BUMP_TYPE)"
|
|
327
|
-
echo "═══════════════════════════════════════════════════════════════"
|
|
328
|
-
echo " Tag: v$NEW_VERSION — pushed to origin"
|
|
329
|
-
echo " Commit: $(git rev-parse --short HEAD)"
|
|
330
|
-
echo " Branch: $BRANCH"
|
|
331
|
-
echo ""
|
|
332
|
-
echo " Workflows triggered:"
|
|
333
|
-
echo " - .github/workflows/publish-github-packages.yml"
|
|
334
|
-
echo " - .github/workflows/publish-npm.yml"
|
|
335
|
-
echo ""
|
|
336
|
-
echo " Changelog: CHANGELOG.md updated"
|
|
337
|
-
echo " Monitor: https://github.com/aryaniyaps/ultimate-pi/actions"
|
|
338
|
-
echo "═══════════════════════════════════════════════════════════════"
|