Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5262c932f
|
||
|
|
6e6a89f15a
|
@@ -1,76 +0,0 @@
|
|||||||
---
|
|
||||||
name: homelab-knowledge
|
|
||||||
description: Query and maintain the shared homelab-wiki when working on homelab services, infrastructure, architecture, operations, or current service status. Use it to gather existing context before work and to keep durable knowledge synchronized after relevant changes; do not use it for unrelated software work or as a substitute for commit and PR history.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Homelab Knowledge
|
|
||||||
|
|
||||||
Use `homelab-wiki` as the shared long-lived knowledge base for people and agents. Search it directly with `rg`; do not introduce a search index, vector database, or generated copy of the wiki.
|
|
||||||
|
|
||||||
## Locate the wiki
|
|
||||||
|
|
||||||
Resolve the checkout in this order:
|
|
||||||
|
|
||||||
1. `$HOMELAB_WIKI_PATH`, when set.
|
|
||||||
2. A sibling directory named `homelab-wiki` next to the current repository.
|
|
||||||
3. `/home/panxiao81/homelab-wiki` when it exists.
|
|
||||||
|
|
||||||
If no checkout is available, report that constraint. Do not silently skip the knowledge step, clone a repository, or create a replacement wiki without the user's authorization.
|
|
||||||
|
|
||||||
Before using the wiki, read its `AGENTS.md` completely. For edits, also read `README.md` and `CONTRIBUTING.md` completely and follow any more specific instructions associated with the target page.
|
|
||||||
|
|
||||||
## Gather context
|
|
||||||
|
|
||||||
At the beginning of a homelab task:
|
|
||||||
|
|
||||||
1. Derive search terms from the component name, service aliases, hostnames, Kubernetes resources, configuration keys, error text, and task intent.
|
|
||||||
2. Use `rg -n -i` in the wiki to find candidate pages. Prefer several precise searches over reading the whole repository.
|
|
||||||
3. Follow the wiki's task index, service index, architecture constraints, source records, and verification conflicts when they are relevant.
|
|
||||||
4. Read the closest authoritative pages and their material links before making decisions. Also read the corresponding source repository README or runbook when changing an implementation.
|
|
||||||
5. Distinguish documented design, declared configuration, deployment history, live verification, and work currently in progress. Do not present one as another.
|
|
||||||
|
|
||||||
For questions about current project or service status, first obtain the maintainer's current-work and ticket context as required by the wiki, unless the conversation already provides that authorization and scope. Reading documentation does not authorize live-system inspection.
|
|
||||||
|
|
||||||
Answer read-only questions from the evidence found. Include paths or links that let the user verify important claims, and state when evidence may be stale or conflicting.
|
|
||||||
|
|
||||||
## Maintain knowledge after changes
|
|
||||||
|
|
||||||
For any code, configuration, infrastructure, or operational change, perform a documentation-impact check before declaring the task complete.
|
|
||||||
|
|
||||||
Update the wiki in the same task when the change affects durable knowledge such as:
|
|
||||||
|
|
||||||
- service purpose, lifecycle, entry point, authentication, permissions, dependencies, or first-use path;
|
|
||||||
- architecture boundaries or accepted constraints;
|
|
||||||
- deployment ownership or persistent operating behavior;
|
|
||||||
- troubleshooting, recovery, verification, or maintenance procedures;
|
|
||||||
- the addition, replacement, or retirement of a service.
|
|
||||||
|
|
||||||
Keep one-time progress, implementation narration, and release-by-release history in commits, PRs, or tickets. Do not copy them into the wiki unless they change a durable stage summary. Implementation-specific parameters may remain in the source repository README or runbook when the wiki convention says to link rather than duplicate them.
|
|
||||||
|
|
||||||
When editing:
|
|
||||||
|
|
||||||
1. Inspect both the source-repository diff and the wiki working tree before writing. Preserve unrelated user changes in both repositories.
|
|
||||||
2. Update the page closest to the fact first, then only the navigation, indexes, constraints, or verification records that the wiki rules require.
|
|
||||||
3. Preserve evidence metadata. Never advance `last_verified` without performing the stated live verification; ordinary review may update only fields permitted by the wiki.
|
|
||||||
4. Link related source commits, PRs, or paths when available. Clearly mark uncommitted sources and unfinished cross-repository synchronization.
|
|
||||||
5. Record conflicts rather than resolving them by assumption. Ask before live inspection or before choosing among materially conflicting current-state claims.
|
|
||||||
6. Keep credentials, tokens, private keys, Terraform state, secret values, and sensitive command output out of documentation. Never read or copy known sensitive files merely to improve the wiki.
|
|
||||||
|
|
||||||
Wiki edits are a separate repository change. Do not commit, push, open a PR, or modify a live system unless the user has authorized that action.
|
|
||||||
|
|
||||||
## Verify and report
|
|
||||||
|
|
||||||
After editing the wiki, run from its root:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 scripts/check_docs.py
|
|
||||||
git diff --check
|
|
||||||
```
|
|
||||||
|
|
||||||
If the checker itself changed, also run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 -m unittest discover -s tests -v
|
|
||||||
```
|
|
||||||
|
|
||||||
In the final response, report source-repository changes and wiki changes separately, including validation performed and anything still awaiting verification or cross-repository linkage. If no wiki update was needed, state the concrete reason; do not merely say that documentation was unaffected.
|
|
||||||
@@ -34,16 +34,6 @@
|
|||||||
- Proxmox VM 的北向管理不能假定单一 API 覆盖完整生命周期。允许按能力组合 Proxmox API、节点
|
- Proxmox VM 的北向管理不能假定单一 API 覆盖完整生命周期。允许按能力组合 Proxmox API、节点
|
||||||
上的受限强类型 Agent/CLI 操作和 ManualTask;节点 Agent 不得退化为无版本契约的任意远程 shell。
|
上的受限强类型 Agent/CLI 操作和 ManualTask;节点 Agent 不得退化为无版本契约的任意远程 shell。
|
||||||
- 所有 controller 必须考虑幂等、observe、finalizer、conditions、删除策略和恢复行为。
|
- 所有 controller 必须考虑幂等、observe、finalizer、conditions、删除策略和恢复行为。
|
||||||
- Ayatori 会联动 Kubernetes API、虚拟化、存储、网络及其他外部控制面;集成测试是功能完成
|
|
||||||
标准的一部分,不得仅凭 fake client 或 mock 测试宣告 controller、adapter 或生命周期变更完成。
|
|
||||||
- 测试应按风险分层:纯领域规则使用快速单元测试;API schema、CEL、status subresource、
|
|
||||||
watch/cache、owner reference 和 reconcile 事件链使用 envtest;需要 scheduler、kubelet、网络、
|
|
||||||
存储或真实后端行为的路径在 Dev 集群或对应后端环境执行端到端测试。
|
|
||||||
- fake client 适合穷举状态机和错误分支,但它不会完整执行 API server defaulting、validation、
|
|
||||||
resourceVersion、garbage collection 或新版 Kubernetes 约束;涉及这些语义时必须增加真实 API
|
|
||||||
server 测试。跨 adapter 的共同契约应使用同一套 contract tests,避免各实现产生语义漂移。
|
|
||||||
- 集成测试必须覆盖正常路径以及幂等重试、controller 重启、依赖稍后出现、删除/finalizer、
|
|
||||||
后端结果不确定和并发竞态等恢复路径;无法在当前层测试的部分要明确记录由哪一层验证。
|
|
||||||
- Secret、token、kubeconfig 及具体生产凭据不得提交到仓库。
|
- Secret、token、kubeconfig 及具体生产凭据不得提交到仓库。
|
||||||
- `deploy/dev/` 与 `deploy/prod/` 使用相同制品;生产版本只通过 promotion 更新。
|
- `deploy/dev/` 与 `deploy/prod/` 使用相同制品;生产版本只通过 promotion 更新。
|
||||||
- 内部专用不构成降低测试、版本、恢复、安全和可审计要求的理由。
|
- 内部专用不构成降低测试、版本、恢复、安全和可审计要求的理由。
|
||||||
|
|||||||
+2
-3
@@ -51,10 +51,9 @@
|
|||||||
- 用户集群只暴露 worker node,控制面完全由平台托管。
|
- 用户集群只暴露 worker node,控制面完全由平台托管。
|
||||||
- 本节记录候选实现边界,不构成路线图承诺。
|
- 本节记录候选实现边界,不构成路线图承诺。
|
||||||
|
|
||||||
## 后续 Compute 验收场景
|
## 首个业务里程碑
|
||||||
|
|
||||||
Database 等首批资源优先落地。Compute 开始实施后,以 Laptop Rebuild Readiness 验证节点
|
完成 Laptop Rebuild Readiness:
|
||||||
生命周期与恢复能力;该场景不作为首批 Database、LoadBalancer 或 Bucket 的交付前置条件:
|
|
||||||
|
|
||||||
1. 临时节点加入。
|
1. 临时节点加入。
|
||||||
2. laptop 上的 workload 被重建、迁移或形成可执行人工任务。
|
2. laptop 上的 workload 被重建、迁移或形成可执行人工任务。
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ func TestInstanceAcceptsExtensionObservationForCurrentTarget(t *testing.T) {
|
|||||||
target := value.Target()
|
target := value.Target()
|
||||||
snapshot := value.Snapshot()
|
snapshot := value.Snapshot()
|
||||||
|
|
||||||
if err := value.ObserveExtensions(target, instance.ObserveExtensionSupport([]string{testTrigram})); err != nil {
|
if err := value.ObserveExtensions(target, instance.ObserveExtensionSupport([]string{"pg_trgm"})); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if got := value.CheckExtensions(instance.NewExtensionSet([]string{testTrigram})); got.Decision != instance.ExtensionsAccepted {
|
if got := value.CheckExtensions(instance.NewExtensionSet([]string{"pg_trgm"})); got.Decision != instance.ExtensionsAccepted {
|
||||||
t.Fatalf("CheckExtensions() = %v, want accepted", got)
|
t.Fatalf("CheckExtensions() = %v, want accepted", got)
|
||||||
}
|
}
|
||||||
if value.Snapshot() != snapshot {
|
if value.Snapshot() != snapshot {
|
||||||
@@ -52,20 +52,20 @@ func TestInstanceRejectsExtensionObservationForDifferentTarget(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := value.ObserveExtensions(different, instance.ObserveExtensionSupport([]string{testTrigram})); err == nil {
|
if err := value.ObserveExtensions(different, instance.ObserveExtensionSupport([]string{"pg_trgm"})); err == nil {
|
||||||
t.Fatal("observation for a different target was accepted")
|
t.Fatal("observation for a different target was accepted")
|
||||||
}
|
}
|
||||||
if got := value.CheckExtensions(instance.NewExtensionSet([]string{testTrigram})); got.Decision != instance.ExtensionSupportUnobserved {
|
if got := value.CheckExtensions(instance.NewExtensionSet([]string{"pg_trgm"})); got.Decision != instance.ExtensionSupportUnobserved {
|
||||||
t.Fatalf("rejected observation changed support: %v", got)
|
t.Fatalf("rejected observation changed support: %v", got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInstanceClearsExtensionObservationAcrossLifecycleBoundaries(t *testing.T) {
|
func TestInstanceClearsExtensionObservationAcrossLifecycleBoundaries(t *testing.T) {
|
||||||
requested := instance.NewExtensionSet([]string{testTrigram})
|
requested := instance.NewExtensionSet([]string{"pg_trgm"})
|
||||||
|
|
||||||
t.Run("validation", func(t *testing.T) {
|
t.Run("validation", func(t *testing.T) {
|
||||||
value := lifecycleInstance(t, instance.Snapshot{Phase: instance.PhaseReady}, false)
|
value := lifecycleInstance(t, instance.Snapshot{Phase: instance.PhaseReady}, false)
|
||||||
if err := value.ObserveExtensions(value.Target(), instance.ObserveExtensionSupport([]string{testTrigram})); err != nil {
|
if err := value.ObserveExtensions(value.Target(), instance.ObserveExtensionSupport([]string{"pg_trgm"})); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := value.BeginValidation(); err != nil {
|
if err := value.BeginValidation(); err != nil {
|
||||||
@@ -78,7 +78,7 @@ func TestInstanceClearsExtensionObservationAcrossLifecycleBoundaries(t *testing.
|
|||||||
|
|
||||||
t.Run("deletion", func(t *testing.T) {
|
t.Run("deletion", func(t *testing.T) {
|
||||||
value := lifecycleInstance(t, instance.Snapshot{Phase: instance.PhaseReady}, true)
|
value := lifecycleInstance(t, instance.Snapshot{Phase: instance.PhaseReady}, true)
|
||||||
if err := value.ObserveExtensions(value.Target(), instance.ObserveExtensionSupport([]string{testTrigram})); err == nil {
|
if err := value.ObserveExtensions(value.Target(), instance.ObserveExtensionSupport([]string{"pg_trgm"})); err == nil {
|
||||||
t.Fatal("deleting instance accepted a new observation")
|
t.Fatal("deleting instance accepted a new observation")
|
||||||
}
|
}
|
||||||
if err := value.BeginDeletion(); err != nil {
|
if err := value.BeginDeletion(); err != nil {
|
||||||
@@ -92,8 +92,8 @@ func TestInstanceClearsExtensionObservationAcrossLifecycleBoundaries(t *testing.
|
|||||||
|
|
||||||
func TestInstanceCanExplicitlyInvalidateExtensionObservation(t *testing.T) {
|
func TestInstanceCanExplicitlyInvalidateExtensionObservation(t *testing.T) {
|
||||||
value := lifecycleInstance(t, instance.Snapshot{Phase: instance.PhaseValidating}, false)
|
value := lifecycleInstance(t, instance.Snapshot{Phase: instance.PhaseValidating}, false)
|
||||||
requested := instance.NewExtensionSet([]string{testTrigram})
|
requested := instance.NewExtensionSet([]string{"pg_trgm"})
|
||||||
if err := value.ObserveExtensions(value.Target(), instance.ObserveExtensionSupport([]string{testTrigram})); err != nil {
|
if err := value.ObserveExtensions(value.Target(), instance.ObserveExtensionSupport([]string{"pg_trgm"})); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := value.ObserveExtensions(value.Target(), instance.ExtensionSupport{}); err != nil {
|
if err := value.ObserveExtensions(value.Target(), instance.ExtensionSupport{}); err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user