---
read_when:
    - ACP सत्र जीवनचक्र या ACPX प्रक्रिया क्लीनअप की रीफ़ैक्टरिंग
    - ACPX अनाथ प्रक्रियाओं, PID पुनः उपयोग, या मल्टी-Gateway सफाई सुरक्षा को डीबग करना
    - उत्पन्न ACP या उप-एजेंट सत्रों के लिए sessions_list दृश्यता बदलना
    - पृष्ठभूमि कार्यों, ACP सत्रों, या प्रोसेस लीज़ के लिए स्वामित्व मेटाडेटा डिज़ाइन करना
sidebarTitle: ACP lifecycle refactor
summary: ACP सत्र और ACPX प्रक्रिया स्वामित्व को स्पष्ट बनाने के लिए माइग्रेशन योजना
title: ACP जीवनचक्र रिफैक्टर
x-i18n:
    generated_at: "2026-06-29T00:05:24Z"
    model: gpt-5.5
    postprocess_version: locale-links-v1
    provider: openai
    source_hash: b7f4ee447e0b436601c68251c26c1b897a642f6a8b1886d18647b62817996792
    source_path: refactor/acp.md
    workflow: 16
---

ACP जीवनचक्र अभी काम करता है, लेकिन इसका बहुत अधिक हिस्सा बाद में अनुमानित किया जाता है।
प्रक्रिया सफाई PIDs, कमांड स्ट्रिंग, रैपर
पथ, और लाइव प्रक्रिया तालिका से स्वामित्व को फिर से बनाती है। सत्र दृश्यता
सत्र-कुंजी स्ट्रिंग और द्वितीयक `sessions.list({ spawnedBy })` लुकअप से स्वामित्व को फिर से बनाती है।
इससे संकीर्ण सुधार संभव होते हैं, लेकिन किनारी मामलों को चूकना भी आसान हो जाता है:
PID पुन: उपयोग, उद्धृत कमांड, एडाप्टर ग्रैंडचिल्ड्रेन, बहु-Gateway स्थिति रूट,
`cancel` बनाम `close`, और `tree` बनाम `all` दृश्यता सभी समान स्वामित्व नियमों को
फिर से खोजने के अलग-अलग स्थान बन जाते हैं।

यह रिफैक्टर स्वामित्व को प्रथम-श्रेणी बनाता है। लक्ष्य कोई नया ACP उत्पाद
सतह नहीं है; यह मौजूदा ACP और ACPX व्यवहार के लिए एक अधिक सुरक्षित आंतरिक अनुबंध है।

## लक्ष्य

- सफाई कभी भी किसी प्रक्रिया को सिग्नल नहीं भेजती जब तक कि वर्तमान लाइव साक्ष्य
  OpenClaw-स्वामित्व वाली लीज़ से मेल न खाए।
- `cancel`, `close`, और स्टार्टअप रीपिंग के अलग-अलग जीवनचक्र इरादे होते हैं।
- `sessions_list`, `sessions_history`, `sessions_send`, और स्थिति जांच समान
  अनुरोधकर्ता-स्वामित्व वाले सत्र मॉडल का उपयोग करते हैं।
- बहु-Gateway इंस्टॉल एक-दूसरे के ACPX रैपर रीप नहीं कर सकते।
- पुराने ACPX सत्र रिकॉर्ड माइग्रेशन के दौरान काम करते रहते हैं।
- रनटाइम Plugin-स्वामित्व वाला रहता है; कोर ACPX पैकेज विवरण नहीं सीखता।

## गैर-लक्ष्य

- ACPX को बदलना या सार्वजनिक `/acp` कमांड सतह बदलना।
- विक्रेता-विशिष्ट ACP एडाप्टर व्यवहार को कोर में ले जाना।
- उपयोगकर्ताओं से अपग्रेड से पहले स्थिति को मैन्युअल रूप से साफ करवाना।
- `cancel` को पुन: उपयोग योग्य ACP सत्र बंद करवाना।

## लक्षित मॉडल

### Gateway इंस्टेंस पहचान

हर Gateway प्रक्रिया के पास एक स्थिर रनटाइम इंस्टेंस आईडी होनी चाहिए:

```ts
type GatewayInstanceId = string;
```

इसे Gateway स्टार्टअप पर जनरेट किया जा सकता है और उस इंस्टॉल के जीवनकाल के लिए
स्थिति में स्थायी रखा जा सकता है। यह कोई सुरक्षा रहस्य नहीं है; यह एक स्वामित्व विभेदक है,
जिसका उपयोग एक Gateway की ACP प्रक्रियाओं को दूसरे Gateway की प्रक्रियाओं से भ्रमित होने से
बचाने के लिए किया जाता है।

### ACP सत्र स्वामित्व

हर शुरू किए गए ACP सत्र के पास सामान्यीकृत स्वामित्व मेटाडेटा होना चाहिए:

```ts
type AcpSessionOwner = {
  sessionKey: string;
  spawnedBy?: string;
  parentSessionKey?: string;
  ownerSessionKey: string;
  agentId: string;
  backend: "acpx";
  gatewayInstanceId: GatewayInstanceId;
  createdAt: number;
};
```

Gateway को ये फ़ील्ड उन सत्र पंक्तियों पर लौटाने चाहिए जहां वे ज्ञात हों।
दृश्यता फ़िल्टरिंग पंक्ति मेटाडेटा पर एक शुद्ध जांच होनी चाहिए:

```ts
canSeeSessionRow({
  row,
  requesterSessionKey,
  visibility,
  a2aPolicy,
});
```

यह दृश्यता जांचों से छिपे हुए द्वितीयक `sessions.list({ spawnedBy })` कॉल हटाता है।
एक शुरू किया गया क्रॉस-एजेंट ACP चाइल्ड अनुरोधकर्ता-स्वामित्व वाला है क्योंकि
पंक्ति ऐसा कहती है, न कि इसलिए कि कोई दूसरी क्वेरी संयोग से उसे खोज लेती है।

### ACPX प्रक्रिया लीज़

हर जनरेट किए गए रैपर लॉन्च को एक लीज़ रिकॉर्ड बनाना चाहिए:

```ts
type AcpxProcessLease = {
  leaseId: string;
  gatewayInstanceId: GatewayInstanceId;
  sessionKey: string;
  wrapperRoot: string;
  wrapperPath: string;
  rootPid: number;
  processGroupId?: number;
  commandHash: string;
  startedAt: number;
  state: "open" | "closing" | "closed" | "lost";
};
```

रैपर प्रक्रिया को अपने वातावरण में लीज़ आईडी और Gateway इंस्टेंस आईडी प्राप्त होनी चाहिए:

```sh
OPENCLAW_ACPX_LEASE_ID=...
OPENCLAW_GATEWAY_INSTANCE_ID=...
```

जब प्लेटफ़ॉर्म अनुमति देता है, सत्यापन को लाइव प्रक्रिया मेटाडेटा को प्राथमिकता देनी चाहिए
जिसे कमांड उद्धरण से भ्रमित नहीं किया जा सकता:

- रूट PID अभी भी मौजूद है
- लाइव रैपर पथ `wrapperRoot` के अंतर्गत है
- उपलब्ध होने पर प्रक्रिया समूह लीज़ से मेल खाता है
- पढ़े जाने योग्य होने पर वातावरण में अपेक्षित लीज़ आईडी है
- कमांड हैश या निष्पादन योग्य पथ लीज़ से मेल खाता है

यदि लाइव प्रक्रिया सत्यापित नहीं की जा सकती, तो सफाई फेल-क्लोज़्ड होती है।

## जीवनचक्र नियंत्रक

एक ACPX जीवनचक्र नियंत्रक पेश करें जो प्रक्रिया लीज़ और सफाई
नीति का स्वामी हो:

```ts
interface AcpxLifecycleController {
  ensureSession(input: AcpRuntimeEnsureInput): Promise<AcpRuntimeHandle>;
  cancelTurn(handle: AcpRuntimeHandle): Promise<void>;
  closeSession(input: {
    handle: AcpRuntimeHandle;
    discardPersistentState?: boolean;
    reason?: string;
  }): Promise<void>;
  reapStartupOrphans(): Promise<void>;
  verifyOwnedTree(lease: AcpxProcessLease): Promise<OwnedProcessTree | null>;
}
```

`cancelTurn` केवल टर्न रद्द करने का अनुरोध करता है। उसे पुन: उपयोग योग्य रैपर
या एडाप्टर प्रक्रियाओं को रीप नहीं करना चाहिए।

`closeSession` को रीप करने की अनुमति है, लेकिन केवल सत्र रिकॉर्ड लोड करने,
लीज़ लोड करने, और यह सत्यापित करने के बाद कि लाइव प्रक्रिया वृक्ष अभी भी उस
लीज़ का है।

`reapStartupOrphans` स्थिति में मौजूद खुली लीज़ से शुरू करता है। वह वंशज खोजने के लिए
प्रक्रिया तालिका का उपयोग कर सकता है, लेकिन उसे पहले मनमाने ACP-जैसे कमांड स्कैन करके
फिर यह तय नहीं करना चाहिए कि वे शायद हमारे हैं।

## रैपर अनुबंध

जनरेट किए गए रैपर छोटे रहने चाहिए। उन्हें:

- समर्थित होने पर एडाप्टर को प्रक्रिया समूह में शुरू करना चाहिए
- सामान्य समाप्ति सिग्नल प्रक्रिया समूह को अग्रेषित करने चाहिए
- पैरेंट की मृत्यु पहचाननी चाहिए
- पैरेंट की मृत्यु पर SIGTERM भेजना चाहिए, फिर SIGKILL
  फ़ॉलबैक चलने तक रैपर को जीवित रखना चाहिए
- उपलब्ध होने पर रूट PID और प्रक्रिया समूह आईडी को जीवनचक्र नियंत्रक को वापस रिपोर्ट करना चाहिए

रैपरों को सत्र नीति तय नहीं करनी चाहिए। वे केवल अपने एडाप्टर समूह के लिए स्थानीय
प्रक्रिया-वृक्ष सफाई लागू करते हैं।

## सत्र दृश्यता अनुबंध

दृश्यता को सामान्यीकृत पंक्ति स्वामित्व का उपयोग करना चाहिए:

```ts
type SessionVisibilityInput = {
  requesterSessionKey: string;
  row: {
    key: string;
    agentId: string;
    ownerSessionKey?: string;
    spawnedBy?: string;
    parentSessionKey?: string;
  };
  visibility: "self" | "tree" | "agent" | "all";
  a2aPolicy: AgentToAgentPolicy;
};
```

नियम:

- `self`: केवल अनुरोधकर्ता सत्र।
- `tree`: अनुरोधकर्ता सत्र और अनुरोधकर्ता द्वारा स्वामित्व वाली या उससे शुरू की गई पंक्तियां।
- `all`: सभी समान-एजेंट पंक्तियां, a2a-अनुमत क्रॉस-एजेंट पंक्तियां, और अनुरोधकर्ता-स्वामित्व वाली
  शुरू की गई क्रॉस-एजेंट पंक्तियां, भले ही सामान्य a2a अक्षम हो।
- `agent`: केवल समान एजेंट, जब तक कि कोई स्पष्ट स्वामी संबंध यह न कहे कि पंक्ति
  अनुरोधकर्ता की है।

इससे `tree` और `all` मोनोटोनिक बनते हैं: `all` को ऐसा स्वामित्व वाला चाइल्ड नहीं छिपाना चाहिए
जिसे `tree` दिखाएगा।

## माइग्रेशन योजना

### चरण 1: पहचान और लीज़ जोड़ें

- Gateway स्थिति में `gatewayInstanceId` जोड़ें।
- ACPX स्थिति डायरेक्टरी के अंतर्गत ACPX लीज़ स्टोर जोड़ें।
- जनरेट किए गए रैपर को शुरू करने से पहले लीज़ लिखें।
- नए ACPX सत्र रिकॉर्ड पर `leaseId` स्टोर करें।
- पुराने रिकॉर्ड के लिए मौजूदा PID और कमांड फ़ील्ड रखें।

### चरण 2: लीज़-प्रथम सफाई

- बंद करने की सफाई को पहले `leaseId` लोड करने के लिए बदलें।
- सिग्नल भेजने से पहले लीज़ के विरुद्ध लाइव प्रक्रिया स्वामित्व सत्यापित करें।
- केवल लेगेसी रिकॉर्ड के लिए वर्तमान रूट PID और रैपर-रूट फ़ॉलबैक रखें।
- सत्यापित सफाई के बाद लीज़ को `closed` चिह्नित करें।
- सफाई से पहले प्रक्रिया जा चुकी हो तो लीज़ को `lost` चिह्नित करें।

### चरण 3: लीज़-प्रथम स्टार्टअप रीपिंग

- स्टार्टअप रीपिंग खुली लीज़ स्कैन करती है।
- हर लीज़ के लिए, रूट प्रक्रिया सत्यापित करें और वंशज एकत्र करें।
- सत्यापित वृक्षों को चिल्ड्रेन-प्रथम रीप करें।
- पुराने `closed` और `lost` लीज़ को सीमित रिटेंशन विंडो के साथ समाप्त करें।
- कमांड-मार्कर स्कैनिंग को केवल अस्थायी लेगेसी फ़ॉलबैक के रूप में रखें, जहां संभव हो
  रैपर रूट और Gateway इंस्टेंस द्वारा संरक्षित।

### चरण 4: सत्र स्वामित्व पंक्तियां

- Gateway सत्र पंक्तियों में स्वामित्व मेटाडेटा जोड़ें।
- ACPX, सबएजेंट, पृष्ठभूमि-कार्य, और सत्र-स्टोर राइटरों को
  `ownerSessionKey` या `spawnedBy` भरना सिखाएं।
- सत्र दृश्यता जांचों को पंक्ति मेटाडेटा का उपयोग करने में बदलें।
- दृश्यता-समय द्वितीयक `sessions.list({ spawnedBy })` लुकअप हटाएं।

### चरण 5: लेगेसी हीयूरिस्टिक हटाएं

एक रिलीज़ विंडो के बाद:

- गैर-लेगेसी ACPX सफाई के लिए संग्रहीत रूट कमांड स्ट्रिंग पर निर्भर रहना बंद करें
- कमांड-मार्कर स्टार्टअप स्कैन हटाएं
- दृश्यता फ़ॉलबैक सूची लुकअप हटाएं
- अनुपस्थित या असत्यापनीय लीज़ के लिए रक्षात्मक फेल-क्लोज़्ड व्यवहार रखें

## परीक्षण

दो टेबल-ड्रिवन सूट जोड़ें।

प्रक्रिया जीवनचक्र सिम्युलेटर:

- PID का असंबंधित प्रक्रिया द्वारा पुन: उपयोग
- PID का दूसरे Gateway के रैपर रूट द्वारा पुन: उपयोग
- संग्रहीत रैपर कमांड शेल-उद्धृत है, लाइव `ps` कमांड नहीं है
- एडाप्टर चाइल्ड बाहर निकलता है, ग्रैंडचाइल्ड प्रक्रिया समूह में रहता है
- पैरेंट मृत्यु SIGTERM फ़ॉलबैक SIGKILL तक पहुंचता है
- प्रक्रिया सूची अनुपलब्ध
- अनुपस्थित प्रक्रिया वाली बासी लीज़
- रैपर, एडाप्टर चाइल्ड, और ग्रैंडचाइल्ड वाला स्टार्टअप अनाथ

सत्र दृश्यता मैट्रिक्स:

- `self`, `tree`, `agent`, `all`
- a2a सक्षम और अक्षम
- समान-एजेंट पंक्ति
- क्रॉस-एजेंट पंक्ति
- अनुरोधकर्ता-स्वामित्व वाली शुरू की गई क्रॉस-एजेंट ACP पंक्ति
- सैंडबॉक्स्ड अनुरोधकर्ता `tree` तक सीमित
- सूची, इतिहास, भेजना, और स्थिति क्रियाएं

महत्वपूर्ण invariant: अनुरोधकर्ता-स्वामित्व वाला शुरू किया गया चाइल्ड वहां दिखाई देता है जहां
कॉन्फ़िगर की गई दृश्यता में अनुरोधकर्ता सत्र वृक्ष शामिल है, और `all`, `tree` से
कम सक्षम नहीं है।

## संगतता नोट्स

पुराने सत्र रिकॉर्ड में `leaseId` नहीं हो सकता। उन्हें लेगेसी
फेल-क्लोज़्ड सफाई पथ का उपयोग करना चाहिए:

- लाइव रूट प्रक्रिया आवश्यक करें
- जब जनरेटेड रैपर अपेक्षित हो, तो रैपर-रूट स्वामित्व आवश्यक करें
- गैर-रैपर रूट के लिए कमांड सहमति आवश्यक करें
- केवल बासी संग्रहीत PID मेटाडेटा के आधार पर कभी सिग्नल न भेजें

यदि कोई लेगेसी रिकॉर्ड सत्यापित नहीं किया जा सकता, तो उसे अकेला छोड़ दें। स्टार्टअप लीज़ सफाई और
अगली रिलीज़ विंडो को अंततः फ़ॉलबैक से छुटकारा दिलाना चाहिए।

## सफलता मानदंड

- पुराने या बासी ACPX सत्र को बंद करने से दूसरे Gateway की प्रक्रिया खत्म नहीं हो सकती।
- पैरेंट मृत्यु जिद्दी एडाप्टर ग्रैंडचिल्ड्रेन को चलते हुए नहीं छोड़ती।
- `cancel` पुन: उपयोग योग्य सत्र बंद किए बिना सक्रिय टर्न को रोकता है।
- `sessions_list` अनुरोधकर्ता-स्वामित्व वाले क्रॉस-एजेंट ACP चिल्ड्रेन को `tree` और `all` दोनों के अंतर्गत दिखा सकता है।
- स्टार्टअप सफाई लीज़ द्वारा संचालित होती है, व्यापक कमांड-स्ट्रिंग स्कैन द्वारा नहीं।
- केंद्रित प्रक्रिया और दृश्यता मैट्रिक्स परीक्षण हर उस किनारी मामले को कवर करते हैं
  जिसके लिए पहले एकबारगी समीक्षा सुधारों की जरूरत पड़ती थी।
