diff --git a/.github/workflows/release-orchestrate.yml b/.github/workflows/release-orchestrate.yml new file mode 100644 index 0000000..4f6796e --- /dev/null +++ b/.github/workflows/release-orchestrate.yml @@ -0,0 +1,86 @@ +name: release-orchestrate + +# One command publishes everything for tag vX.Y.Z: +# gh workflow run release-orchestrate.yml --ref vX.Y.Z -f version=X.Y.Z +# Resolves the release-build run for the tag, then serially dispatches: +# crates -> npm -> pypi -> latest-json -> post-release-verify +# Each child keeps its own context validation; this workflow only sequences them. + +on: + workflow_dispatch: + inputs: + version: + description: "Version without leading v (must match tag vX.Y.Z and Cargo.toml)" + required: true + type: string + +permissions: + contents: read + actions: write + +concurrency: + group: release-orchestrate-${{ inputs.version }} + cancel-in-progress: false + +jobs: + orchestrate: + name: orchestrate release v${{ inputs.version }} + runs-on: ubuntu-latest + timeout-minutes: 60 + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ inputs.version }} + steps: + - name: Checkout release tag + uses: actions/checkout@v4 + + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Validate release context + run: python3 scripts/validate_release_context.py + + - name: Resolve release-build run + run: | + TAG="v$VERSION" + RUN_JSON=$(gh run list --workflow=release-build.yml --branch "$TAG" --event push --json databaseId,status,conclusion,headSha --limit 1) + echo "$RUN_JSON" + RUN_ID=$(echo "$RUN_JSON" | jq -r '.[0].databaseId // empty') + STATUS=$(echo "$RUN_JSON" | jq -r '.[0].status // empty') + CONCLUSION=$(echo "$RUN_JSON" | jq -r '.[0].conclusion // empty') + HEAD_SHA=$(echo "$RUN_JSON" | jq -r '.[0].headSha // empty') + [ -n "$RUN_ID" ] || { echo "::error::No release-build run found for tag $TAG"; exit 1; } + [ "$STATUS" = "completed" ] || { echo "::error::release-build run $RUN_ID is still $STATUS"; exit 1; } + [ "$CONCLUSION" = "success" ] || { echo "::error::release-build run $RUN_ID concluded: $CONCLUSION"; exit 1; } + [ "$HEAD_SHA" = "$GITHUB_SHA" ] || { echo "::error::release-build headSha $HEAD_SHA != checkout $GITHUB_SHA"; exit 1; } + echo "BUILD_RUN_ID=$RUN_ID" >> "$GITHUB_ENV" + + - name: Publish (crates → npm → pypi → latest-json → verify) + run: | + TAG="v$VERSION" + dispatch_and_wait() { + local workflow="$1"; shift + echo "=== dispatching $workflow ===" + gh workflow run "$workflow" --ref "$TAG" "$@" + sleep 10 + local run_id="" + for _ in 1 2 3 4 5 6; do + run_id=$(gh run list --workflow="$workflow" --branch "$TAG" --event workflow_dispatch --json databaseId,status \ + --jq '[.[] | select(.status != "completed")][0].databaseId // empty') + [ -n "$run_id" ] && break + sleep 10 + done + [ -n "$run_id" ] || { echo "::error::$workflow run not found after dispatch"; exit 1; } + gh run watch "$run_id" --exit-status + } + dispatch_and_wait release-publish-crates.yml + dispatch_and_wait release-publish-npm.yml -f build_run_id="$BUILD_RUN_ID" + dispatch_and_wait release-publish-pypi.yml -f build_run_id="$BUILD_RUN_ID" + dispatch_and_wait release-update-latest-json.yml -f version="$VERSION" + dispatch_and_wait post-release-verify.yml -f version="$VERSION" + + - name: Release summary + run: | + gh release view "v$VERSION" --json tagName,isDraft,assets --jq '{tag: .tagName, draft: .isDraft, assets: (.assets | length)}' diff --git a/.gitignore b/.gitignore index 8825a24..d09eb17 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ * # Keep directory traversal so whitelisted paths below can be reached. -!*/ # Always ignore local-only directories and artifacts. /.claude/ @@ -21,6 +20,7 @@ /desktop/tauri/gen/ /desktop/tauri/target/ **/__pycache__/ +local/* # Root project metadata. !/.gitignore @@ -33,15 +33,18 @@ # Rust workspace. !/rust/ +!/rust/crates/**/ !/rust/Cargo.toml !/rust/Cargo.lock !/rust/crates/ !/rust/crates/**/Cargo.toml !/rust/crates/**/*.rs +!/rust/crates/**/CHANGELOG.md !/rust/crates/**/assets/ !/rust/crates/**/assets/*.json /rust/crates/**/assets/web/ !/rust/apps/ +!/rust/apps/**/ !/rust/apps/**/Cargo.toml !/rust/apps/**/*.rs !/rust/apps/**/assets/ @@ -53,13 +56,6 @@ !/.github/workflows/ !/.github/workflows/*.yml -# Local draft documentation. -/docs/* -# 规范文档作为架构验收标准,纳入版本控制 -!/docs/架构文档-重要架构设计v1.md -!/docs/项目骨架设计v1.md -!/docs/重构计划-v1.md -!/docs/技术文档-LIB说明v1.md # Web app source. !/apps/ @@ -109,20 +105,6 @@ !/python/packages/memorph/src/memorph/ !/python/packages/memorph/src/memorph/*.py -# Research notes (not part of the project source). -/headroom的调研报告.md -/memorph基于headroom完善压缩机制。md # Provider-native test fixtures. -!/rust/crates/memorph/src/providers/kimi/fixtures/ -!/rust/crates/memorph/src/providers/kimi/fixtures/** -!/rust/crates/memorph/src/providers/kiro/fixtures/ -!/rust/crates/memorph/src/providers/kiro/fixtures/** -!/rust/crates/memorph/src/providers/cursor/fixtures/ -!/rust/crates/memorph/src/providers/cursor/fixtures/** - -# Project-wide Codex experience instructions. -!AGENTS.md -!.agent/ -!.agent/config.toml -!docs/codex-experience.md +!/rust/crates/memorph/src/providers/**/fixtures/** \ No newline at end of file diff --git a/README.md b/README.md index 0339b6c..6c9821b 100644 --- a/README.md +++ b/README.md @@ -88,9 +88,9 @@ npx memorph ### CLI -CLI模式更多的是结合`SKILLS`之后利用agent帮你管理会话的迁移与管理 +CLI 可用于脚本、Agent 和人工操作。无参数运行直接打开 TUI;所有命令支持全局 `--json`。 -#### 查看当前工作区的可用会话-list +#### 会话列表与过滤:list ```bash memorph list [OPTIONS] @@ -98,141 +98,128 @@ memorph list [OPTIONS] | 参数 | 说明 | |------|------| -| `--all` | 显示所有工作区的会话 | -| `--claude` | 仅显示 Claude Code 会话 | -| `--codex` | 仅显示 Codex 会话 | -| `--opencode` | 仅显示 OpenCode 会话 | +| `--all` | 显示所有工作区会话 | +| `-p, --provider ` | 限定 Provider,可重复 | +| `--sort ` | 排序方式 | +| `--limit ` / `--offset ` | 分页 | +| `-d, --dir ` | 匹配项目目录或源路径 | +| `-s, --session ` | 匹配会话 ID 或标题 | +| `--title ` | 匹配会话标题 | +| `--text ` | 搜索消息正文 | +| `--since