mirror of
https://github.com/dtzp555-max/ocp.git
synced 2026-07-19 09:44:07 +00:00
chore(repo): add .gitignore for runtime artifacts; commit scripts/heartbeat-field-check.sh (#55)
Two related changes — both repo-hygiene, no behavior impact. ### `.gitignore` (new) Ignores runtime artifacts that should never be tracked: - `logs/` and `*.log` — proxy.log, last_send.log, heartbeat-field-check log - `node_modules/` — dependency cache - `.env`, `.env.*` — local secrets/config - `.DS_Store`, `*.swp`, `*~` — editor/OS scratch `logs/` was previously untracked-but-present in working trees; the new ignore makes that intent explicit and prevents accidental commits. ### `scripts/heartbeat-field-check.sh` (commit existing untracked file) This script was authored as a one-shot field-evidence gatherer for the v3.12.0 SSE heartbeat work (PR #49 / issue #47). It fired successfully on 2026-05-02 09:00 Australia/Brisbane via launchd (`~/Library/LaunchAgents/dev.ocp.heartbeat-check.plist`) and posted a summary comment to issue #47. Useful tooling pattern (one-shot field check + launchd schedule + dry-run flag), worth keeping under version control rather than letting it die in an untracked working tree. Verification: `git status` clean after both adds. Co-authored-by: dtzp555 <dtzp555@gmail.com>
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
# Runtime artifacts
|
||||
logs/
|
||||
*.log
|
||||
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.*
|
||||
|
||||
# Editor / OS scratch
|
||||
.DS_Store
|
||||
*.swp
|
||||
*~
|
||||
Executable
+132
@@ -0,0 +1,132 @@
|
||||
#!/bin/bash
|
||||
# One-shot field-evidence gatherer for OCP v3.12.0 SSE heartbeat.
|
||||
# Scheduled by ~/Library/LaunchAgents/dev.ocp.heartbeat-check.plist to fire
|
||||
# once at 2026-05-02 09:00 Australia/Brisbane. Gathers evidence from local
|
||||
# OCP logs + GitHub issue #47 + repo issue search, posts a summary comment
|
||||
# on #47, and exits. Does NOT open PRs or change code — the maintainer
|
||||
# decides after reading the summary.
|
||||
#
|
||||
# Dry-run: ./heartbeat-field-check.sh --dry-run (prints summary, skips post)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO="dtzp555-max/ocp"
|
||||
SHIP_DATE="2026-04-25"
|
||||
# Baseline captured at script-install time so internal testing entries from
|
||||
# Phase 3 verification (~5 entries from 2026-04-25T00:00–00:48Z) don't get
|
||||
# counted as field evidence. Any heartbeat_active log entry with ts >= this
|
||||
# timestamp is treated as a real opt-in.
|
||||
BASELINE_TS="2026-04-25T01:00:00Z"
|
||||
PROXY_LOG="$HOME/ocp/logs/proxy.log"
|
||||
OUT_DIR="$HOME/ocp/logs"
|
||||
SELF_LOG="$OUT_DIR/heartbeat-field-check-$(date +%Y-%m-%d).log"
|
||||
DRY_RUN=0
|
||||
[ "${1:-}" = "--dry-run" ] && DRY_RUN=1
|
||||
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
exec > >(tee -a "$SELF_LOG") 2>&1
|
||||
|
||||
echo "=== heartbeat field-evidence check: $(date -u +%Y-%m-%dT%H:%M:%SZ) (dry_run=$DRY_RUN) ==="
|
||||
|
||||
# ── signal 1: local proxy log ─────────────────────────────────────────────
|
||||
if [ -r "$PROXY_LOG" ]; then
|
||||
# Only count entries with ts >= BASELINE_TS (string sort works on RFC3339)
|
||||
HEARTBEAT_COUNT=$(grep '"event":"heartbeat_active"' "$PROXY_LOG" 2>/dev/null \
|
||||
| awk -v base="$BASELINE_TS" '
|
||||
match($0, /"ts":"[^"]+"/) {
|
||||
ts = substr($0, RSTART+6, RLENGTH-7);
|
||||
if (ts >= base) c++
|
||||
}
|
||||
END { print c+0 }')
|
||||
else
|
||||
HEARTBEAT_COUNT=0
|
||||
fi
|
||||
echo "signal 1 — heartbeat_active log entries since $BASELINE_TS: $HEARTBEAT_COUNT"
|
||||
|
||||
# ── signal 2: comments on #47 since ship ──────────────────────────────────
|
||||
NEW_47_JSON="/tmp/ocp-47-new-comments-$$.json"
|
||||
gh issue view 47 --repo "$REPO" --json comments \
|
||||
--jq '[.comments[] | select(.createdAt >= "'"$SHIP_DATE"'T00:00:00Z")]' \
|
||||
> "$NEW_47_JSON" 2>/dev/null || echo "[]" > "$NEW_47_JSON"
|
||||
NEW_COMMENTS=$(jq 'length' "$NEW_47_JSON")
|
||||
echo "signal 2 — new comments on #47 since $SHIP_DATE: $NEW_COMMENTS"
|
||||
|
||||
# Build a compact, human-readable excerpt for the summary body
|
||||
NEW_47_EXCERPT=""
|
||||
if [ "$NEW_COMMENTS" -gt 0 ]; then
|
||||
NEW_47_EXCERPT=$(jq -r '.[] | "- **@\(.author.login)** (\(.createdAt)): " + (.body | gsub("\r"; "") | split("\n")[0])[:180]' "$NEW_47_JSON")
|
||||
fi
|
||||
|
||||
# ── signal 3: other heartbeat-related issues since ship ──────────────────
|
||||
OTHER_ISSUES_JSON="/tmp/ocp-heartbeat-issues-$$.json"
|
||||
gh search issues "repo:$REPO heartbeat" --json number,title,state,createdAt --limit 30 \
|
||||
--jq '[.[] | select(.createdAt >= "'"$SHIP_DATE"'T00:00:00Z" and .number != 47 and .number != 48)]' \
|
||||
> "$OTHER_ISSUES_JSON" 2>/dev/null || echo "[]" > "$OTHER_ISSUES_JSON"
|
||||
OTHER_ISSUES=$(jq 'length' "$OTHER_ISSUES_JSON")
|
||||
echo "signal 3 — other heartbeat-related issues since ship: $OTHER_ISSUES"
|
||||
|
||||
OTHER_ISSUES_EXCERPT=""
|
||||
if [ "$OTHER_ISSUES" -gt 0 ]; then
|
||||
OTHER_ISSUES_EXCERPT=$(jq -r '.[] | "- #\(.number) [\(.state)] \(.title)"' "$OTHER_ISSUES_JSON")
|
||||
fi
|
||||
|
||||
# ── compose summary ──────────────────────────────────────────────────────
|
||||
BODY_FILE="/tmp/ocp-47-summary-$$.md"
|
||||
{
|
||||
echo "### Automated 7-day field-evidence check (v3.12.0)"
|
||||
echo
|
||||
echo "_Triggered by a local launchd scheduled task on the maintainer's rig at $(date -u +%Y-%m-%dT%H:%M:%SZ)._"
|
||||
echo
|
||||
echo "| Signal | Count |"
|
||||
echo "|---|---|"
|
||||
echo "| \`heartbeat_active\` log entries on prod rig (since baseline $BASELINE_TS) | $HEARTBEAT_COUNT |"
|
||||
echo "| New comments on #47 since $SHIP_DATE | $NEW_COMMENTS |"
|
||||
echo "| Other heartbeat-related issues filed since $SHIP_DATE | $OTHER_ISSUES |"
|
||||
echo
|
||||
if [ -n "$NEW_47_EXCERPT" ]; then
|
||||
echo "**New #47 comments (first line each):**"
|
||||
echo
|
||||
echo "$NEW_47_EXCERPT"
|
||||
echo
|
||||
fi
|
||||
if [ -n "$OTHER_ISSUES_EXCERPT" ]; then
|
||||
echo "**Other heartbeat-related issues:**"
|
||||
echo
|
||||
echo "$OTHER_ISSUES_EXCERPT"
|
||||
echo
|
||||
fi
|
||||
echo "**Decision guidance for maintainer (manual):**"
|
||||
echo
|
||||
echo "- If any of the above indicate a **crash report** on \`: keepalive\` comment frames → leave default at \`0\` and file a \`CLAUDE_HEARTBEAT_FORMAT=empty-delta\` follow-up issue (spec \`§D2\` fallback plan)."
|
||||
echo "- If there is at least one **opt-in confirmation** (a user reports \`CLAUDE_HEARTBEAT_INTERVAL\` fixed their timeout issue) and no crash reports → consider opening a PR for v3.13.0 flipping the default to \`30000\`, following the same ALIGNMENT + independent-reviewer + release-kit discipline as PR #49."
|
||||
echo "- If all three signals are zero → extend the soak window or close this follow-up as \"no field evidence.\""
|
||||
echo
|
||||
echo "This bot does not open PRs or change code. The maintainer reviews and acts."
|
||||
} > "$BODY_FILE"
|
||||
|
||||
echo "--- summary preview ---"
|
||||
cat "$BODY_FILE"
|
||||
echo "--- end preview ---"
|
||||
|
||||
# ── post (unless dry-run) ────────────────────────────────────────────────
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
echo "DRY RUN — skipping gh issue comment"
|
||||
else
|
||||
gh issue comment 47 --repo "$REPO" --body-file "$BODY_FILE" && echo "comment posted on #47"
|
||||
fi
|
||||
|
||||
# ── cleanup + self-disable so the plist doesn't linger loaded forever ────
|
||||
rm -f "$NEW_47_JSON" "$OTHER_ISSUES_JSON" "$BODY_FILE"
|
||||
|
||||
if [ "$DRY_RUN" -eq 0 ]; then
|
||||
# Unload + remove the plist so this never fires again
|
||||
PLIST="$HOME/Library/LaunchAgents/dev.ocp.heartbeat-check.plist"
|
||||
if [ -f "$PLIST" ]; then
|
||||
launchctl bootout "gui/$(id -u)" "$PLIST" 2>/dev/null || launchctl unload "$PLIST" 2>/dev/null || true
|
||||
rm -f "$PLIST"
|
||||
echo "self-disabled: removed $PLIST"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "=== done ==="
|
||||
Reference in New Issue
Block a user