Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## 변경 목적

<!-- Conventional Commits 형식의 PR 제목과 하나 이상의 type:* 라벨을 사용하세요. area:*는 선택입니다. -->

## 검증 결과

<!-- 실행한 검사와 결과, 실행하지 못한 검사를 적어 주세요. -->

## 호환성 영향

<!-- 사용자 문서, 공개 API 또는 플러그인 계약에 미치는 영향을 적어 주세요. 호환성을 깨는 변경에는 type:breaking을 추가하세요. -->
52 changes: 52 additions & 0 deletions .github/workflows/desktop-core-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Desktop core validation

on:
pull_request:
branches: [main]

permissions:
contents: read

concurrency:
group: desktop-core-${{ github.event.number }}
cancel-in-progress: true

jobs:
desktop:
name: Desktop core / ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-2022, macos-14, ubuntu-22.04]
runs-on: ${{ matrix.os }}
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-node@v7
with:
node-version: '24.21.0'
cache: npm
- run: npm ci
- name: Linux desktop dependencies
if: runner.os == 'Linux'
run: npx playwright install-deps chromium
- run: npm run check
- name: Core document flow
if: runner.os != 'Linux'
run: npm run test:desktop:core
- name: Core document flow under Xvfb
if: runner.os == 'Linux'
run: xvfb-run -a npm run test:desktop:core
- name: Core evidence
if: always()
uses: actions/upload-artifact@v7
with:
name: desktop-core-${{ matrix.os }}
retention-days: 14
include-hidden-files: true
path: |
.pre04-runs/core-*/results.json
.pre04-runs/core-*/*.log
.pre04-runs/core-*/*.png
13 changes: 9 additions & 4 deletions .github/workflows/desktop-validation.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
name: Desktop validation
name: Desktop full validation

on:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read

jobs:
desktop:
name: Desktop / ${{ matrix.os }}
name: Desktop full / ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -53,6 +51,9 @@ jobs:
retention-days: 14
include-hidden-files: true
path: |
.pre04-runs/core-*/results.json
.pre04-runs/core-*/*.log
.pre04-runs/core-*/*.png
.pre04-runs/integration-*/results.json
.pre04-runs/integration-*/*.log
.pre04-runs/smoke-*/results.json
Expand All @@ -64,3 +65,7 @@ jobs:

.pre04-runs/m3-*/results.json
.pre04-runs/m3-*/*.png
.pre04-runs/m4-*/results.json
.pre04-runs/m4-*/*.png
.pre04-runs/ux-*/results.json
.pre04-runs/ux-*/*.png
36 changes: 36 additions & 0 deletions .github/workflows/pr-policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: PR policy

on:
pull_request:
branches: [main]
types: [opened, reopened, synchronize, edited, labeled, unlabeled, ready_for_review]

permissions:
contents: read
pull-requests: read

concurrency:
group: pr-policy-${{ github.event.number }}
cancel-in-progress: true

jobs:
policy:
name: PR policy
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-node@v7
with:
node-version: '24.21.0'
- run: node --test scripts/pr-policy.test.mjs
- name: Read current PR metadata and validate
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.number }}
run: |
gh api "repos/$GH_REPO/pulls/$PR_NUMBER" --jq '{pull_request: .}' > "$RUNNER_TEMP/pr-policy.json"
GITHUB_EVENT_PATH="$RUNNER_TEMP/pr-policy.json" node scripts/pr-policy.mjs
21 changes: 21 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,28 @@ permissions:
contents: read

jobs:
validation:
name: Verify full validation
runs-on: ubuntu-22.04
timeout-minutes: 5
permissions:
contents: read
actions: read
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-node@v7
with:
node-version: '24.21.0'
- name: Require manual full validation of the release commit
env:
GH_TOKEN: ${{ github.token }}
run: |
export RELEASE_COMMIT="$(git rev-parse HEAD)"
node scripts/release-validation.mjs
package:
needs: validation
name: Package / ${{ matrix.asset }}
strategy:
fail-fast: false
Expand Down
128 changes: 128 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
= Metis
:experimental:

English | link:doc/README.ko.adoc[한국어]

Metis aims to be a local-first knowledge tool that uses standard AsciiDoc documents as the source of truth. Built around file ownership and tool independence, it helps users structure, compose, reuse, and explore connected knowledge.

== Development philosophy

**Knowledge should remain in the user's files, and tools should help users work with it.** Metis aims to provide an AsciiDoc-based knowledge environment where documents remain readable, editable, and reusable even after users stop using the app.

image::doc/diagrams/philosophy-en.svg[Workflow diagram]

link:doc/diagrams/philosophy-en.mmd[Mermaid source]

The following principles guide implementation and feature decisions. Document meaning and portability take priority when adding convenience features.

* **AsciiDoc source first:** Respect its syntax and semantics, and avoid custom syntax where the standard can express the content. Derived data, such as search indexes and graphs, must be rebuildable from the source.
* **Files and ownership first:** Use local plain text files as the foundation of knowledge. The same documents should work with other editors, Git, and AsciiDoc tools.
* **Meaning and reuse:** Prioritize document meaning over presentation. Use ``include``, attributes, and ``xref`` to compose and reuse documents.
* **Extensions that preserve the source:** Design plugins and AI to assist document work. Knowledge must remain readable and durable when those features are removed.

The principles above guide development priorities and decisions.

== Development environment

Metis is a desktop app built with Electron, React, and TypeScript. npm workspaces manage the app and shared packages.

[cols="1,3",options="header"]
|===
| Requirement | Details
| Node.js | ``>=24.21.0 <25``; **24.21.0** is the reproducibility and CI baseline
| npm | **11.19.0** was used for existing local validation; install using the root ``package-lock.json``
| Operating system | Locally validated on Windows x64. CI is configured for macOS and Linux, but execution has not yet been validated
| Runtime environment | A desktop environment capable of displaying Electron windows. Network access is required for the initial dependency and Electron installation
|===

Run all commands from the **repository root**. Basic usage requires no separate ``.env`` file, external server, or database configuration.

== Install, build, and run

[source,sh]
----
npm ci
npm start
----

``npm start`` builds the app and launches Electron. Select **Open folder (폴더 열기)** to open a folder containing AsciiDoc documents, or start with **New workspace (새 작업 공간)**. Use **New document (새 문서)** to create a document in the workspace.

To build without launching the app:

[source,sh]
----
npm run build
----

Build output is written to ``apps/desktop/dist/``. There is currently no development server, watch mode, or HMR command. After editing the source, close the running app and run ``npm start`` again.

image::doc/diagrams/development-en.svg[Workflow diagram]

link:doc/diagrams/development-en.mmd[Mermaid source]

== Validate changes

[source,sh]
----
npm run check
npm run test:desktop:core
----

PRs run these commands on Windows, macOS, and Linux. The core GUI scenario checks startup, opening a workspace, document creation, editing, saving and reopening, AsciiDoc preview, search, and source-byte preservation. PRs do not package the application or run the full GUI suite.

[cols="1,3",options="header"]
|===
| Command | Purpose
| ``npm run check`` | Type checking, unit tests, tooling tests, and build
| ``npm run test:desktop:core`` | Core document flow against the built development app
| ``npm run test:integration`` | Full development GUI suite: 31 existing scenarios plus the core flow
| ``npm run test:integration:packaged`` | The same full suite against the latest packaged app
|===

GUI tests do not build the app. Run the check or build command first. Evidence is saved under ``.pre04-runs/core-*/`` and ``.pre04-runs/integration-*/``. Linux uses Xvfb for GUI tests.

Before releasing, manually run the full 3-OS validation from Actions or the CLI:

[source,sh]
----
gh workflow run desktop-validation.yml --ref main
gh run list --workflow desktop-validation.yml --event workflow_dispatch --branch main
gh run watch RUN_ID --exit-status
gh run view RUN_ID --json headSha,url,conclusion
----

Tag the successful run's exact headSha, even if main has advanced. Release packaging requires the latest manual full validation of that same main commit and all three OS jobs to succeed. Full validation includes packaging and both development and packaged GUI suites; it never publishes a release by itself. See link:doc/git-strategy.adoc[Git strategy] for retry and tag rules.

== Package the app

[source,sh]
----
npm run package
npm run test:integration:packaged
----

``package`` includes a build and creates an **application folder for the current host OS and architecture** under ``.pre04-runs/package-*/out/``. It does not include an installer, signing, or automatic updates. The latest package staging path is recorded in ``.pre04-runs/latest-package.txt``, which packaged integration tests read automatically.

To launch the packaged app directly from Windows PowerShell:

[source,powershell]
----
$metisPackage = Get-Content .pre04-runs/latest-package.txt
& "$metisPackage/out/Metis-win32-x64/Metis.exe"
----

This example targets Windows x64. On Linux, run packaged GUI tests with ``xvfb-run -a npm run test:integration:packaged``.

== Respect — Obsidian and AsciiDoc

Metis respects and draws inspiration from Obsidian and AsciiDoc.

**Obsidian** is an important reference for Metis's approach to local-first work, user-owned knowledge, connections and exploration between documents, and extensible workflows. We aim to learn from the experience it offers people building and connecting their own knowledge.

**AsciiDoc** provides the foundation for Metis's document philosophy and source format. We value meaningful plain text, the separation of content and presentation, and document structure, composition, and reuse. We aim to keep documents usable with existing AsciiDoc tools.

We thank the developers and contributors who have built and sustained both projects and their ecosystems. Inspired by their work, Metis aims to create a knowledge workspace that stays true to AsciiDoc.

== Contributing and Git policy

See link:doc/git-strategy.adoc[Git strategy] for PR labels, required checks, squash merges, and release tag protection.
Loading
Loading