ab6af144b7
---ci---
phase: 6
milestone: v0.5
status: complete
decisions:
- id: D-006
decision: Research as intermediate work product
rationale: Conclusions update .ci/ files; full research doc intentionally not preserved
confidence: 0.90
- id: D-007
decision: Branch hierarchy enforcement: main > milestone > phase
rationale: Prevents out-of-order merges and semantically wrong tags
confidence: 0.92
- id: D-008
decision: 3-tier versioning: NFR/feature/schema-breaking
rationale: Patch per phase (NFR/feature) or minor per phase (schema-breaking); milestone gets minor (feature) or major (schema-breaking)
confidence: 0.95
requirements:
covered: [VER-06, BRANCH-01, BRANCH-02, ARCH-01]
---/ci---
- Synthesize ARCHITECTURE-PLAN.md into .ci/ci/ARCHITECTURE.md (expanded 51→230 lines)
- Add D-006/D-007/D-008 to .ci/ci/PROJECT.md key decisions table
- Delete ARCHITECTURE-PLAN.md after synthesis
- Rewrite ship.md with 3-tier versioning model + branch hierarchy merge flows
- Rewrite branch-strategy.md with 3-tier versioning + branch hierarchy + version validation
- Add MilestoneType to config types
- Replace isNfrMilestone() with getMilestoneType() returning nfr|feature|schema-breaking
- Add validateMergeOrder(), mergeMilestoneBranch(), computeMilestoneTag() to GitBranch
- Add computeShipVersion(), validateVersionOrder(), resolveMergeTarget() to ship command
- Remove hardcoded v0.5. from error-recovery rollback
- Create .githooks/pre-push for semver ordering + branch hierarchy validation
- Add 15 new tests (370 total, all passing)
157 lines
5.3 KiB
Bash
Executable File
157 lines
5.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
OPENCODE_DIR="${HOME}/.config/opencode"
|
|
CI_DIR="$(cd "$(dirname "$0")/.." && pwd)/opencode"
|
|
|
|
UNINSTALL=false
|
|
FORCE=false
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--uninstall) UNINSTALL=true ;;
|
|
--force) FORCE=true ;;
|
|
--help|-h)
|
|
echo "Usage: $(basename "$0") [--uninstall] [--force]"
|
|
echo ""
|
|
echo "Install CI opencode integration files to ~/.config/opencode/"
|
|
echo ""
|
|
echo " --uninstall Remove CI integration files"
|
|
echo " --force Overwrite existing files without prompting"
|
|
echo " --help Show this help"
|
|
exit 0
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ "$UNINSTALL" = true ]; then
|
|
echo "Uninstalling CI opencode integration..."
|
|
|
|
rm -f "${OPENCODE_DIR}/agents/ci-"*.md 2>/dev/null || true
|
|
rm -f "${OPENCODE_DIR}/command/ci-"*.md 2>/dev/null || true
|
|
rm -rf "${OPENCODE_DIR}/ci/" 2>/dev/null || true
|
|
|
|
echo "CI integration files removed."
|
|
echo "Note: opencode.json permissions entry preserved (edit manually if needed)."
|
|
exit 0
|
|
fi
|
|
|
|
if [ ! -d "$CI_DIR" ]; then
|
|
echo "Error: opencode/ directory not found at ${CI_DIR}"
|
|
echo "Ensure you're running from the CI repository root."
|
|
exit 1
|
|
fi
|
|
|
|
echo "Installing CI opencode integration..."
|
|
echo " Source: ${CI_DIR}"
|
|
echo " Target: ${OPENCODE_DIR}"
|
|
echo ""
|
|
|
|
mkdir -p "${OPENCODE_DIR}/agents"
|
|
mkdir -p "${OPENCODE_DIR}/command"
|
|
mkdir -p "${OPENCODE_DIR}/ci/contexts"
|
|
mkdir -p "${OPENCODE_DIR}/ci/references"
|
|
mkdir -p "${OPENCODE_DIR}/ci/workflows"
|
|
|
|
COPIED=0
|
|
SKIPPED=0
|
|
|
|
copy_file() {
|
|
local src="$1"
|
|
local dest="$2"
|
|
|
|
if [ -f "$dest" ] && [ "$FORCE" = false ]; then
|
|
if cmp -s "$src" "$dest" 2>/dev/null; then
|
|
SKIPPED=$((SKIPPED + 1))
|
|
return
|
|
fi
|
|
echo " Conflict: $(basename "$src") already exists. Use --force to overwrite."
|
|
SKIPPED=$((SKIPPED + 1))
|
|
return
|
|
fi
|
|
|
|
sed "s|__OPENCODE_DIR__|${OPENCODE_DIR}|g" "$src" > "$dest"
|
|
COPIED=$((COPIED + 1))
|
|
}
|
|
|
|
echo "Installing agents..."
|
|
for f in "${CI_DIR}/agents/ci-"*.md; do
|
|
[ -f "$f" ] && copy_file "$f" "${OPENCODE_DIR}/agents/$(basename "$f")"
|
|
done
|
|
|
|
echo "Installing commands..."
|
|
for f in "${CI_DIR}/command/ci-"*.md; do
|
|
[ -f "$f" ] && copy_file "$f" "${OPENCODE_DIR}/command/$(basename "$f")"
|
|
done
|
|
|
|
echo "Installing contexts..."
|
|
for f in "${CI_DIR}/ci/contexts/"*.md; do
|
|
[ -f "$f" ] && copy_file "$f" "${OPENCODE_DIR}/ci/contexts/$(basename "$f")"
|
|
done
|
|
|
|
echo "Installing references..."
|
|
for f in "${CI_DIR}/ci/references/"*.md; do
|
|
[ -f "$f" ] && copy_file "$f" "${OPENCODE_DIR}/ci/references/$(basename "$f")"
|
|
done
|
|
|
|
echo "Installing workflows..."
|
|
for f in "${CI_DIR}/ci/workflows/"*.md; do
|
|
[ -f "$f" ] && copy_file "$f" "${OPENCODE_DIR}/ci/workflows/$(basename "$f")"
|
|
done
|
|
|
|
echo "Installing VERSION..."
|
|
[ -f "${CI_DIR}/ci/VERSION" ] && copy_file "${CI_DIR}/ci/VERSION" "${OPENCODE_DIR}/ci/VERSION"
|
|
|
|
echo ""
|
|
echo "Merging opencode.json permissions..."
|
|
OPENCODE_JSON="${OPENCODE_DIR}/opencode.json"
|
|
CI_JSON="${CI_DIR}/opencode.json"
|
|
|
|
if [ -f "$CI_JSON" ]; then
|
|
if [ ! -f "$OPENCODE_JSON" ]; then
|
|
sed "s|__OPENCODE_DIR__|${OPENCODE_DIR}|g" "$CI_JSON" > "$OPENCODE_JSON"
|
|
echo " Created opencode.json"
|
|
else
|
|
if command -v node &>/dev/null; then
|
|
local_ci_json="$(sed "s|__OPENCODE_DIR__|${OPENCODE_DIR}|g" "$CI_JSON")"
|
|
echo "$local_ci_json" > /tmp/ci-json-merge.json
|
|
node -e "
|
|
const fs = require('fs');
|
|
const existing = JSON.parse(fs.readFileSync('${OPENCODE_JSON}', 'utf8'));
|
|
const ci = JSON.parse(fs.readFileSync('/tmp/ci-json-merge.json', 'utf8'));
|
|
const merged = { ...existing };
|
|
merged.permission = merged.permission || {};
|
|
merged.permission.read = merged.permission.read || {};
|
|
merged.permission.external_directory = merged.permission.external_directory || {};
|
|
for (const [k, v] of Object.entries(ci.permission?.read || {})) {
|
|
if (!merged.permission.read[k]) merged.permission.read[k] = v;
|
|
}
|
|
for (const [k, v] of Object.entries(ci.permission?.external_directory || {})) {
|
|
if (!merged.permission.external_directory[k]) merged.permission.external_directory[k] = v;
|
|
}
|
|
fs.writeFileSync('${OPENCODE_JSON}', JSON.stringify(merged, null, 2));
|
|
console.log(' Merged permissions (preserved existing entries)');
|
|
"
|
|
rm -f /tmp/ci-json-merge.json
|
|
else
|
|
echo " Warning: node not found. Manually merge opencode.json permissions."
|
|
echo " Add to opencode.json:"
|
|
echo ' "~/.config/opencode/ci/*": "allow" (in permission.read and permission.external_directory)'
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo " CI ► INSTALL COMPLETE"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo " Copied: ${COPIED} files"
|
|
echo " Skipped: ${SKIPPED} files"
|
|
echo ""
|
|
echo " Commands available: ci-init, ci-run, ci-quick, ci-status,"
|
|
echo " ci-audit, ci-verify, ci-debug, ci-review, ci-ship,"
|
|
echo " ci-rollback, ci-clarify"
|
|
echo ""
|
|
echo " Run --uninstall to remove."
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" |