Skill: virtual-ny/clawcolab (version 1.0.0)

--- name: clawcolab description: Coordinate multiple OpenClaw instances in a shared GitHub repository under a half-trust model with secrecy boundaries, approval gates, structured tasks, claims, handoffs, risks, and decision records. Use when users want secure multi-agent GitHub collaboration across people or devices without exposing private local memory, secrets, or unrestricted authority. --- # ClawColab Coordinate work through a shared GitHub repository without treating the repository as a full-context memory sync. Assume a **half-trust environment**: - Collaborate actively - Share only what is necessary - Do not assume every participant should see all local context - Do not export local memory, secrets, or private user context unless explicitly approved ## Core rules 1. **Classify before sharing** 2. **Default to non-sharing** 3. **Share the minimum necessary** 4. **Treat local memory and secrets as private by default** 5. **Do not promote visibility levels without approval** 6. **Record decisions and approvals explicitly** 7. **Prefer structured artifacts over freeform chat** ## First-use minimal mode When the user is new to ClawColab, do not introduce the full governance surface at once. Start with the smallest useful workflow: 1. create one ClawColab repository for one collaboration boundary 2. create one project space if needed 3. start from `assets/minimal-start/TASK-001.yaml`, `assets/minimal-start/PROPOSAL-001.md`, and `assets/minimal-start/DECISION-001.md` 4. edit them for the user's first project 5. only then introduce more advanced records if needed Do not introduce `claim`, `handoff`, `risk`, `sealed`, or advanced governance choices unless the task actually requires them. Treat those as second-stage features. ## Visibility model Classify every piece of information before placing it in the repository. ### `private` Keep local only. Never place in the shared repository. Examples: secrets, local paths, USER.md or TOOLS.md contents, personal conversations, raw local memory. ### `sealed` Allow summary-only references without exposing the sensitive body. Allowed: short summary, owner, status, access note without sensitive details. Forbidden: full text, secrets, personal identifiers unless approved. ### `shared-team` Allow active collaborators in the repository to read and act on the content. Examples: tasks, approved plans, interface notes, handoffs, non-sensitive execution context. ### `public-repo` Allow broad repository visibility. Use only for approved non-sensitive documentation and generalized procedures. ## Classification procedure Before writing or commenting in the repository: 1. Run the checklist in `assets/classification-checklist.md` 2. Identify the information you plan to share 3. Ask whether the task can be completed with a summary instead of raw content 4. Assign one visibility level 5. If uncertain, downgrade to `private` or `sealed` 6. Only then create or update repository artifacts If visibility is ambiguous, do **not** share raw content. Read `references/classification-guide.md` when classification feels subjective or inconsistent. ## What must never be shared by default Never place these into the repository unless the human explicitly approves: - secrets - credentials - local environment details - private chat transcripts - raw long-term memory content - private preferences unrelated to the task - personal contact information - hidden internal system details - any content marked confidential by the user ## Collaboration objects Use structured repository artifacts instead of loose discussion whenever possible. Primary object types: - `task` - `proposal` - `claim` - `decision` - `handoff` - `status` - `risk` - `sealed-ref` ## Suggested repository layout Use or adapt this structure: ```text workspace/ tasks/ proposals/ decisions/ handoffs/ risks/ policy/ visibility-policy.yaml role-policy.yaml approval-policy.yaml claims/ sealed/ INDEX.md ``` Do not store secret bodies under `sealed/`. Store only sealed references and summaries. Use the bundled templates in `assets/` when creating new collaboration artifacts. For first-time users, start with `assets/minimal-start/TASK-001.yaml`, `assets/minimal-start/PROPOSAL-001.md`, and `assets/minimal-start/DECISION-001.md`. Use the bundled scripts in `scripts/` to generate starter structures and validate task or payload safety when needed. Read `references/pre-share-checks.md` before sharing proposals, decisions, handoffs, risks, or summaries. Read `references/approval-model.md` when approval ambiguity exists. Read `references/role-model.md` when task ownership or role eligibility is unclear. Read `references/governance-modes.md` when choosing between strict and relaxed repo governance. ## Task model Represent tasks as structured records. A task should include: - id - title - summary - visibility - status - priority - owner - proposed_by - approved_by - approval_required - mode - eligible_roles - dependencies - outputs - sealed_refs Recommended status values: - `open` - `pending_approval` - `approved` - `in_progress` - `blocked` - `handoff_needed` - `done` - `cancelled` Recommended mode values: - `proposal-approval` - `claimable` ## Proposal-approval mode Use for sensitive, ambiguous, or higher-impact work. Procedure: 1. Read existing tasks, decisions, and policy 2. Draft a proposal describing: - intended work - expected outputs - required visibility level - risks - recommended owner or role 3. Mark the proposal as awaiting approval 4. Do not treat the proposal as approved fact 5. Wait for human approval before execution when required Use proposal-approval mode by default unless the repo policy clearly allows autonomous claiming. ## Claimable mode Use only when repository policy allows task claiming and the task is explicitly marked `mode: claimable`. Treat `proposal-approval` as the default for all other work. Before claiming: 1. Confirm the task is `open` 2. Confirm your role is eligible 3. Confirm the task is low risk and not policy-sensitive, visibility-sensitive, or ownership-sensitive 4. Confirm the task is not marked `approval_required: true`, unless approval policy explicitly allows a pending claim state 5. Confirm no conflicting approved owner exists 6. Confirm the task does not require access to private or sealed body content you do not have approval to use 7. Confirm `policy/role-policy.yaml` and `policy/approval-policy.yaml` do not block the claim Then: 1. Create a claim record or update the task according to repo convention 2. State why you are eligible 3. Move the task to `in_progress` only if policy permits automatic claiming 4. Otherwise move it to `pending_approval` If there is a conflict, do not silently override another agent. Record the conflict and request adjudication. High-risk or policy-adjacent work should default to `proposal-approval`. ## Role model Use simple roles to guide task assignment. Suggested roles: - `coordinator` - `architect` - `implementer` - `reviewer` - `security-reviewer` - `researcher` - `documenter` - `human-approver` Read `policy/role-policy.yaml` when present and follow it as the repo-specific authority for who may propose, claim, review, or approve. Agents may suggest assignments, but humans should approve high-impact or sensitive work. Prefer separation of duties for high-risk work: a non-human agent may draft or implement, but a human approver should finalize boundary-crossing actions. ## Human approval gates Read `policy/approval-policy.yaml` when present and follow it as the repo-specific gate definition. Require human approval before: - raising visibility from `private` or `sealed` to a broader level - executing high-impact tasks - resolving role conflicts in sensitive work - publishing final decisions that affect others - sharing content derived from private local memory - assigning ownership for sensitive workstreams - merging proposals into authoritative policy - changing `policy/visibility-policy.yaml`, `policy/role-policy.yaml`, or `policy/approval-policy.yaml` Treat visibility promotion as blocked unless an explicit decision record exists first. Use `assets/visibility-promotion-decision-template.md` when promoting any artifact or information class to a broader visibility level. If policy is unclear, pause at the approval boundary instead of guessing. ## Default pre-share workflow Before writing a proposal, decision, handoff, risk, or shared summary: 1. run the classification checklist 2. run `scripts/validate-collab-payload.py` on the artifact when possible 3. check whether approval is required 4. if visibility is being promoted, require a decision record first 5. only then commit or propose the change ## Decision, handoff, risk, and sealed records Use explicit records instead of burying meaning in chat or comments. ### Decision Include: title, status, approver, source proposal, final decision, rationale, scope, and effective reference. ### Handoff Include: from, to, task id, current status, completed work, remaining work, risks, and referenced artifacts. ### Risk Create a risk record when secrecy is unclear, metadata may leak, claims conflict, or dependencies are under-specified. Include severity, description, mitigations, and escalation path. ### Sealed reference Include only id, title, owner, summary, status, access note, and related tasks. Never include secret values or protected body content. ## GitHub workflow guidance Prefer this pattern: - Propose work in `workspace/proposals/` or PR descriptions - Track active work in `workspace/tasks/` - Record approved outcomes in `workspace/decisions/` - Record partial transfers in `workspace/handoffs/` - Record safety or execution concerns in `workspace/risks/` Use branches conservatively, for example: - `proposal/...` - `task/...` - `review/...` Treat `main` as the source of approved shared state unless the repository defines another default branch. ## Communication style inside the repository Be structured and explicit. Prefer: - exact scope - exact visibility - exact state - exact owner - explicit approval status Avoid: - vague promises - implied approvals - dumping large local context - casual mention of sensitive facts - mixing sealed information into shared documents ## Minimal-share rule When contributing, ask: - Can this be reduced to a summary? - Can this be expressed as a task instead of a raw dump? - Can I refer to a sealed item instead of quoting it? - Does the next agent need this exact detail, or only the outcome? If the exact detail is not necessary, do not include it. ## Conflict handling If multiple agents disagree: 1. Record the disagreement 2. Link the affected task or proposal 3. Summarize each option neutrally 4. Identify whether the disagreement is technical, security-related, or procedural 5. Escalate to a human approver when required Do not invent consensus. ## Failure handling If you cannot complete a task safely: - stop before exposing unsafe content - write a concise status or risk update - request approval or clarification - preserve enough context for the next agent to continue safely Do not “helpfully” over-share to compensate for uncertainty. ## Success criteria A collaboration run is successful when: - work is coordinated through repository artifacts - sensitive local context remains local unless explicitly approved - proposals become decisions through explicit approval - handoffs are traceable - task ownership is clear - claimable work remains within policy - the repository contains actionable shared state without becoming a dump of private context

path: references/examples.md
content: # Examples

## Example 1: Sensitive planning note
A local agent has confidential customer input that affects priority.

Safe approach:
- Keep customer details `private`.
- Add a `sealed-ref` noting that confidential priority input exists.
- Create a `task` for a sanitized prioritization proposal.

## Example 2: Claimable low-risk documentation update
A repo policy allows claimable documentation work.

Safe approach:
- Verify the task is `open` and low risk.
- Submit a `claim`.
- Move the task to `in_progress` if policy permits.
- Commit the documentation update and close with status.

## Example 3: Conflicting agent ownership
Two agents want the same implementation task.

Safe approach:
- Record both claim attempts.
- Do not overwrite ownership silently.
- Create or update a `risk` item.
- Wait for human adjudication if policy does not resolve the conflict.


path: references/governance-modes.md
content: # Governance Modes

## Strict Mode
Use when participants are cross-org, the repo contains sensitive project structure, or approvals must be explicit.

Characteristics:
- default gate is human approval
- all visibility promotion requires approval
- medium-risk work requires explicit approval
- claimable mode is limited to low-risk work
- security reviewer is required for high-risk tasks

## Relaxed Mode
Use when collaborators are from the same trusted small team and tasks are operational rather than sensitive.

Characteristics:
- low-risk claimable work can proceed automatically
- medium-risk work may proceed if role policy allows and no secrecy boundary changes
- policy changes and public releases still require human approval

## Recommendation
Start in strict mode. Relax only after the collaboration patterns are stable and leakage risks are well understood.


path: references/privacy-review.md
content: # Privacy Review

## Result
No secrets, tokens, private keys, personal contact details, or user-specific memory exports are included in the `clawcolab` skill package.

## Review scope
- `SKILL.md`
- `assets/`
- `references/`
- `scripts/`

## Notes
- Templates use placeholder values only.
- Repository examples and local sandboxes are outside the skill folder and are not part of the packaged skill.
- Workflow templates may require path adjustment depending on how adopters install the skill into their own repositories.

## Publication recommendation
Safe to package and share as a skill, subject to a final validation build.


path: references/release-notes.md
content: # Release Notes

## ClawColab v1.0.0
Initial public release for a GitHub-native, half-trust collaboration skill for multiple OpenClaw instances.

### Included
- visibility model: `private`, `sealed`, `shared-team`, `public-repo`
- structured collaboration objects: task, proposal, decision, handoff, risk, claim
- approval and role policy templates
- validation and template-generation scripts
- GitHub workflow template for repository validation

### Intended use
Use when multiple OpenClaw instances need to collaborate through a shared GitHub repository with explicit secrecy boundaries, approval gates, auditable decisions, and structured task coordination.


path: references/task-lifecycle.md
content: # Task Lifecycle

## States
- `open`
- `pending_approval`
- `approved`
- `in_progress`
- `blocked`
- `handoff_needed`
- `done`
- `cancelled`

## Proposal-Approval Flow
`open -> pending_approval -> approved -> in_progress -> done`

## Claimable Flow
`open -> in_progress -> done`

Use `open -> pending_approval -> in_progress` when claim requests exist but policy requires review.

## Blocked Work
Move to `blocked` when a task cannot proceed safely or lacks required approval.
Create a `risk` record when the block involves ambiguity or policy conflict.

## Handoff
Move to `handoff_needed` when the next step should transfer to another role or agent.
Add a handoff artifact before clearing ownership.

## Claimable Guardrails
Use `claimable` only for low-risk work with explicit `mode: claimable`.
Do not use `claimable` for policy work, visibility promotion, sensitive ownership changes, or high-risk tasks.
If any of those apply, use `proposal-approval` instead.


path: references/classification-guide.md
content: # Classification Guide

## Purpose
Reduce classification drift between agents by using a repeatable pre-share process.

## Default rule
When uncertain, downgrade classification rather than widening visibility.

## Quick interpretation
- `private`: local-only, never commit
- `sealed`: summary-only reference, no sensitive body content
- `shared-team`: approved team-visible collaboration content
- `public-repo`: approved broadly visible repo content

## Common decision rule
If the exact content is not required for someone else to act, prefer `sealed` or `private` over a broader level.

## Reminder
Classification is not complete until the checklist in `assets/classification-checklist.md` has been answered.


path: references/publish-checklist.md
content: # Publish Checklist

- Confirm `SKILL.md` is concise and accurately scoped.
- Confirm `references/privacy-review.md` has no unresolved concerns.
- Confirm templates contain placeholders only.
- Confirm validation scripts run successfully.
- Confirm the packaged `.skill` contains only files inside `skills/clawcolab/`.
- Confirm release notes reflect the current version and scope.


path: references/github-workflow.md
content: # GitHub Workflow

## Branching
Recommended branch patterns:
- `proposal/...`
- `task/...`
- `review/...`

Treat the default branch as approved shared state.

## Files vs Issues vs PRs
- Use files in `workspace/` for durable structured state.
- Use Issues for discussion, escalation, and cross-cutting tracking.
- Use PRs for proposed changes that require review or approval.

## Suggested Flow
1. Create or update a task.
2. Draft a proposal if approval is required.
3. Open a PR or commit proposal artifacts.
4. Wait for human approval where required.
5. Merge approved outputs into the default branch.
6. Record the final decision if it changes policy or future work.

## Review Expectations
Every change should make these items obvious:
- visibility level
- owner or requester
- approval status
- affected task IDs

## Audit Expectations
Use commit messages, PR descriptions, and decision files so future reviewers can answer:
- who proposed the change
- who approved the change
- which task or proposal it belongs to
- whether the change affected policy, execution, or risk posture


path: references/role-model.md
content: # Role Model

## Purpose
Use roles to limit who may propose, claim, review, or approve work.

## Suggested Roles
- `coordinator`: keeps work moving and aligns ownership
- `architect`: designs structure, interfaces, and policy-aware plans
- `implementer`: executes approved technical work
- `reviewer`: reviews quality and completeness
- `security-reviewer`: reviews secrecy, policy, and leakage risk
- `researcher`: gathers and summarizes non-sensitive inputs
- `documenter`: updates docs and handoff artifacts
- `human-approver`: approves policy, secrecy, and high-impact changes

## Separation of Duties
Prefer not to let the same non-human role both propose and finalize sensitive work.
For high-risk tasks, require a security-reviewer plus a human-approver before treating work as final.

## Claim Rules
An agent may claim work only if:
- the task mode allows claiming
- the role policy allows claiming
- the task is open and not reserved
- no higher approval gate blocks execution

## Approval Rules
Only the `human-approver` role should approve:
- policy changes
- visibility promotions
- sensitive ownership changes
- final publication to `public-repo`


path: references/approval-model.md
content: # Approval Model

## Purpose
Use explicit approval gates so half-trust collaboration stays reviewable and does not drift into implicit authority.

## Core Principle
Agents may propose, draft, claim, and review within policy. Humans approve boundary-crossing actions.

## Mandatory Human Approval
Require human approval for:
- any visibility promotion
- any policy change
- any high-risk task execution
- any public-repo release
- any conflict involving sensitive ownership or secrecy boundaries

## Conditional Approval
Allow policy-controlled automation only when all of these are true:
- the task is marked low risk
- the task mode is `claimable`
- the role policy permits the agent to claim it
- no unresolved claim conflict exists
- no secrecy boundary is crossed

## Review Matrix
- Low-risk claimable work: may proceed automatically if policy allows
- Medium-risk work: require explicit repo policy rule or human approval
- High-risk work: require human approval and security review
- Policy changes: require human approval
- Public release changes: require human approval

## Approval Artifacts
Use one or more of the following as the authoritative approval record:
- merged PR with explicit approval note
- decision file
- approved issue comment if the repo policy accepts it

If approval is not recorded, treat it as not approved.


path: references/pre-share-checks.md
content: # Pre-Share Checks

Before creating or updating any shared artifact:

1. Run the classification checklist.
2. If content will enter the repository, run the payload scan.
3. Check whether approval is required.
4. If visibility is being promoted, require an explicit decision record first.
5. Only then write or update the artifact.

## Applies by default to
- proposals
- decisions
- handoffs
- risks
- shared summaries


path: references/security-model.md
content: # Security Model

## Purpose
Use a half-trust model for collaboration in shared GitHub repositories.

## Assumptions
- Participants may cooperate without sharing all local context.
- Repository content is a coordination layer, not a full memory sync.
- All content should be reduced to the minimum required to complete shared work.

## Visibility Levels
- `private`: Keep local only.
- `sealed`: Share existence and summary without body content.
- `shared-team`: Share with active collaborators.
- `public-repo`: Safe for broader repository visibility.

## Promotion Rules
- `private -> sealed/shared-team/public-repo`: require human approval.
- `sealed -> shared-team/public-repo`: require human approval.
- `shared-team -> public-repo`: require human approval unless policy explicitly says otherwise.

## Forbidden Content
Do not place the following in the shared repo by default:
- credentials and secrets
- private chat logs
- raw local memory
- personal identifiers not needed for the task
- local hostnames, SSH aliases, or machine-specific access notes

## Safe Reduction Patterns
Prefer:
- summaries over raw logs
- task statements over memory dumps
- sealed references over confidential text
- outputs and decisions over background chatter


path: references/message-types.md
content: # Message Types

## task
Define a unit of work with owner, state, visibility, and outputs.

## proposal
Request approval for work, structure, ownership, or policy changes.

## claim
Record an agent's request to take ownership of claimable work.

## decision
Record an approved conclusion that governs future work.

## handoff
Transfer partial work or blocked context to another agent or role.

## status
Provide a concise progress update tied to a task or proposal.

## risk
Record ambiguity, leakage risk, policy conflict, or execution risk.

## sealed-ref
Reference sensitive context by summary only.

## Naming Guidance
Use stable IDs such as:
- `TASK-001`
- `PROPOSAL-001`
- `DECISION-001`
- `HANDOFF-001`
- `RISK-001`


path: scripts/validate-collab-payload.py
content: #!/usr/bin/env python3
import argparse
import re
import sys
from pathlib import Path

SUSPICIOUS_PATTERNS = {
    "api_key": re.compile(r"(?i)(api[_-]?key|secret[_-]?key)\s*[:=]\s*\S+"),
    "token": re.compile(r"(?i)(token|bearer)\s*[:=]\s*\S+"),
    "password": re.compile(r"(?i)password\s*[:=]\s*\S+"),
    "private_key": re.compile(r"-----BEGIN (RSA|EC|OPENSSH|DSA)? ?PRIVATE KEY-----"),
    "ssh_alias": re.compile(r"(?im)^\s*host\s+\S+\s*$"),
}


def scan_text(text: str):
    findings = []
    for name, pattern in SUSPICIOUS_PATTERNS.items():
        for match in pattern.finditer(text):
            snippet = match.group(0)[:160].replace("\n", " ")
            findings.append((name, snippet))
    return findings


def main():
    parser = argparse.ArgumentParser(description="Scan collaboration payloads for likely sensitive content.")
    parser.add_argument("paths", nargs="+", help="Files to scan")
    args = parser.parse_args()

    total = 0
    for raw in args.paths:
        path = Path(raw)
        if not path.exists() or not path.is_file():
            print(f"SKIP {path}: not a file", file=sys.stderr)
            continue
        text = path.read_text(encoding="utf-8", errors="ignore")
        findings = scan_text(text)
        if findings:
            print(f"FAIL {path}")
            for name, snippet in findings:
                print(f"  - {name}: {snippet}")
            total += len(findings)
        else:
            print(f"OK   {path}")

    return 1 if total else 0


if __name__ == "__main__":
    raise SystemExit(main())


path: scripts/generate_clawcolab_templates.py
content: #!/usr/bin/env python3
import argparse
import shutil
from pathlib import Path

FILES = {
    'assets/task-template.yaml': 'workspace/tasks/TASK-001.yaml',
    'assets/proposal-template.md': 'workspace/proposals/PROPOSAL-001.md',
    'assets/decision-template.md': 'workspace/decisions/DECISION-001.md',
    'assets/handoff-template.md': 'workspace/handoffs/HANDOFF-001.md',
    'assets/risk-template.md': 'workspace/risks/RISK-001.md',
    'assets/claim-template.yaml': 'workspace/claims/CLAIM-001.yaml',
    'assets/visibility-policy-template.yaml': 'workspace/policy/visibility-policy.yaml',
    'assets/role-policy-template.yaml': 'workspace/policy/role-policy.yaml',
    'assets/approval-policy-template.yaml': 'workspace/policy/approval-policy.yaml',
}


def main():
    parser = argparse.ArgumentParser(description='Generate a sample ClawColab repository structure from bundled templates.')
    parser.add_argument('destination', help='Destination directory')
    args = parser.parse_args()

    skill_dir = Path(__file__).resolve().parent.parent
    dest = Path(args.destination).resolve()
    dest.mkdir(parents=True, exist_ok=True)
    (dest / 'sealed').mkdir(exist_ok=True)

    for src_rel, dest_rel in FILES.items():
        src = skill_dir / src_rel
        out = dest / dest_rel
        out.parent.mkdir(parents=True, exist_ok=True)
        shutil.copyfile(src, out)
        print(f'WROTE {out}')

    index = dest / 'sealed' / 'INDEX.md'
    if not index.exists():
        index.write_text('- id: sealed-001\n  title: Example sealed reference\n  owner: replace-me\n  summary: Replace with a summary-only sealed note.\n  status: exists\n', encoding='utf-8')
        print(f'WROTE {index}')


if __name__ == '__main__':
    main()


path: scripts/detect_claim_conflicts.py
content: #!/usr/bin/env python3
import argparse
import re
import sys
from collections import defaultdict
from pathlib import Path


def scan_file(path: Path):
    text = path.read_text(encoding='utf-8', errors='ignore')
    task_id = None
    agent = None
    for line in text.splitlines():
        if line.startswith('task_id:'):
            task_id = line.split(':', 1)[1].strip()
        elif line.startswith('agent:'):
            agent = line.split(':', 1)[1].strip()
    if not task_id:
        m = re.search(r'TASK-\d+', text)
        if m:
            task_id = m.group(0)
    return task_id, agent or path.stem


def main():
    parser = argparse.ArgumentParser(description='Detect multiple claims for the same task.')
    parser.add_argument('paths', nargs='+')
    args = parser.parse_args()
    claims = defaultdict(list)
    for raw in args.paths:
        path = Path(raw)
        task_id, agent = scan_file(path)
        if task_id:
            claims[task_id].append((agent, path))
    conflict = False
    for task_id, items in sorted(claims.items()):
        if len(items) > 1:
            conflict = True
            print(f'CONFLICT {task_id}')
            for agent, path in items:
                print(f'  - {agent}: {path}')
        else:
            agent, path = items[0]
            print(f'OK {task_id}: {agent} ({path})')
    return 1 if conflict else 0


if __name__ == '__main__':
    raise SystemExit(main())


path: scripts/validate_policy_bundle.py
content: #!/usr/bin/env python3
import argparse
from pathlib import Path

REQUIRED_VISIBILITY = {'private', 'sealed', 'shared-team', 'public-repo'}
REQUIRED_ROLES = {'coordinator', 'architect', 'implementer', 'reviewer', 'security-reviewer', 'human-approver'}
REQUIRED_APPROVAL_KEYS = {'visibility_promotion', 'task_execution', 'ownership_changes', 'policy_changes'}


def parse_simple_yaml(text):
    data = {}
    stack = [(-1, data)]
    for raw_line in text.splitlines():
        if not raw_line.strip() or raw_line.lstrip().startswith('#'):
            continue
        indent = len(raw_line) - len(raw_line.lstrip(' '))
        line = raw_line.strip()
        while stack and indent <= stack[-1][0]:
            stack.pop()
        if line.startswith('- '):
            continue
        if ':' not in line:
            continue
        key, value = line.split(':', 1)
        key = key.strip()
        value = value.strip()
        parent = stack[-1][1]
        if value == '':
            parent[key] = {}
            stack.append((indent, parent[key]))
        else:
            parent[key] = value
    return data


def validate_visibility(path: Path):
    data = parse_simple_yaml(path.read_text(encoding='utf-8', errors='ignore'))
    errs = []
    levels = set(data.get('levels', {}).keys())
    missing = REQUIRED_VISIBILITY - levels
    if missing:
        errs.append(f'missing visibility levels: {sorted(missing)}')
    if data.get('promotion_requires_decision_record') != 'true':
        errs.append('promotion_requires_decision_record should be true')
    return errs


def validate_roles(path: Path):
    data = parse_simple_yaml(path.read_text(encoding='utf-8', errors='ignore'))
    errs = []
    roles = set(data.get('roles', {}).keys())
    missing = REQUIRED_ROLES - roles
    if missing:
        errs.append(f'missing roles: {sorted(missing)}')
    human = data.get('roles', {}).get('human-approver', {})
    if human.get('can_approve') != 'true':
        errs.append('human-approver must have can_approve: true')
    constraints = data.get('constraints', {})
    if constraints.get('security_reviewer_required_for_high_risk') == 'true' and 'security-reviewer' not in roles:
        errs.append('security-reviewer role required for high risk but missing')
    return errs


def validate_approval(path: Path):
    data = parse_simple_yaml(path.read_text(encoding='utf-8', errors='ignore'))
    errs = []
    rules = set(data.get('approval_rules', {}).keys())
    missing = REQUIRED_APPROVAL_KEYS - rules
    if missing:
        errs.append(f'missing approval rule groups: {sorted(missing)}')
    task_exec = data.get('approval_rules', {}).get('task_execution', {})
    if task_exec.get('high_risk') != 'human-approval':
        errs.append('high_risk task execution must be human-approval')
    if task_exec.get('medium_risk') != 'human-approval':
        errs.append('medium_risk task execution should default to human-approval')
    req = data.get('claimable_requirements', {})
    if req.get('risk_level_must_be') != 'low':
        errs.append('claimable_requirements.risk_level_must_be should be low')
    if req.get('explicit_mode_required') != 'true':
        errs.append('claimable_requirements.explicit_mode_required should be true')
    return errs


def main():
    parser = argparse.ArgumentParser(description='Validate a ClawColab policy bundle.')
    parser.add_argument('visibility_policy')
    parser.add_argument('role_policy')
    parser.add_argument('approval_policy')
    args = parser.parse_args()
    checks = [
        (Path(args.visibility_policy), validate_visibility),
        (Path(args.role_policy), validate_roles),
        (Path(args.approval_policy), validate_approval),
    ]
    failed = False
    for path, func in checks:
        if not path.exists():
            print(f'FAIL {path}\n  - file does not exist')
            failed = True
            continue
        errs = func(path)
        if errs:
            failed = True
            print(f'FAIL {path}')
            for err in errs:
                print(f'  - {err}')
        else:
            print(f'OK   {path}')
    return 1 if failed else 0


if __name__ == '__main__':
    raise SystemExit(main())


path: scripts/validate_task_state.py
content: #!/usr/bin/env python3
import argparse
from pathlib import Path

ALLOWED_STATUS = {'open','pending_approval','approved','in_progress','blocked','handoff_needed','done','cancelled'}
ALLOWED_MODE = {'proposal-approval','claimable'}
ALLOWED_RISK = {'low','medium','high'}
REQUIRED_KEYS = ['id','title','visibility','status','mode','approval_required','risk_level']


def parse_simple_yaml(text):
    data = {}
    for line in text.splitlines():
        if not line.strip() or line.lstrip().startswith('#'):
            continue
        if line.startswith(' ') or line.startswith('\t'):
            continue
        if ':' not in line:
            continue
        k, v = line.split(':', 1)
        data[k.strip()] = v.strip()
    return data


def validate(path: Path):
    data = parse_simple_yaml(path.read_text(encoding='utf-8', errors='ignore'))
    errors = []
    warnings = []
    for key in REQUIRED_KEYS:
        if key not in data:
            errors.append(f'missing key: {key}')
    status = data.get('status')
    mode = data.get('mode')
    risk = data.get('risk_level')
    if status and status not in ALLOWED_STATUS:
        errors.append(f'invalid status: {status}')
    if mode and mode not in ALLOWED_MODE:
        errors.append(f'invalid mode: {mode}')
    if risk and risk not in ALLOWED_RISK:
        errors.append(f'invalid risk_level: {risk}')
    if data.get('approval_required') not in {'true','false'}:
        errors.append('approval_required must be true or false')
    if data.get('mode') == 'claimable' and data.get('risk_level') != 'low':
        errors.append('claimable tasks must have risk_level: low')
    if data.get('mode') == 'claimable' and data.get('approval_required') == 'true':
        errors.append('claimable tasks should not require approval; use proposal-approval instead')
    outputs = data.get('outputs', '')
    if 'policy/' in outputs:
        errors.append('tasks that change policy outputs must not be treated as ordinary task outputs')
    if 'demo_space' not in data:
        warnings.append('missing demo_space (recommended for project scoping)')
    if 'priority' not in data:
        warnings.append('missing priority')
    return errors, warnings


def main():
    parser = argparse.ArgumentParser(description='Validate basic ClawColab task file state.')
    parser.add_argument('paths', nargs='+')
    args = parser.parse_args()
    failed = False
    for raw in args.paths:
        path = Path(raw)
        errs, warns = validate(path)
        if errs:
            failed = True
            print(f'FAIL {path}')
            for err in errs:
                print(f'  - {err}')
        else:
            print(f'OK   {path}')
        for warn in warns:
            print(f'WARN {path}: {warn}')
    return 1 if failed else 0


if __name__ == '__main__':
    raise SystemExit(main())


path: assets/task-template.yaml
content: id: TASK-XXX
title: Replace with concise task title
summary: Replace with a short execution-oriented summary.
demo_space: replace-with-project-space-or-null
visibility: shared-team
status: open
priority: medium
mode: proposal-approval
approval_required: true
risk_level: medium
owner: null
proposed_by: agent-name
approved_by: null
eligible_roles:
  - coordinator
  - architect
dependencies: []
inputs: []
outputs: []
sealed_refs: []
risks: []
notes: |
  Add any additional context that is safe at the selected visibility level.


path: assets/decision-template.md
content: # DECISION-XXX

## Title
Replace with decision title

## Status
approved

## Approved By
Human name

## Based On
- PROPOSAL-XXX

## Scope
Describe what this decision governs.

## Decision
State the final approved decision clearly.

## Rationale
Explain why this decision was chosen.

## Effective Reference
Commit, PR, date, or branch reference.


path: assets/risk-template.md
content: # RISK-XXX

## Title
Replace with risk title

## Severity
medium

## Affected Tasks
- TASK-XXX

## Description
Describe the risk and why it matters.

## Potential Impact
Describe failure mode or leakage risk.

## Mitigations
- Mitigation 1
- Mitigation 2

## Escalation Path
State who must review or approve the next step.


path: assets/handoff-template.md
content: # HANDOFF-XXX

## From
agent-name

## To
agent-name or role

## Task
TASK-XXX

## Status
partial

## Completed Work
- Item 1

## Remaining Work
- Item 1

## Risks
- Item 1

## Shared Artifacts
- `path/to/artifact`

## Sealed References
- sealed-xxx


path: assets/role-policy-template.yaml
content: version: 1
roles:
  coordinator:
    can_propose: true
    can_claim: true
    can_review: true
    can_approve: false
    allowed_task_modes:
      - proposal-approval
      - claimable
  architect:
    can_propose: true
    can_claim: true
    can_review: true
    can_approve: false
    allowed_task_modes:
      - proposal-approval
      - claimable
  implementer:
    can_propose: true
    can_claim: true
    can_review: false
    can_approve: false
    allowed_task_modes:
      - claimable
      - proposal-approval
  reviewer:
    can_propose: true
    can_claim: false
    can_review: true
    can_approve: false
    allowed_task_modes:
      - proposal-approval
  security-reviewer:
    can_propose: true
    can_claim: false
    can_review: true
    can_approve: false
    allowed_task_modes:
      - proposal-approval
  researcher:
    can_propose: true
    can_claim: true
    can_review: false
    can_approve: false
    allowed_task_modes:
      - claimable
      - proposal-approval
  documenter:
    can_propose: true
    can_claim: true
    can_review: false
    can_approve: false
    allowed_task_modes:
      - claimable
  human-approver:
    can_propose: true
    can_claim: false
    can_review: true
    can_approve: true
    allowed_task_modes:
      - proposal-approval
      - claimable
constraints:
  only_human_approver_may_promote_visibility: true
  only_human_approver_may_finalize_policy_changes: true
  security_reviewer_required_for_high_risk: true


path: assets/claim-template.yaml
content: task_id: TASK-XXX
agent: agent-name
action: claim
timestamp: 2026-03-12T01:00:00-04:00
role: implementer
justification: Explain why this agent is eligible to claim the task.
visibility: shared-team
requested_state: pending_approval


path: assets/visibility-policy-template.yaml
content: version: 1
default_visibility: private
levels:
  private:
    description: Keep local only. Never commit to the shared repository.
    approval_required_to_promote: true
  sealed:
    description: Allow summary-only references in the repository without sensitive body content.
    approval_required_to_promote: true
  shared-team:
    description: Allow repository-visible collaboration for approved participants.
    approval_required_to_promote: true
  public-repo:
    description: Allow broad visibility within the repository audience.
    approval_required_to_promote: true
promotion_requires_decision_record: true
forbidden_shared_content:
  - secrets
  - credentials
  - local-memory-raw-content
  - private-chat-transcripts
  - personal-contact-information
modes:
  default: proposal-approval
  allow_claimable_for_low_risk: true
claim_rules:
  require_role_match: true
  require_open_status: true
  block_when_approval_required: true


path: assets/proposal-template.md
content: # PROPOSAL-XXX

## Title
Replace with proposal title

## Status
pending_approval

## Visibility
shared-team

## Proposed By
agent-name

## Scope
Describe the intended work and boundaries.

## Proposed Actions
- Action 1
- Action 2

## Expected Outputs
- `path/to/output`

## Risks
- Risk 1

## Requested Owner or Role
- security-reviewer

## Approval Needed
Describe what the human approver is being asked to approve.


path: assets/visibility-promotion-decision-template.md
content: # DECISION-XXX

## Title
Approve visibility promotion

## Status
approved

## Approved By
Human name

## Based On
- PROPOSAL-XXX

## Scope
Define a visibility promotion for a specific artifact or information class.

## Promotion
- from: private | sealed | shared-team
- to: sealed | shared-team | public-repo

## Decision
State exactly what content may be promoted and under which limits.

## Rationale
Explain why promotion is necessary and safe enough.

## Effective Reference
Commit, PR, or date reference.


path: assets/github-workflows/clawcolab-validate.yml
content: name: ClawColab Validate

on:
  pull_request:
  workflow_dispatch:

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Validate policy presence and consistency
        run: |
          python skills/clawcolab/scripts/validate_policy_bundle.py \
            workspace/policy/visibility-policy.yaml \
            workspace/policy/role-policy.yaml \
            workspace/policy/approval-policy.yaml

      - name: Validate task files and pre-share readiness
        shell: bash
        run: |
          shopt -s nullglob
          files=(workspace/tasks/*.yaml)
          if [ ${#files[@]} -gt 0 ]; then
            python skills/clawcolab/scripts/validate_task_state.py "${files[@]}"
          else
            echo "No task files found"
          fi

      - name: Scan collaboration payloads for sensitive content
        shell: bash
        run: |
          shopt -s globstar nullglob
          files=(workspace/**/* sealed/INDEX.md)
          filtered=()
          for f in "${files[@]}"; do
            if [ -f "$f" ]; then filtered+=("$f"); fi
          done
          if [ ${#filtered[@]} -gt 0 ]; then
            python skills/clawcolab/scripts/validate-collab-payload.py "${filtered[@]}"
          else
            echo "No collaboration files found"
          fi

      - name: Detect claim conflicts
        shell: bash
        run: |
          shopt -s nullglob
          files=(workspace/claims/*)
          if [ ${#files[@]} -gt 0 ]; then
            python skills/clawcolab/scripts/detect_claim_conflicts.py "${files[@]}"
          else
            echo "No claim files found"
          fi


path: assets/minimal-start/PROPOSAL-001.md
content: # PROPOSAL-001

## Title
Start the first project with a narrow approved scope

## Status
pending_approval

## Visibility
shared-team

## Proposed By
bootstrap

## Scope
Define the smallest useful first milestone for this collaboration space.

## Proposed Actions
- state the project goal clearly
- keep the first milestone narrow
- avoid advanced workflow features unless they are needed immediately

## Expected Outputs
- `workspace/decisions/DECISION-001.md`

## Risks
- starting too broadly may create confusion
- unclear scope makes later coordination harder

## Requested Owner or Role
- coordinator
- human-approver

## Approval Needed
Approve the first milestone and initial project scope.


path: assets/minimal-start/DECISION-001.md
content: # DECISION-001

## Title
Initial project objective

## Status
approved

## Approved By
TBD

## Based On
- PROPOSAL-001

## Scope
Define the first approved project objective.

## Decision
TBD

## Rationale
TBD

## Effective Reference
TBD


path: assets/minimal-start/TASK-001.yaml
content: id: TASK-001
title: Define the first project objective
summary: Establish the first concrete goal for this collaboration space.
visibility: shared-team
status: open
priority: high
mode: proposal-approval
approval_required: true
owner: null
proposed_by: bootstrap
approved_by: null
eligible_roles:
  - coordinator
  - architect
dependencies: []
inputs: []
outputs:
  - workspace/proposals/PROPOSAL-001.md
  - workspace/decisions/DECISION-001.md
sealed_refs: []
risks: []
notes: |
  Keep the first task narrow. The goal is to define what this project is trying to do first.


path: assets/classification-checklist.md
content: # Classification Checklist

Run this checklist before sharing any content into a ClawColab repository.

## Questions
1. Did this content come from private local memory, private notes, or private chat?
2. Does it include secrets, tokens, credentials, local paths, machine details, or personal identifiers?
3. Can the task be completed with a summary instead of raw content?
4. If several summaries are combined, could they still reveal sensitive facts?
5. What is the minimum visibility level required: `private`, `sealed`, `shared-team`, or `public-repo`?
6. If classification is uncertain, should this be downgraded to `private` or `sealed`?

## Rule
Do not share until all six questions have been answered.


path: assets/approval-policy-template.yaml
content: version: 1
default_gate: human-approval
approval_rules:
  visibility_promotion:
    private_to_sealed: human-approval
    private_to_shared-team: human-approval
    private_to_public-repo: human-approval
    sealed_to_shared-team: human-approval
    sealed_to_public-repo: human-approval
    shared-team_to_public-repo: human-approval
  task_execution:
    high_risk: human-approval
    medium_risk: human-approval
    low_risk: auto-if-claimable
  ownership_changes:
    sensitive_task_reassignment: human-approval
    claim_conflict_resolution: human-approval
  policy_changes:
    visibility_policy: human-approval
    role_policy: human-approval
    approval_policy: human-approval
required_reviewers:
  high_risk:
    - human-approver
    - security-reviewer
  policy_change:
    - human-approver
  public_release:
    - human-approver
    - reviewer
block_merge_when:
  - sensitive_scan_fails
  - claim_conflict_unresolved
  - approval_missing
  - policy_violation_detected

claimable_requirements:
  risk_level_must_be: low
  must_not_touch_policy: true
  must_not_promote_visibility: true
  must_not_change_sensitive_ownership: true
  explicit_mode_required: true


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)