Skip to content
Open
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
3 changes: 3 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Displays the "Sponsor" button on this repository.
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository
github: [ix-infrastructure]
156 changes: 156 additions & 0 deletions .github/scripts/copyright-headers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Copyright 2026 Ix Infrastructure Inc.

"""Enforce the Ix Infrastructure copyright header on every source file.

python3 .github/scripts/copyright-headers.py # check, exit 1 on misses
python3 .github/scripts/copyright-headers.py --fix # insert the missing ones

Run from the repository root. CI runs the check; contributors run --fix.

Deliberately NOT covered, because a header there is wrong rather than missing:
* test fixtures — parser tests snapshot their output including line numbers,
so a header shifts every symbol down a line and breaks them;
* anything the repo marks linguist-generated in .gitattributes — regenerated
by tooling (the header would be clobbered) or vendored from upstream, whose
copyright is not ours to claim;
* committed build output and dependencies (dist/, node_modules/, ...).

A file type absent from the tables below is not checked. Adding a language to
the repo means adding its comment syntax here.
"""

import os
import re
import subprocess
import sys

HEADER = "Copyright 2026 Ix Infrastructure Inc."

SLASH = {".ts", ".tsx", ".mts", ".cts", ".mjs", ".cjs", ".js", ".jsx", ".scala", ".sc",
".java", ".go", ".rs", ".c", ".h", ".cc", ".cpp", ".hpp", ".swift", ".kt"}
HASH = {".sh", ".bash", ".zsh", ".ps1", ".psm1", ".py", ".rb", ".pl"}
CMD = {".cmd", ".bat"}

EXCLUDE_RE = re.compile(
r"(^|/)(node_modules|dist|build|out|target|vendor|third_party|\.yarn|coverage)(/|$)"
r"|(^|/)(test-)?fixtures?(/|$)"
r"|(^|/)__fixtures__(/|$)"
r"|\.min\.(js|mjs|cjs)$"
r"|\.d\.ts$"
)

SHEBANG_RE = re.compile(r"^#!")
CODING_RE = re.compile(r"^#.*coding[:=]")
ECHOOFF_RE = re.compile(r"^\s*@echo\s+off", re.I)


def comment(ext):
if ext in SLASH:
return "// " + HEADER
if ext in HASH:
return "# " + HEADER
if ext in CMD:
return "@REM " + HEADER
return None


def tracked_files():
out = subprocess.run(["git", "ls-files"], capture_output=True, text=True, check=True).stdout
return [p for p in out.splitlines() if p]


def linguist_generated(paths):
"""Files the repo itself declares generated. Let git do the glob matching."""
if not paths:
return set()
proc = subprocess.run(["git", "check-attr", "--stdin", "linguist-generated"],
input="\n".join(paths), capture_output=True, text=True)
return {line.rsplit(": linguist-generated:", 1)[0]
for line in proc.stdout.splitlines() if line.endswith(": set")}


def insert_at(lines, ext):
"""Index the header goes at, keeping order-sensitive first lines in place."""
if not lines:
return 0
if ext in CMD:
# `@echo off` must stay first or the REM echoes to the console
return 1 if ECHOOFF_RE.match(lines[0]) else 0
if SHEBANG_RE.match(lines[0]):
if ext == ".py" and len(lines) > 1 and CODING_RE.match(lines[1]):
return 2
return 1
if ext == ".py" and CODING_RE.match(lines[0]):
return 1
return 0


def main(fix):
files = tracked_files()
generated = linguist_generated(files)
missing, wrong = [], []

for rel in files:
ext = os.path.splitext(rel)[1]
line = comment(ext)
if line is None or EXCLUDE_RE.search(rel) or rel in generated:
continue
if not os.path.isfile(rel) or os.path.islink(rel):
continue
with open(rel, "r", encoding="utf-8", errors="surrogateescape", newline="") as fh:
text = fh.read()
if not text.strip():
continue
lines = text.split("\n")
head = [candidate.rstrip("\r").rstrip() for candidate in lines[:5]]
if line in head:
continue
if any("Copyright" in candidate for candidate in head):
# A copyright line, but not ours verbatim — a stale spelling of the
# entity, or someone else's claim. Never auto-"fixed": inserting a
# second header would leave the file asserting two owners.
wrong.append(rel)
continue
missing.append(rel)
if fix:
nl_crlf = "\r\n" in text.split("\n", 1)[0] + "\n"
block = [line, ""]
if nl_crlf:
block = [b + "\r" for b in block]
at = insert_at([candidate.rstrip("\r") for candidate in lines], ext)
lines[at:at] = block
with open(rel, "w", encoding="utf-8", errors="surrogateescape", newline="") as fh:
fh.write("\n".join(lines))

if not missing and not wrong:
print(f"All source files carry the header: {HEADER}")
return 0

if wrong:
print(f"{len(wrong)} source file(s) carry a copyright line that is not"
f' exactly "{HEADER}":\n')
for w in wrong:
print(f" {w}")
print("\nFix these by hand — --fix will not touch them, because inserting a"
"\nsecond header would leave the file naming two owners.\n")

if missing:
if fix:
print(f"Added the header to {len(missing)} file(s):")
for m in missing:
print(f" {m}")
else:
print(f"{len(missing)} source file(s) are missing the copyright header:\n")
for m in missing:
print(f" {m}")
print(f'\nEvery source file must start with "{HEADER}"'
" in that language's comment syntax.\nFix them all with:\n"
"\n python3 .github/scripts/copyright-headers.py --fix\n")

if fix and not wrong:
return 0
return 1


if __name__ == "__main__":
sys.exit(main("--fix" in sys.argv))
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

# Every source file must carry the copyright line. In this job rather than
# a workflow of its own: the ruleset requires exactly one status check,
# `CI Passed`, and `test` is in its `needs` — a check in any other
# workflow reports on the PR and gates nothing. Toolchain-free (stdlib
# python3 is preinstalled; the script shells out only to git).
- name: Copyright headers on every source file
run: python3 .github/scripts/copyright-headers.py
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: latest
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright [yyyy] [name of copyright owner]
Copyright 2026 Ix Infrastructure Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ix-opencode-plugin

[![Sponsor](https://img.shields.io/badge/sponsor-%E2%9D%A4-db61a2)](https://github.com/sponsors/ix-infrastructure)

An OpenCode plugin that brings [Ix Memory](https://github.com/ix-infrastructure/Ix)'s graph-first reasoning into OpenCode as a native cognitive layer.

OpenCode + Ix = reasoning engine + persistent code knowledge graph. Skills are cognitive abstractions — not CLI wrappers — that start with cheap graph signals before reading source, and stop early when the question is answered.
Expand Down
2 changes: 2 additions & 0 deletions install.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Copyright 2026 Ix Infrastructure Inc.

# install.ps1 — ix-opencode-plugin installer for Windows
#
# Usage:
Expand Down
2 changes: 2 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env bash
# Copyright 2026 Ix Infrastructure Inc.

# install.sh — ix-opencode-plugin installer
#
# Usage:
Expand Down
2 changes: 2 additions & 0 deletions plugins/ix-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-plugin.ts — OpenCode plugin entry point (v1.4.2 format)
*
Expand Down
2 changes: 2 additions & 0 deletions runtime/cli.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

import { $ } from "bun";

/**
Expand Down
2 changes: 2 additions & 0 deletions runtime/client.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* Ix Core Runtime HTTP client.
*
Expand Down
2 changes: 2 additions & 0 deletions runtime/llm.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix `--format llm` fast-path, gated on the installed CLI's version.
*
Expand Down
2 changes: 2 additions & 0 deletions runtime/secrets.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* Secret detection and redaction for Ix runtime payloads.
*
Expand Down
2 changes: 2 additions & 0 deletions tests/llm.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* The `--format llm` gate.
*
Expand Down
2 changes: 2 additions & 0 deletions tests/tools.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* OpenCodeToolContractParity + RuntimeUnavailableFallback + BunCompatibility
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-decide.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-decide — pre-edit policy gate
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-docs-tool.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-docs-tool — doc/context summary retrieval
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-explain.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-explain — symbol deep explanation
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-health.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-health — CLI and graph availability probe
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-history.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-history — revision and history lookup
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-impact.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-impact — blast radius analysis
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-ingest.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-ingest — ingest status and trigger
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-inventory.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-inventory — enumerate files or symbols within a path scope
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-locate.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-locate — text / semantic search
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-map.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-map — architectural map and subsystem overview
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-neighbors.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-neighbors — neighborhood traversal
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-query.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-query — graph entity lookup
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-rank.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-rank — rank symbols by a graph metric
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-smells.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-smells — architecture smell detection
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-stats.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-stats — graph-wide statistics
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-subsystems.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-subsystems — list graph-derived subsystems
*
Expand Down
2 changes: 2 additions & 0 deletions tools/ix-trace.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright 2026 Ix Infrastructure Inc.

/**
* ix-trace — execution path tracing
*
Expand Down