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
2 changes: 1 addition & 1 deletion dist/directory/fullops-squad/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fullops-squad",
"version": "1.8.5",
"version": "1.8.6",
"repository": "https://github.com/tourbut/Fullops-Squad-plugin",
"displayName": "FullOps Squad",
"description": "Opt-in development harness that coordinates role-based AI workers in Orca with handovers, design documents, lint gates and pre-merge review.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
tools/frontend/
# 판정에 쓰지 않은 캡처·첫 실행 실패본·스냅샷·중간 SHA gate 로그 (rules/common/testing.md)
docs/evaluations/qa-reports/**/raw/
# 레포 작업용 도구·로그·임시 산출물 (rules/common/README.md `작업 파일 위치`)
local/
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ worker는 항목을 끝낼 때마다 이 목록에 체크한다. 대화가 요

관찰 가능한 성공 조건·실행할 검증·예상 실패 및 경계 조건을 적는다. 끝난 상태를 한 번에 적는다(예: 엔드포인트 이전 완료, 레거시 삭제, 테스트 통과).
증명 방법: 이 과제의 완료를 무엇으로 보이는지 적는다(테스트·명령·Jev 시나리오·확인할 흐름). 상위 의도의 성공 기준을 맡으면 그 기준을 어떻게 보이는지 연결한다.
검사별 담당·대상·실행 시점·통과 조건을 적고 worker 완료와 제품 최종 수락을 구분한다. 하네스 제약도 적는다: FullOps lint 명령의 전체 경로·cwd·`--from <기준 SHA>`, 검증 증거 파일 형식(`.fullops-squad/` 아래 `.md`는 front matter 필수 — lint DOC-003, 원시 로그·캡처 텍스트는 `.txt`/`.log`), 재검토 리뷰의 base 조건(이전 리뷰 SHA의 후손), 원격·격리 검증 환경의 스크립트 경로. 반복 범위와 증거 재사용은 [공통 테스트 기준](../rules/common/testing.md)의 `담당과 반복 범위`를 따른다. 검사·캡처·검수 역할은 테스트 레벨 범위 안에서 정한다. 캡처·영상은 필요한 판정 항목과 연결하고, 레벨이 요구하는 후속 QA·ART 검수가 있으면 담당과 인계 조건을 적는다.
검사별 담당·대상·실행 시점·통과 조건을 적고 worker 완료와 제품 최종 수락을 구분한다. 하네스 제약도 적는다: FullOps lint 명령의 전체 경로·cwd·`--from <기준 SHA>`, 검증 증거 파일 형식(`.fullops-squad/` 아래 `.md`는 front matter 필수 — lint DOC-003, 원시 로그·캡처 텍스트는 `.txt`/`.log`), 재검토 리뷰의 base 조건(이전 리뷰 SHA의 후손), 원격·격리 검증 환경의 스크립트 경로, 로그·임시 산출물 위치(`.fullops-squad/local/`, 판정 증거는 `qa-reports/<과제 키>-test/`). 반복 범위와 증거 재사용은 [공통 테스트 기준](../rules/common/testing.md)의 `담당과 반복 범위`를 따른다. 검사·캡처·검수 역할은 테스트 레벨 범위 안에서 정한다. 캡처·영상은 필요한 판정 항목과 연결하고, 레벨이 요구하는 후속 QA·ART 검수가 있으면 담당과 인계 조건을 적는다.
worker는 이 조건을 모두 채울 때까지 중간 확인 없이 진행한다. 멈추고 묻는 경우는 `추가 승인이 필요한 행위`, 설명되지 않는 검증 실패, 제품 규칙 변경·범위 확대·공유 제품 기준의 불명확성이다. 제품/기술 책임 분리 레포의 DEV는 기술 계획·구조/API·버그 분석/수정을 같은 작업에서 수행하고 실제 구현에 맞게 기술 문서를 갱신한다.

### UI 작업의 디자인 기준과 검증
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ setup에서 이 레포를 직접 확인하고 채운다. 원본 템플릿의 기
| 제품 목적 | 미확정 |
| 기본 브랜치 | 미확정 — Git에서 조회 |
| 기술 스택·아키텍처 정본 | 미확정 — 기존 문서 연결 |
| 공통 개발 기준 | [rules/common/README.md](rules/common/README.md) — `fullops-common-0.3.5` |
| 공통 개발 기준 | [rules/common/README.md](rules/common/README.md) — `fullops-common-0.3.6` |
| 보안·코딩 규칙 | 미확정 — 기존 문서 연결 |
| 테스트·린트·빌드 명령 | 미확정 — 실행 가능한 명령과 실행 위치 기록. lint 명령은 `lint/lint.json`에 등록 |
| 문서 언어 | 한국어 |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# FullOps 공통 개발 규칙

규칙 묶음: `fullops-common-0.3.5`
규칙 묶음: `fullops-common-0.3.6`

## 적용

Expand All @@ -18,6 +18,10 @@

비밀값 보호, 승인 범위, 리뷰 수락 기준은 작업 지시서나 외부 스킬로 임의 완화하지 않는다. 미해결 critical/high가 있으면 기존 FullOps 리뷰 검사를 통과할 수 없다. 실제 충돌이나 예외는 지시서에 경로·이유·승인 필요 여부를 기록하고, 승인이 필요한 예외는 승인 전 적용하지 않는다.

## 작업 파일 위치

레포 작업에 쓰는 도구·검증 로그·임시 산출물은 레포 안 `.fullops-squad/local/`에 둔다. `.fullops-squad/.gitignore`가 이 폴더를 제외한다. 여러 워크트리가 함께 쓰는 도구(휴대용 Node·make 등)는 기본 체크아웃(`git rev-parse --git-common-dir`의 상위 폴더)의 `.fullops-squad/local/`에 둔다. 레포 밖(`%LOCALAPPDATA%`·`%TEMP%`·홈 디렉터리)에는 레포 전용 파일을 만들지 않는다. 호스트가 주는 세션 scratchpad는 그 세션에서만 쓰는 임시 파일에 쓴다. 예외가 필요하면 사용자 승인을 받은 뒤 경로·용도·정리 시점을 `project.md`에 기록한다. 과제 판정 증거는 [테스트](testing.md)의 `qa-reports` 규칙을 따른다.

## 전달과 검토

지시서의 `적용 기준과 예외`에 이 묶음의 식별자, 사용한 프로젝트 문서 경로와 기준 커밋을 적는다. 미커밋 문서는 명시한 스냅샷 경로로 식별한다. 규칙을 수정했다면 같은 식별자만으로 동일한 내용이라고 판단하지 않는다.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
- `full`: 안정된 통합 후보에서 전체 회귀와 필요한 통합·수락 검사를 담당자별로 한 번 수행한다.
- `exhaustive`: full에 프로젝트에 필요한 E2E·성능·장시간·환경 검수를 더해 안정된 후보에서 한 번 수행한다.

보안·데이터 손실 방지·프로젝트 필수 검사·독립 리뷰(`review.py need`가 필요로 판정한 변경)·최종 수락 조건은 모든 레벨에서 유지한다. 지시서는 레벨 밖의 검사·캡처 폭·테마·검수 역할을 더하지 않는다. 더 필요하면 레벨을 올리거나 사용자에게 묻는다. 완료 조건에 선택 레벨·검사 담당·대상·시점을 기록하고 통과 뒤에는 새 변경·실패·근거 결함이 있을 때만 재검증한다.
보안·데이터 손실 방지·프로젝트 필수 검사·독립 리뷰(`review.py need`가 필요로 판정한 변경)·최종 수락 조건은 모든 레벨에서 유지한다. 지시서는 레벨 밖의 검사·캡처 폭·테마·검수 역할을 더하지 않는다. 더 필요하면 레벨을 올리거나 사용자에게 묻는다. 사용자가 승인한 수락 기준(기획·의도 문서)이 명시한 캡처·판정은 레벨 기본값보다 우선한다. 지시서는 그 수락 기준을 근거로 적고, 보고서는 그 판정 때문에 길어져도 된다. 완료 조건에 선택 레벨·검사 담당·대상·시점을 기록하고 통과 뒤에는 새 변경·실패·근거 결함이 있을 때만 재검증한다.
lint.json의 test 명령에 최소 level을 명시하면 범위 밖 명령은 skipped와 사유를 남긴다. 레벨 없는 기존 명령과 required: true 명령은 항상 실행한다. 명시적 setup/update에서 실제 프로젝트 기준으로 전체 회귀의 level을 분류하고, 변경 경로용 기존 명령을 연결한다. 명령 문법·영향 범위를 추정하거나 기존 필수 검사를 낮추지 않는다. 기준 merge-base의 설정을 사용하며 검사 생략을 PASS로 보고하지 않는다.
<!-- fullops-mode:end -->

Expand All @@ -32,7 +32,7 @@ lint.json의 test 명령에 최소 level을 명시하면 범위 밖 명령은 sk

캡처는 시각 판정이 필요한 지정 항목에만 만든다. 영상은 모션·깜빡임·시간에 따른 변화처럼 정지 화면으로 판정할 수 없는 항목에만 만든다. 통합 후보마다 필요한 자료를 한 번 확보해 검수자와 공유하며, 자동 검사로 판정되는 값·상태는 실행 결과로 남긴다.

커밋하는 증거는 보고서의 판정 항목이 링크하는 파일만이다. 통과 항목의 캡처, 첫 실행 실패본, HTML·DOM 스냅샷, 완료 SHA 이전 중간 커밋의 gate 로그와 그 해시 목록은 `docs/evaluations/qa-reports/<과제 키>-test/raw/`에 둔다. 이 경로는 `.fullops-squad/.gitignore`가 제외한다. gate 로그(lint·test·integration)는 완료 SHA 1건만 보존한다. 같은 화면의 시각 검수 캡처는 지시서가 정한 검수 역할 하나(designer 또는 tester)가 만든다. 구현 담당자는 지시서가 자기 판정 항목으로 지정한 렌더만 만들고, 검수용 렌더를 대신 만들지 않는다. 증거를 만들려고 쓴 일회성 스크립트와 그 출력도 `raw/`에 둔다. 같은 과제의 수정·재검증·배포 확인은 새 보고서 폴더를 만들지 않고 기존 `report.md`에 절을 덧붙인다.
커밋하는 증거는 보고서의 판정 항목이 링크하는 파일만이다. 통과 항목의 캡처, 첫 실행 실패본, HTML·DOM 스냅샷, 완료 SHA 이전 중간 커밋의 gate 로그와 그 해시 목록은 `docs/evaluations/qa-reports/<과제 키>-test/raw/`에 둔다. 이 경로는 `.fullops-squad/.gitignore`가 제외한다. gate 로그(lint·test·integration)는 완료 SHA 1건만 보존한다. 같은 화면의 시각 검수 캡처는 지시서가 정한 검수 역할 하나(designer 또는 tester)가 만든다. 구현 담당자는 지시서가 자기 판정 항목으로 지정한 렌더만 만들고, 검수용 렌더를 대신 만들지 않는다. 증거를 만들려고 쓴 일회성 스크립트와 그 출력도 `raw/`에 둔다. 보고서는 `raw/`를 링크하지 않는다. 다른 과제에서 다시 쓸 검증 하네스(실행 스크립트·compose override·E2E 설정)는 `raw/`가 아니라 레포의 커밋되는 위치(예: `scripts/qa/`)에 두고, 비밀값 경로만 환경 변수로 받는다. 같은 과제의 수정·재검증·배포 확인은 새 보고서 폴더를 만들지 않고 기존 `report.md`에 절을 덧붙인다.

UI/UX 품질은 과제 단위가 아니라 통합 후보·마일스톤의 큰 틀 검수에서 판단한다. 판정 기준은 `docs/planning/intents/`의 성공 기준이다. 주요 사용자 흐름은 `docs/evaluations/scenarios/`의 고정 시나리오 세트로 유지해 통합 후보마다 다시 돌리고, 발견한 결함은 시나리오로 추가한다. 지정 담당은 그 흐름을 처음부터 끝까지 실행하며 화면 사이의 흐름·일관성·정보 구조를 함께 본다. 결과는 우선순위를 매긴 개선 목록 하나로 남기고, 다음 개선 과제는 그 목록을 범위로 여러 화면을 함께 바꾸게 배정한다. 캡처는 이 검수에서 판정에 쓴 화면만 남긴다.

Expand Down
2 changes: 1 addition & 1 deletion dist/directory/fullops-squad/plugin.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "fullops-squad",
"version": "1.8.5",
"version": "1.8.6",
"description": "Orca worker 핸드오버와 개발 산출물을 관리하는 레포별 선택형 하네스"
}
36 changes: 36 additions & 0 deletions dist/directory/fullops-squad/releases/1.8.6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 1.8.6 — 작은 원인으로 큰 비용이 드는 지점 줄이기, 작업 파일 위치 규칙

근거: jevpet UX3-A 작업 회고(#94), KnowsLink 레포 밖 작업 파일 15G(#95).

## 변경

### 반복 비용 줄이기 (#94)

- **기록만 바뀐 커밋은 lint를 다시 돌리지 않는다**: lint 통과 HEAD 뒤 커밋이 완료 기록·검증 보고(`.fullops-squad/handovers/`·`.fullops-squad/docs/evaluations/`)만 바꿨으면 done-gate가 이전 통과를 그대로 인정한다. 바뀐 기록의 front matter는 done-gate가 직접 검사한다(DOC-002·DOC-003). 산출물 문서·설정·코드가 바뀌었으면 지금처럼 lint를 다시 요구한다.
- **실행 순서 안내**: 작업 트리가 깨끗하지 않아 lint가 거절할 때 걸린 파일과 순서(구현 커밋 → lint → 완료 보고 → `work.py finish` → 커밋)를 함께 알린다. `fullops-work` 스킬에도 같은 순서를 적었다.
- **`raw/` 링크 알림**: qa-reports 보고서가 커밋하지 않는 `raw/`를 링크하면 쓴 직후 한 번 알린다. 막지는 않는다.
- **패킷 불일치 오류가 원인을 말한다**: `packet … identity differs`가 task·role·attempt·지시서 중 무엇이 다른지 표시하고, 지시서가 다르면 front matter(`status` 등)를 되돌리거나 패킷을 다시 만들라고 안내한다.
- **수락 기준 우선**: 사용자가 승인한 수락 기준이 명시한 캡처·판정은 테스트 레벨 기본값보다 우선한다. 보고서 길이 알림도 그 경우는 그대로 두라고 안내한다.

### 작업 파일 위치 (#95, fullops-common-0.3.6)

- 레포 작업에 쓰는 도구·검증 로그·임시 산출물은 레포 안 `.fullops-squad/local/`(gitignore)에 둔다. 여러 워크트리가 함께 쓰는 도구는 기본 체크아웃의 `.fullops-squad/local/`에 둔다. 레포 밖(`%LOCALAPPDATA%`·`%TEMP%`·홈)에는 레포 전용 파일을 만들지 않는다. 예외는 사용자 승인 뒤 `project.md`에 경로·용도·정리 시점을 기록한다.
- 다시 쓸 검증 하네스(실행 스크립트·compose override·E2E 설정)는 `raw/`가 아니라 레포의 커밋되는 위치(예: `scripts/qa/`)에 두고 비밀값 경로만 환경 변수로 받는다.
- 지시서 템플릿의 `완료 기준과 검증`에 로그·임시 산출물 위치를 적었다.

보류: 패킷 context 문서를 선택 항목으로 돌리는 안(#94-5)은 읽기 증거 계약을 약하게 해 보류한다. 레포 밖 쓰기를 감지하는 hook(#95-4)은 정상 설치·scratchpad와 구분이 어려워 넣지 않는다.

## 필수 적용

update-fullops는 이 절의 항목을 해당 없음·보류로 분류하지 않는다. `update.py --verify`가 통과해야 `plugin_version`을 1.8.6으로 올린다.

- 작업 파일 위치 규칙 — 확인: `.fullops-squad/rules/common/README.md`에 `작업 파일 위치`
- 작업 파일 폴더 제외 — 확인: `.fullops-squad/.gitignore`에 `local/`
- 수락 기준 우선·검증 하네스 위치 — 확인: `.fullops-squad/rules/common/testing.md`에 `검증 하네스`
- 지시서 템플릿의 작업 파일 위치 — 확인: `.fullops-squad/handovers/_TEMPLATE.md`에 `.fullops-squad/local/`

## 기존 레포 적용

- 위 필수 적용: setup은 기존 파일을 바꾸지 않는다. `rules/common/README.md`·`rules/common/testing.md`는 새 설치 패키지의 `assets/repository/.fullops-squad/rules/common/` 같은 파일과 비교해 통합한다(레포에서 고친 내용은 보존). `.fullops-squad/.gitignore`에 `local/` 두 줄을 더하고, `handovers/_TEMPLATE.md`의 `완료 기준과 검증` 문장을 새 판으로 바꾼다. `project.md`의 규칙 묶음 표기를 `fullops-common-0.3.6`으로 올린다. 끝나면 `update.py --verify`로 확인한다.
- 레포 밖에 이미 만든 작업 폴더가 있으면 `.fullops-squad/local/`로 옮기고 규칙 문서의 참조를 고친다. 원본 삭제는 사용자가 확인한 뒤 한다. 다른 경로(예: `.devtools/`)를 이미 쓰고 있으면 옮기는 대신 `project.md`에 예외로 기록해도 된다.
- 나머지(lint 재사용·알림·오류 문구)는 플러그인 업데이트 뒤 새 세션에서 적용된다.
22 changes: 20 additions & 2 deletions dist/directory/fullops-squad/scripts/done_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import subprocess
import sys

from lint import C_STYLE, CONFIG, DEFAULT, HASH, PY
from lint import C_STYLE, CONFIG, DEFAULT, HASH, PY, blob, deliverable_violations
import deliverables
import policy
from storage import write_json
Expand Down Expand Up @@ -128,6 +128,23 @@ def code(path):
return sorted(filter(code, committed)), sorted(filter(code, dirty))


RECORDS = ('.fullops-squad/handovers/', '.fullops-squad/docs/evaluations/')


def records_only(root, passed, head):
"""lint 통과 HEAD 뒤 커밋이 완료 기록·검증 보고만 바꿨는지. 그러면 명령 검사를 다시 돌리지 않고 문서 형식만 본다(#94)"""
try:
subprocess.run(['git', '-C', str(root), 'merge-base', '--is-ancestor', passed, head], check=True, capture_output=True)
changed = git(root, 'diff', '--name-only', passed, head).splitlines()
if not changed or not all(p.startswith(RECORDS) for p in changed):
return False
index = deliverables.index_rows(blob(root, head, '.fullops-squad/' + deliverables.INDEX) or '')
kept = git(root, 'diff', '--name-only', '--diff-filter=d', passed, head).splitlines()
return not any(deliverable_violations(p, blob(root, head, p) or '', index) for p in kept)
except (OSError, ValueError, subprocess.CalledProcessError):
return False


def expected_base(root, state):
roles = json.loads((root / '.fullops-squad/fullops.json').read_text()).get('roles', {})
branch = git(root, 'rev-parse', '--abbrev-ref', 'HEAD')
Expand Down Expand Up @@ -197,7 +214,8 @@ def main(event=None):
write_json(session, state) # 성공 Stop 뒤 finish가 인박스를 비워도 기준을 보존한다.
try:
record = json.loads((gate / 'pass.json').read_text())
passed = record.get('head') == head and (not expected or record.get('base') == expected)
passed = (not expected or record.get('base') == expected) and bool(record.get('head')) and (
record['head'] == head or records_only(root, record['head'], head))
except (OSError, ValueError, AttributeError):
passed = False
if passed and not dirty:
Expand Down
2 changes: 1 addition & 1 deletion dist/directory/fullops-squad/scripts/flow_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ def main(event=None):
state.pop('sending', None)
import harness_gate
command, files = targets(field(event, 'tool_input') or {})
notes = harness_gate.advice(root, files, config['test_level'], HANDOVER)
notes = harness_gate.advice(root, files, config['test_level'], HANDOVER) + harness_gate.raw_links(root, files)
if primary(root, state): # 흐름 그래프 경계 알림(docs/flow-graph.md E7·E11·E15)
notes += [n for n in [integration.merge_drift(root, shell_commands(command)),
harness_gate.repeat_budget(root, shell_commands(command))] if n]
Expand Down
23 changes: 22 additions & 1 deletion dist/directory/fullops-squad/scripts/harness_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,28 @@ def advice(root, files, level, handover_pattern):
lines = len(text.splitlines())
if lines > REPORT_LINES:
notes.append(f'보고서 {relative}가 {lines}줄입니다. 테스트 레벨 {level}의 보고서는 판정 항목과 결과 표, 실패·미실행·한계만 적고 '
'30줄 안팎으로 둡니다. 통과한 검사는 명령·SHA·종료코드 한 줄이면 됩니다.')
'30줄 안팎으로 둡니다. 통과한 검사는 명령·SHA·종료코드 한 줄이면 됩니다. 승인된 수락 기준이나 지시서가 요구한 판정 때문에 길어졌으면 그대로 둡니다.')
return notes


RAW_LINK = re.compile(r'\]\(\s*<?([^)\s>]+)')


def raw_links(root, files):
"""방금 쓴 qa-reports 보고서가 Git이 제외하는 `raw/`를 링크하면 알릴 문장(#94)"""
notes = []
for name, _ in files:
relative = _relative(root, name)
if not _folder(relative) or not relative.endswith('.md') or '/raw/' in relative:
continue
try:
text = (root / relative).read_text(encoding='utf-8')
except (OSError, UnicodeDecodeError):
continue
links = sorted({link for link in RAW_LINK.findall(text) if '://' not in link and re.search(r'(^|/)raw/', link)})
if links:
notes.append(f"보고서 {relative}가 커밋하지 않는 `raw/`를 링크합니다({', '.join(links[:3])}). 판정 근거면 파일을 보고서 폴더로 옮기고, "
'아니면 링크를 빼세요. 다른 체크아웃에서는 열리지 않습니다(rules/common/testing.md).')
return notes


Expand Down
Loading
Loading